From f51d753f81c0862e18af48d701a57128572883ed Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 3 Jun 2022 14:37:05 +0200 Subject: drm/etnaviv: print offender task information on hangcheck recovery Track the pid per submit, so we can print the name and cmdline of the task which submitted the batch that caused the gpu to hang. Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 1 + drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 6 ++++++ drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 18 +++++++++++++++++- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 2 +- drivers/gpu/drm/etnaviv/etnaviv_sched.c | 2 +- 5 files changed, 26 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index 63688e6e4580..baa81cbf701a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -96,6 +96,7 @@ struct etnaviv_gem_submit { int out_fence_id; struct list_head node; /* GPU active submit list */ struct etnaviv_cmdbuf cmdbuf; + struct pid *pid; /* submitting process */ bool runtime_resumed; u32 exec_state; u32 flags; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 1ac916b24891..1491159d0d20 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -399,6 +399,9 @@ static void submit_cleanup(struct kref *kref) mutex_unlock(&submit->gpu->fence_lock); dma_fence_put(submit->out_fence); } + + put_pid(submit->pid); + kfree(submit->pmrs); kfree(submit); } @@ -422,6 +425,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, struct sync_file *sync_file = NULL; struct ww_acquire_ctx ticket; int out_fence_fd = -1; + struct pid *pid = get_pid(task_pid(current)); void *stream; int ret; @@ -519,6 +523,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, goto err_submit_ww_acquire; } + submit->pid = pid; + ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf, ALIGN(args->stream_size, 8) + 8); if (ret) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 37018bc55810..7d9bf4673e2d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -1045,12 +1045,28 @@ pm_put: } #endif -void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu) +void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit) { + struct etnaviv_gpu *gpu = submit->gpu; + char *comm = NULL, *cmd = NULL; + struct task_struct *task; unsigned int i; dev_err(gpu->dev, "recover hung GPU!\n"); + task = get_pid_task(submit->pid, PIDTYPE_PID); + if (task) { + comm = kstrdup(task->comm, GFP_KERNEL); + cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL); + put_task_struct(task); + } + + if (comm && cmd) + dev_err(gpu->dev, "offending task: %s (%s)\n", comm, cmd); + + kfree(cmd); + kfree(comm); + if (pm_runtime_get_sync(gpu->dev) < 0) goto pm_put; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 85eddd492774..b3a0941d56fd 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -168,7 +168,7 @@ bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu); int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m); #endif -void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu); +void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit); void etnaviv_gpu_retire(struct etnaviv_gpu *gpu); int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu, u32 fence, struct drm_etnaviv_timespec *timeout); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index 72e2553fbc98..d29f467eee13 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -67,7 +67,7 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job /* get the GPU back into the init state */ etnaviv_core_dump(submit); - etnaviv_gpu_recover_hang(gpu); + etnaviv_gpu_recover_hang(submit); drm_sched_resubmit_jobs(&gpu->sched); -- cgit v1.2.3 From 6cffb1c27f2d05047c7f569c425fd56d11ae89b2 Mon Sep 17 00:00:00 2001 From: "T.J. Mercier" Date: Wed, 6 Jul 2022 18:29:24 +0000 Subject: drm/etnaviv: Remove duplicate call to drm_gem_free_mmap_offset The docs explicitly say the drm_gem_object_release function already calls this, and this does not appear to be a prerequisite for the call to etnaviv_gem_ops.release. Signed-off-by: T.J. Mercier Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index cc386f8a7116..ecb828e4e156 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -504,7 +504,6 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj) kfree(mapping); } - drm_gem_free_mmap_offset(obj); etnaviv_obj->ops->release(etnaviv_obj); drm_gem_object_release(obj); -- cgit v1.2.3 From 5a40837debaa9dcc71765d32ce1a15be068b6cc2 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 14 Jul 2022 12:31:42 +0200 Subject: drm/etnaviv: move idle mapping reaping into separate function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same logic is already used in two different places and now it will also be needed outside of the compilation unit, so split it into a separate function. Cc: stable@vger.kernel.org # 5.19 Signed-off-by: Lucas Stach Reviewed-by: Guido Günther --- drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 23 +++++++++++++++-------- drivers/gpu/drm/etnaviv/etnaviv_mmu.h | 1 + 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index dc1aa738c4f1..55479cb8b1ac 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -135,6 +135,19 @@ static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context, drm_mm_remove_node(&mapping->vram_node); } +void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping) +{ + struct etnaviv_iommu_context *context = mapping->context; + + lockdep_assert_held(&context->lock); + WARN_ON(mapping->use); + + etnaviv_iommu_remove_mapping(context, mapping); + etnaviv_iommu_context_put(mapping->context); + mapping->context = NULL; + list_del_init(&mapping->mmu_node); +} + static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context, struct drm_mm_node *node, size_t size) { @@ -202,10 +215,7 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context, * this mapping. */ list_for_each_entry_safe(m, n, &list, scan_node) { - etnaviv_iommu_remove_mapping(context, m); - etnaviv_iommu_context_put(m->context); - m->context = NULL; - list_del_init(&m->mmu_node); + etnaviv_iommu_reap_mapping(m); list_del_init(&m->scan_node); } @@ -257,10 +267,7 @@ static int etnaviv_iommu_insert_exact(struct etnaviv_iommu_context *context, } list_for_each_entry_safe(m, n, &scan_list, scan_node) { - etnaviv_iommu_remove_mapping(context, m); - etnaviv_iommu_context_put(m->context); - m->context = NULL; - list_del_init(&m->mmu_node); + etnaviv_iommu_reap_mapping(m); list_del_init(&m->scan_node); } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h index e4a0b7d09c2e..c01a147f0dfd 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h @@ -91,6 +91,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context, struct etnaviv_vram_mapping *mapping, u64 va); void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context, struct etnaviv_vram_mapping *mapping); +void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping); int etnaviv_iommu_get_suballoc_va(struct etnaviv_iommu_context *ctx, struct etnaviv_vram_mapping *mapping, -- cgit v1.2.3 From 332f847212e43d584019a8264895f25cf92aa647 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 14 Jul 2022 12:31:43 +0200 Subject: drm/etnaviv: reap idle mapping if it doesn't match the softpin address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a idle BO, which is held open by another process, gets freed by userspace and subsequently referenced again by e.g. importing it again, userspace may assign a different softpin VA than the last time around. As the kernel GEM object still exists, we likely have a idle mapping with the old VA still cached, if it hasn't been reaped in the meantime. As the context matches, we then simply try to resurrect this mapping by increasing the refcount. As the VA in this mapping does not match the new softpin address, we consequently fail the otherwise valid submit. Instead of failing, reap the idle mapping. Cc: stable@vger.kernel.org # 5.19 Signed-off-by: Lucas Stach Reviewed-by: Guido Günther --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index ecb828e4e156..d45bf0368339 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -258,7 +258,12 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get( if (mapping->use == 0) { mutex_lock(&mmu_context->lock); if (mapping->context == mmu_context) - mapping->use += 1; + if (va && mapping->iova != va) { + etnaviv_iommu_reap_mapping(mapping); + mapping = NULL; + } else { + mapping->use += 1; + } else mapping = NULL; mutex_unlock(&mmu_context->lock); -- cgit v1.2.3 From 90cb380f9ceb811059340d06ff5fd0c0e93ecbe1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 9 Sep 2022 11:20:23 +0200 Subject: hwspinlock: qcom: correct MMIO max register for newer SoCs Newer ARMv8 Qualcomm SoCs using 0x1000 register stride have maximum register 0x20000 (32 mutexes * 0x1000). Fixes: 7a1e6fb1c606 ("hwspinlock: qcom: Allow mmio usage in addition to syscon") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220909092035.223915-4-krzysztof.kozlowski@linaro.org --- drivers/hwspinlock/qcom_hwspinlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwspinlock/qcom_hwspinlock.c b/drivers/hwspinlock/qcom_hwspinlock.c index 80ea45b3a815..9734e149d981 100644 --- a/drivers/hwspinlock/qcom_hwspinlock.c +++ b/drivers/hwspinlock/qcom_hwspinlock.c @@ -121,7 +121,7 @@ static const struct regmap_config tcsr_mutex_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = 0x40000, + .max_register = 0x20000, .fast_io = true, }; -- cgit v1.2.3 From 5d4753f741d824e04e7ba46f46ec016be120f383 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 9 Sep 2022 11:20:24 +0200 Subject: hwspinlock: qcom: add support for MMIO on older SoCs Older Qualcomm SoCs have TCSR mutex registers with 0x80 stride, instead of 0x1000. Add dedicated compatibles and regmap for such case. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220909092035.223915-5-krzysztof.kozlowski@linaro.org --- drivers/hwspinlock/qcom_hwspinlock.c | 42 +++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/hwspinlock/qcom_hwspinlock.c b/drivers/hwspinlock/qcom_hwspinlock.c index 9734e149d981..9cf186362ae2 100644 --- a/drivers/hwspinlock/qcom_hwspinlock.c +++ b/drivers/hwspinlock/qcom_hwspinlock.c @@ -22,6 +22,7 @@ struct qcom_hwspinlock_of_data { u32 offset; u32 stride; + const struct regmap_config *regmap_config; }; static int qcom_hwspinlock_trylock(struct hwspinlock *lock) @@ -73,15 +74,42 @@ static const struct qcom_hwspinlock_of_data of_sfpb_mutex = { .stride = 0x4, }; -/* All modern platform has offset 0 and stride of 4k */ +static const struct regmap_config tcsr_msm8226_mutex_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1000, + .fast_io = true, +}; + +static const struct qcom_hwspinlock_of_data of_msm8226_tcsr_mutex = { + .offset = 0, + .stride = 0x80, + .regmap_config = &tcsr_msm8226_mutex_config, +}; + +static const struct regmap_config tcsr_mutex_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x20000, + .fast_io = true, +}; + static const struct qcom_hwspinlock_of_data of_tcsr_mutex = { .offset = 0, .stride = 0x1000, + .regmap_config = &tcsr_mutex_config, }; static const struct of_device_id qcom_hwspinlock_of_match[] = { { .compatible = "qcom,sfpb-mutex", .data = &of_sfpb_mutex }, { .compatible = "qcom,tcsr-mutex", .data = &of_tcsr_mutex }, + { .compatible = "qcom,apq8084-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, + { .compatible = "qcom,ipq6018-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, + { .compatible = "qcom,msm8226-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, + { .compatible = "qcom,msm8974-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, + { .compatible = "qcom,msm8994-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, { } }; MODULE_DEVICE_TABLE(of, qcom_hwspinlock_of_match); @@ -117,14 +145,6 @@ static struct regmap *qcom_hwspinlock_probe_syscon(struct platform_device *pdev, return regmap; } -static const struct regmap_config tcsr_mutex_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x20000, - .fast_io = true, -}; - static struct regmap *qcom_hwspinlock_probe_mmio(struct platform_device *pdev, u32 *offset, u32 *stride) { @@ -133,6 +153,8 @@ static struct regmap *qcom_hwspinlock_probe_mmio(struct platform_device *pdev, void __iomem *base; data = of_device_get_match_data(dev); + if (!data->regmap_config) + return ERR_PTR(-EINVAL); *offset = data->offset; *stride = data->stride; @@ -141,7 +163,7 @@ static struct regmap *qcom_hwspinlock_probe_mmio(struct platform_device *pdev, if (IS_ERR(base)) return ERR_CAST(base); - return devm_regmap_init_mmio(dev, base, &tcsr_mutex_config); + return devm_regmap_init_mmio(dev, base, data->regmap_config); } static int qcom_hwspinlock_probe(struct platform_device *pdev) -- cgit v1.2.3 From cc7d3fb446a91f24978a6aa59cbb578f92e22242 Mon Sep 17 00:00:00 2001 From: Doug Brown Date: Sat, 10 Sep 2022 13:29:38 -0700 Subject: drm/etnaviv: add missing quirks for GC300 The GC300's features register doesn't specify that a 2D pipe is available, and like the GC600, its idle register reports zero bits where modules aren't present. Signed-off-by: Doug Brown Reviewed-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 7d9bf4673e2d..a96392c2dd02 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -416,6 +416,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) if (gpu->identity.model == chipModel_GC700) gpu->identity.features &= ~chipFeatures_FAST_CLEAR; + /* These models/revisions don't have the 2D pipe bit */ + if ((gpu->identity.model == chipModel_GC500 && + gpu->identity.revision <= 2) || + gpu->identity.model == chipModel_GC300) + gpu->identity.features |= chipFeatures_PIPE_2D; + if ((gpu->identity.model == chipModel_GC500 && gpu->identity.revision < 2) || (gpu->identity.model == chipModel_GC300 && @@ -449,8 +455,9 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5); } - /* GC600 idle register reports zero bits where modules aren't present */ - if (gpu->identity.model == chipModel_GC600) + /* GC600/300 idle register reports zero bits where modules aren't present */ + if (gpu->identity.model == chipModel_GC600 || + gpu->identity.model == chipModel_GC300) gpu->idle_mask = VIVS_HI_IDLE_STATE_TX | VIVS_HI_IDLE_STATE_RA | VIVS_HI_IDLE_STATE_SE | -- cgit v1.2.3 From 61a6920bb604df3a0e389a2a9479e1e233e4461d Mon Sep 17 00:00:00 2001 From: Doug Brown Date: Sat, 10 Sep 2022 13:29:39 -0700 Subject: drm/etnaviv: fix power register offset on GC300 Older GC300 revisions have their power registers at an offset of 0x200 rather than 0x100. Add new gpu_read_power and gpu_write_power functions to encapsulate accesses to the power addresses and fix the addresses. Signed-off-by: Doug Brown Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_dump.c | 7 ++++++- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 20 ++++++++++---------- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 21 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c index f418e0b75772..44b5f3c35aab 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c @@ -83,10 +83,15 @@ static void etnaviv_core_dump_registers(struct core_dump_iterator *iter, { struct etnaviv_dump_registers *reg = iter->data; unsigned int i; + u32 read_addr; for (i = 0; i < ARRAY_SIZE(etnaviv_dump_registers); i++, reg++) { + read_addr = etnaviv_dump_registers[i]; + if (read_addr >= VIVS_PM_POWER_CONTROLS && + read_addr <= VIVS_PM_PULSE_EATER) + read_addr = gpu_fix_power_address(gpu, read_addr); reg->reg = cpu_to_le32(etnaviv_dump_registers[i]); - reg->value = cpu_to_le32(gpu_read(gpu, etnaviv_dump_registers[i])); + reg->value = cpu_to_le32(gpu_read(gpu, read_addr)); } etnaviv_core_dump_header(iter, ETDUMP_BUF_REG, reg); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index a96392c2dd02..ed2f9c8f288c 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -590,7 +590,7 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu) u32 pmc, ppc; /* enable clock gating */ - ppc = gpu_read(gpu, VIVS_PM_POWER_CONTROLS); + ppc = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS); ppc |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING; /* Disable stall module clock gating for 4.3.0.1 and 4.3.0.2 revs */ @@ -598,9 +598,9 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu) gpu->identity.revision == 0x4302) ppc |= VIVS_PM_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING; - gpu_write(gpu, VIVS_PM_POWER_CONTROLS, ppc); + gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, ppc); - pmc = gpu_read(gpu, VIVS_PM_MODULE_CONTROLS); + pmc = gpu_read_power(gpu, VIVS_PM_MODULE_CONTROLS); /* Disable PA clock gating for GC400+ without bugfix except for GC420 */ if (gpu->identity.model >= chipModel_GC400 && @@ -635,7 +635,7 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu) pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ; pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ; - gpu_write(gpu, VIVS_PM_MODULE_CONTROLS, pmc); + gpu_write_power(gpu, VIVS_PM_MODULE_CONTROLS, pmc); } void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch) @@ -695,11 +695,11 @@ static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu) (gpu->identity.features & chipFeatures_PIPE_3D)) { /* Performance fix: disable internal DFS */ - pulse_eater = gpu_read(gpu, VIVS_PM_PULSE_EATER); + pulse_eater = gpu_read_power(gpu, VIVS_PM_PULSE_EATER); pulse_eater |= BIT(18); } - gpu_write(gpu, VIVS_PM_PULSE_EATER, pulse_eater); + gpu_write_power(gpu, VIVS_PM_PULSE_EATER, pulse_eater); } static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu) @@ -1317,9 +1317,9 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu, u32 val; /* disable clock gating */ - val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS); + val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS); val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING; - gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val); + gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val); /* enable debug register */ val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL); @@ -1350,9 +1350,9 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu, gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val); /* enable clock gating */ - val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS); + val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS); val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING; - gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val); + gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val); } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index b3a0941d56fd..f1204b070fb8 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -10,6 +10,7 @@ #include "etnaviv_gem.h" #include "etnaviv_mmu.h" #include "etnaviv_drv.h" +#include "common.xml.h" struct etnaviv_gem_submit; struct etnaviv_vram_mapping; @@ -159,6 +160,26 @@ static inline u32 gpu_read(struct etnaviv_gpu *gpu, u32 reg) return readl(gpu->mmio + reg); } +static inline u32 gpu_fix_power_address(struct etnaviv_gpu *gpu, u32 reg) +{ + /* Power registers in GC300 < 2.0 are offset by 0x100 */ + if (gpu->identity.model == chipModel_GC300 && + gpu->identity.revision < 0x2000) + reg += 0x100; + + return reg; +} + +static inline void gpu_write_power(struct etnaviv_gpu *gpu, u32 reg, u32 data) +{ + writel(data, gpu->mmio + gpu_fix_power_address(gpu, reg)); +} + +static inline u32 gpu_read_power(struct etnaviv_gpu *gpu, u32 reg) +{ + return readl(gpu->mmio + gpu_fix_power_address(gpu, reg)); +} + int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value); int etnaviv_gpu_init(struct etnaviv_gpu *gpu); -- cgit v1.2.3 From d37c120b73128690434cc093952439eef9d56af1 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 16 Sep 2022 12:40:31 +0200 Subject: drm/etnaviv: don't truncate physical page address While the interface for the MMU mapping takes phys_addr_t to hold a full 64bit address when necessary and MMUv2 is able to map physical addresses with up to 40bit, etnaviv_iommu_map() truncates the address to 32bits. Fix this by using the correct type. Fixes: 931e97f3afd8 ("drm/etnaviv: mmuv2: support 40 bit phys address") Signed-off-by: Lucas Stach Reviewed-by: Philipp Zabel --- drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index 55479cb8b1ac..67bdce5326c6 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -80,10 +80,10 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova, return -EINVAL; for_each_sgtable_dma_sg(sgt, sg, i) { - u32 pa = sg_dma_address(sg) - sg->offset; + phys_addr_t pa = sg_dma_address(sg) - sg->offset; size_t bytes = sg_dma_len(sg) + sg->offset; - VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes); + VERB("map[%d]: %08x %pap(%zx)", i, iova, &pa, bytes); ret = etnaviv_context_map(context, da, pa, bytes, prot); if (ret) -- cgit v1.2.3 From 4bce244272513ebb4d13c570e9fbca28497015b2 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Fri, 26 Aug 2022 21:07:28 +0200 Subject: drm/etnaviv: disable tx clock gating for GC7000 rev6203 The i.MX8MN SoC errata sheet mentions ERR050226: "GPU: Texture L2 Cache idle signal may incorrectly clock gate the texture engine in GPU". The workaround is to disable the corresponding clock gatings. While on it move the clock gating check for rev6202 into the same check to bundle them. Signed-off-by: Marco Felsch Reviewed-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index ed2f9c8f288c..51320eeebfcf 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -623,14 +623,15 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu) /* Disable TX clock gating on affected core revisions. */ if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) || - etnaviv_is_model_rev(gpu, GC2000, 0x5108)) + etnaviv_is_model_rev(gpu, GC2000, 0x5108) || + etnaviv_is_model_rev(gpu, GC2000, 0x6202) || + etnaviv_is_model_rev(gpu, GC2000, 0x6203)) pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX; - /* Disable SE, RA and TX clock gating on affected core revisions. */ + /* Disable SE and RA clock gating on affected core revisions. */ if (etnaviv_is_model_rev(gpu, GC7000, 0x6202)) pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SE | - VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA | - VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX; + VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA; pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ; pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ; -- cgit v1.2.3 From 084b9e1732f71e36c21a820162c9f601577932c6 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 23 Sep 2022 15:40:44 -0700 Subject: drm/msm/gem: Unpin objects slightly later The introduction of "drm/msm/gem: Evict active GEM objects when necessary" exposes a problem with "drm/msm/gem: Unpin buffers earlier", in that we need to keep the object pinned in the time the submit is queued up in the gpu scheduler. Otherwise the shrinker will see it as a thing that can be evicted if we wait for it to be signaled. But if the shrinker path is waiting on it with the obj lock held, the job cannot be scheduled, as that also requires briefly grabbing the obj lock, leading to deadlock. (Not to mention, we don't want the shrinker to evict an obj queued up in gpu scheduler.) Fixes: f371bcc0c2ac ("drm/msm/gem: Unpin buffers earlier") Fixes: 025d27239a2f ("drm/msm/gem: Evict active GEM objects when necessary") Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/19 Signed-off-by: Rob Clark Tested-by: Chia-I Wu Patchwork: https://patchwork.freedesktop.org/patch/504528/ Link: https://lore.kernel.org/r/20220923224043.2449152-1-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem_submit.c | 4 ++-- drivers/gpu/drm/msm/msm_ringbuffer.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 5599d93ec0d2..c670591995e6 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -501,11 +501,11 @@ out: */ static void submit_cleanup(struct msm_gem_submit *submit, bool error) { - unsigned cleanup_flags = BO_LOCKED | BO_OBJ_PINNED; + unsigned cleanup_flags = BO_LOCKED; unsigned i; if (error) - cleanup_flags |= BO_VMA_PINNED; + cleanup_flags |= BO_VMA_PINNED | BO_OBJ_PINNED; for (i = 0; i < submit->nr_bos; i++) { struct msm_gem_object *msm_obj = submit->bos[i].obj; diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index cad4c3525f0b..57a8e9564540 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -25,7 +25,8 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job) msm_gem_lock(obj); msm_gem_unpin_vma_fenced(submit->bos[i].vma, fctx); - submit->bos[i].flags &= ~BO_VMA_PINNED; + msm_gem_unpin_locked(obj); + submit->bos[i].flags &= ~(BO_VMA_PINNED | BO_OBJ_PINNED); msm_gem_unlock(obj); } -- cgit v1.2.3 From ec8f1813bf8d0737898f99a8c1c69df0cde0d7dd Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Wed, 28 Sep 2022 12:48:59 +0530 Subject: drm/msm/a6xx: Replace kcalloc() with kvzalloc() In order to reduce chance of allocation failure while capturing a6xx gpu state, use kvzalloc() instead of kcalloc() in state_kcalloc(). Indirectly, this patch helps to fix leaking memory allocated for gmu_debug object. Fixes: b859f9b009b (drm/msm/gpu: Snapshot GMU debug buffer) Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/505074/ Link: https://lore.kernel.org/r/20220928124830.1.I8ea24a8d586b4978823b848adde000f92f74d5c2@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 55f443328d8e..3c112a6cc8a2 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -91,7 +91,7 @@ struct a6xx_state_memobj { static void *state_kcalloc(struct a6xx_gpu_state *a6xx_state, int nr, size_t objsize) { struct a6xx_state_memobj *obj = - kzalloc((nr * objsize) + sizeof(*obj), GFP_KERNEL); + kvzalloc((nr * objsize) + sizeof(*obj), GFP_KERNEL); if (!obj) return NULL; @@ -819,7 +819,7 @@ static struct msm_gpu_state_bo *a6xx_snapshot_gmu_bo( snapshot->iova = bo->iova; snapshot->size = bo->size; - snapshot->data = kvzalloc(snapshot->size, GFP_KERNEL); + snapshot->data = state_kcalloc(a6xx_state, 1, snapshot->size); if (!snapshot->data) return NULL; @@ -1034,14 +1034,8 @@ static void a6xx_gpu_state_destroy(struct kref *kref) struct a6xx_gpu_state *a6xx_state = container_of(state, struct a6xx_gpu_state, base); - if (a6xx_state->gmu_log) - kvfree(a6xx_state->gmu_log->data); - - if (a6xx_state->gmu_hfi) - kvfree(a6xx_state->gmu_hfi->data); - list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node) - kfree(obj); + kvfree(obj); adreno_gpu_state_destroy(state); kfree(a6xx_state); -- cgit v1.2.3 From 76efc2453d0e8e5d6692ef69981b183ad674edea Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Wed, 28 Sep 2022 12:49:00 +0530 Subject: drm/msm/gpu: Fix crash during system suspend after unbind In adreno_unbind, we should clean up gpu device's drvdata to avoid accessing a stale pointer during system suspend. Also, check for NULL ptr in both system suspend/resume callbacks. Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/505075/ Link: https://lore.kernel.org/r/20220928124830.2.I5ee0ac073ccdeb81961e5ec0cce5f741a7207a71@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/adreno_device.c | 10 +++++++++- drivers/gpu/drm/msm/msm_gpu.c | 2 ++ drivers/gpu/drm/msm/msm_gpu.h | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 24b489b6129a..628806423f7d 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -679,6 +679,9 @@ static int adreno_system_suspend(struct device *dev) struct msm_gpu *gpu = dev_to_gpu(dev); int remaining, ret; + if (!gpu) + return 0; + suspend_scheduler(gpu); remaining = wait_event_timeout(gpu->retire_event, @@ -700,7 +703,12 @@ out: static int adreno_system_resume(struct device *dev) { - resume_scheduler(dev_to_gpu(dev)); + struct msm_gpu *gpu = dev_to_gpu(dev); + + if (!gpu) + return 0; + + resume_scheduler(gpu); return pm_runtime_force_resume(dev); } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 0098ee8438aa..021f4e29b613 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -997,4 +997,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu) } msm_devfreq_cleanup(gpu); + + platform_set_drvdata(gpu->pdev, NULL); } diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index ff911e7305ce..58a72e6b1400 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -280,6 +280,10 @@ struct msm_gpu { static inline struct msm_gpu *dev_to_gpu(struct device *dev) { struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(dev); + + if (!adreno_smmu) + return NULL; + return container_of(adreno_smmu, struct msm_gpu, adreno_smmu); } -- cgit v1.2.3 From 3a661247967a6f3c99a95a8ba4c8073c5846ea4b Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Wed, 28 Sep 2022 16:36:51 -0700 Subject: drm/msm/dp: add atomic_check to bridge ops DRM commit_tails() will disable downstream crtc/encoder/bridge if both disable crtc is required and crtc->active is set before pushing a new frame downstream. There is a rare case that user space display manager issue an extra screen update immediately followed by close DRM device while down stream display interface is disabled. This extra screen update will timeout due to the downstream interface is disabled but will cause crtc->active be set. Hence the followed commit_tails() called by drm_release() will pass the disable downstream crtc/encoder/bridge conditions checking even downstream interface is disabled. This cause the crash to happen at dp_bridge_disable() due to it trying to access the main link register to push the idle pattern out while main link clocks is disabled. This patch adds atomic_check to prevent the extra frame will not be pushed down if display interface is down so that crtc->active will not be set neither. This will fail the conditions checking of disabling down stream crtc/encoder/bridge which prevent drm_release() from calling dp_bridge_disable() so that crash at dp_bridge_disable() prevented. There is no protection in the DRM framework to check if the display pipeline has been already disabled before trying again. The only check is the crtc_state->active but this is controlled by usermode using UAPI. Hence if the usermode sets this and then crashes, the driver needs to protect against double disable. SError Interrupt on CPU7, code 0x00000000be000411 -- SError CPU: 7 PID: 3878 Comm: Xorg Not tainted 5.19.0-stb-cbq #19 Hardware name: Google Lazor (rev3 - 8) (DT) pstate: a04000c9 (NzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : __cmpxchg_case_acq_32+0x14/0x2c lr : do_raw_spin_lock+0xa4/0xdc sp : ffffffc01092b6a0 x29: ffffffc01092b6a0 x28: 0000000000000028 x27: 0000000000000038 x26: 0000000000000004 x25: ffffffd2973dce48 x24: 0000000000000000 x23: 00000000ffffffff x22: 00000000ffffffff x21: ffffffd2978d0008 x20: ffffffd2978d0008 x19: ffffff80ff759fc0 x18: 0000000000000000 x17: 004800a501260460 x16: 0441043b04600438 x15: 04380000089807d0 x14: 07b0089807800780 x13: 0000000000000000 x12: 0000000000000000 x11: 0000000000000438 x10: 00000000000007d0 x9 : ffffffd2973e09e4 x8 : ffffff8092d53300 x7 : ffffff808902e8b8 x6 : 0000000000000001 x5 : ffffff808902e880 x4 : 0000000000000000 x3 : ffffff80ff759fc0 x2 : 0000000000000001 x1 : 0000000000000000 x0 : ffffff80ff759fc0 Kernel panic - not syncing: Asynchronous SError Interrupt CPU: 7 PID: 3878 Comm: Xorg Not tainted 5.19.0-stb-cbq #19 Hardware name: Google Lazor (rev3 - 8) (DT) Call trace: dump_backtrace.part.0+0xbc/0xe4 show_stack+0x24/0x70 dump_stack_lvl+0x68/0x84 dump_stack+0x18/0x34 panic+0x14c/0x32c nmi_panic+0x58/0x7c arm64_serror_panic+0x78/0x84 do_serror+0x40/0x64 el1h_64_error_handler+0x30/0x48 el1h_64_error+0x68/0x6c __cmpxchg_case_acq_32+0x14/0x2c _raw_spin_lock_irqsave+0x38/0x4c lock_timer_base+0x40/0x78 __mod_timer+0xf4/0x25c schedule_timeout+0xd4/0xfc __wait_for_common+0xac/0x140 wait_for_completion_timeout+0x2c/0x54 dp_ctrl_push_idle+0x40/0x88 dp_bridge_disable+0x24/0x30 drm_atomic_bridge_chain_disable+0x90/0xbc drm_atomic_helper_commit_modeset_disables+0x198/0x444 msm_atomic_commit_tail+0x1d0/0x374 commit_tail+0x80/0x108 drm_atomic_helper_commit+0x118/0x11c drm_atomic_commit+0xb4/0xe0 drm_client_modeset_commit_atomic+0x184/0x224 drm_client_modeset_commit_locked+0x58/0x160 drm_client_modeset_commit+0x3c/0x64 __drm_fb_helper_restore_fbdev_mode_unlocked+0x98/0xac drm_fb_helper_set_par+0x74/0x80 drm_fb_helper_hotplug_event+0xdc/0xe0 __drm_fb_helper_restore_fbdev_mode_unlocked+0x7c/0xac drm_fb_helper_restore_fbdev_mode_unlocked+0x20/0x2c drm_fb_helper_lastclose+0x20/0x2c drm_lastclose+0x44/0x6c drm_release+0x88/0xd4 __fput+0x104/0x220 ____fput+0x1c/0x28 task_work_run+0x8c/0x100 do_exit+0x450/0x8d0 do_group_exit+0x40/0xac __wake_up_parent+0x0/0x38 invoke_syscall+0x84/0x11c el0_svc_common.constprop.0+0xb8/0xe4 do_el0_svc+0x8c/0xb8 el0_svc+0x2c/0x54 el0t_64_sync_handler+0x120/0x1c0 el0t_64_sync+0x190/0x194 SMP: stopping secondary CPUs Kernel Offset: 0x128e800000 from 0xffffffc008000000 PHYS_OFFSET: 0x80000000 CPU features: 0x800,00c2a015,19801c82 Memory Limit: none Changes in v2: -- add more commit text Changes in v3: -- add comments into dp_bridge_atomic_check() Changes in v4: -- rewording the comment into dp_bridge_atomic_check() Changes in v5: -- removed quote x at end of commit text Changes in v6: -- removed quote x at end of comment in dp_bridge_atomic_check() Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable") Reported-by: Leonard Lausen Suggested-by: Rob Clark Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/17 Signed-off-by: Kuogee Hsieh Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/505331/ Link: https://lore.kernel.org/r/1664408211-25314-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dp/dp_drm.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 6df25f7662e7..6db82f9b03af 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -31,6 +31,36 @@ static enum drm_connector_status dp_bridge_detect(struct drm_bridge *bridge) connector_status_disconnected; } +static int dp_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct msm_dp *dp; + + dp = to_dp_bridge(bridge)->dp_display; + + drm_dbg_dp(dp->drm_dev, "is_connected = %s\n", + (dp->is_connected) ? "true" : "false"); + + /* + * There is no protection in the DRM framework to check if the display + * pipeline has been already disabled before trying to disable it again. + * Hence if the sink is unplugged, the pipeline gets disabled, but the + * crtc->active is still true. Any attempt to set the mode or manually + * disable this encoder will result in the crash. + * + * TODO: add support for telling the DRM subsystem that the pipeline is + * disabled by the hardware and thus all access to it should be forbidden. + * After that this piece of code can be removed. + */ + if (bridge->ops & DRM_BRIDGE_OP_HPD) + return (dp->is_connected) ? 0 : -ENOTCONN; + + return 0; +} + + /** * dp_bridge_get_modes - callback to add drm modes via drm_mode_probed_add() * @bridge: Poiner to drm bridge @@ -61,6 +91,9 @@ static int dp_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector * } static const struct drm_bridge_funcs dp_bridge_ops = { + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, .enable = dp_bridge_enable, .disable = dp_bridge_disable, .post_disable = dp_bridge_post_disable, @@ -68,6 +101,7 @@ static const struct drm_bridge_funcs dp_bridge_ops = { .mode_valid = dp_bridge_mode_valid, .get_modes = dp_bridge_get_modes, .detect = dp_bridge_detect, + .atomic_check = dp_bridge_atomic_check, }; struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev, -- cgit v1.2.3 From 0b33a33bd15d5bab73b87152b220a8d0153a4587 Mon Sep 17 00:00:00 2001 From: Nathan Huckleberry Date: Tue, 13 Sep 2022 13:55:48 -0700 Subject: drm/msm: Fix return type of mdp4_lvds_connector_mode_valid The mode_valid field in drm_connector_helper_funcs is expected to be of type: enum drm_mode_status (* mode_valid) (struct drm_connector *connector, struct drm_display_mode *mode); The mismatched return type breaks forward edge kCFI since the underlying function definition does not match the function hook definition. The return type of mdp4_lvds_connector_mode_valid should be changed from int to enum drm_mode_status. Reported-by: Dan Carpenter Link: https://github.com/ClangBuiltLinux/linux/issues/1703 Cc: llvm@lists.linux.dev Signed-off-by: Nathan Huckleberry Fixes: 3e87599b68e7 ("drm/msm/mdp4: add LVDS panel support") Reviewed-by: Abhinav Kumar Reviewed-by: Nathan Chancellor Patchwork: https://patchwork.freedesktop.org/patch/502878/ Link: https://lore.kernel.org/r/20220913205551.155128-1-nhuck@google.com Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c index 7288041dd86a..7444b75c4215 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c @@ -56,8 +56,9 @@ static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) return ret; } -static int mdp4_lvds_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +mdp4_lvds_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct mdp4_lvds_connector *mdp4_lvds_connector = to_mdp4_lvds_connector(connector); -- cgit v1.2.3 From 6808abdb33bf90330e70a687d29f038507e06ebb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Sep 2022 10:53:11 +0200 Subject: drm/msm: fix use-after-free on probe deferral The bridge counter was never reset when tearing down the DRM device so that stale pointers to deallocated structures would be accessed on the next tear down (e.g. after a second late bind deferral). Given enough bridges and a few probe deferrals this could currently also lead to data beyond the bridge array being corrupted. Fixes: d28ea556267c ("drm/msm: properly add and remove internal bridges") Fixes: a3376e3ec81c ("drm/msm: convert to drm_bridge") Cc: stable@vger.kernel.org # 3.12 Reviewed-by: Dmitry Baryshkov Signed-off-by: Johan Hovold Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/502665/ Link: https://lore.kernel.org/r/20220913085320.8577-2-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/msm_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 07f66412533b..fec6d449eded 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -247,6 +247,7 @@ static int msm_drm_uninit(struct device *dev) for (i = 0; i < priv->num_bridges; i++) drm_bridge_remove(priv->bridges[i]); + priv->num_bridges = 0; pm_runtime_get_sync(dev); msm_irq_uninstall(ddev); -- cgit v1.2.3 From 74466e46e7543c7f74f1502181e9ba93f7521374 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Sep 2022 10:53:12 +0200 Subject: drm/msm/dp: fix memory corruption with too many bridges Add the missing sanity check on the bridge counter to avoid corrupting data beyond the fixed-sized bridge array in case there are ever more than eight bridges. Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable") Cc: stable@vger.kernel.org # 5.17 Signed-off-by: Johan Hovold Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/502664/ Link: https://lore.kernel.org/r/20220913085320.8577-3-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dp/dp_display.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index bfd0aeff3f0d..be9ed891dc3f 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1597,6 +1597,12 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, return -EINVAL; priv = dev->dev_private; + + if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) { + DRM_DEV_ERROR(dev->dev, "too many bridges\n"); + return -ENOSPC; + } + dp_display->drm_dev = dev; dp_priv = container_of(dp_display, struct dp_display_private, dp_display); -- cgit v1.2.3 From 2e786eb2f9cebb07e317226b60054df510b60c65 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Sep 2022 10:53:13 +0200 Subject: drm/msm/dsi: fix memory corruption with too many bridges Add the missing sanity check on the bridge counter to avoid corrupting data beyond the fixed-sized bridge array in case there are ever more than eight bridges. Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") Cc: stable@vger.kernel.org # 4.1 Signed-off-by: Johan Hovold Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/502668/ Link: https://lore.kernel.org/r/20220913085320.8577-4-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/dsi.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 39bbabb5daf6..8a95c744972a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -218,6 +218,12 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, return -EINVAL; priv = dev->dev_private; + + if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) { + DRM_DEV_ERROR(dev->dev, "too many bridges\n"); + return -ENOSPC; + } + msm_dsi->dev = dev; ret = msm_dsi_host_modeset_init(msm_dsi->host, dev); -- cgit v1.2.3 From 4c1294da6aed1f16d47a417dcfe6602833c3c95c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Sep 2022 10:53:14 +0200 Subject: drm/msm/hdmi: fix memory corruption with too many bridges Add the missing sanity check on the bridge counter to avoid corrupting data beyond the fixed-sized bridge array in case there are ever more than eight bridges. Fixes: a3376e3ec81c ("drm/msm: convert to drm_bridge") Cc: stable@vger.kernel.org # 3.12 Signed-off-by: Johan Hovold Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/502670/ Link: https://lore.kernel.org/r/20220913085320.8577-5-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/hdmi/hdmi.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 93fe61b86967..a0ed6aa8e4e1 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -300,6 +300,11 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, struct platform_device *pdev = hdmi->pdev; int ret; + if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) { + DRM_DEV_ERROR(dev->dev, "too many bridges\n"); + return -ENOSPC; + } + hdmi->dev = dev; hdmi->encoder = encoder; -- cgit v1.2.3 From a79343dcaba4b11adb57350e0b6426906a9b658e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Sep 2022 10:53:15 +0200 Subject: drm/msm/dp: fix IRQ lifetime Device-managed resources allocated post component bind must be tied to the lifetime of the aggregate DRM device or they will not necessarily be released when binding of the aggregate device is deferred. This is specifically true for the DP IRQ, which will otherwise remain requested so that the next bind attempt fails when requesting the IRQ a second time. Since commit c3bf8e21b38a ("drm/msm/dp: Add eDP support via aux_bus") this can happen when the aux-bus panel driver has not yet been loaded so that probe is deferred. Fix this by tying the device-managed lifetime of the DP IRQ to the DRM device so that it is released when bind fails. Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Cc: stable@vger.kernel.org # 5.10 Reviewed-by: Dmitry Baryshkov Signed-off-by: Johan Hovold Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/502679/ Link: https://lore.kernel.org/r/20220913085320.8577-6-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index be9ed891dc3f..352cc09f2069 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1249,7 +1249,7 @@ int dp_display_request_irq(struct msm_dp *dp_display) return -EINVAL; } - rc = devm_request_irq(&dp->pdev->dev, dp->irq, + rc = devm_request_irq(dp_display->drm_dev->dev, dp->irq, dp_display_irq_handler, IRQF_TRIGGER_HIGH, "dp_display_isr", dp); if (rc < 0) { -- cgit v1.2.3 From 2b57f726611e294dc4297dd48eb8c98ef1938e82 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Sep 2022 10:53:16 +0200 Subject: drm/msm/dp: fix aux-bus EP lifetime Device-managed resources allocated post component bind must be tied to the lifetime of the aggregate DRM device or they will not necessarily be released when binding of the aggregate device is deferred. This can lead resource leaks or failure to bind the aggregate device when binding is later retried and a second attempt to allocate the resources is made. For the DP aux-bus, an attempt to populate the bus a second time will simply fail ("DP AUX EP device already populated"). Fix this by tying the lifetime of the EP device to the DRM device rather than DP controller platform device. Fixes: c3bf8e21b38a ("drm/msm/dp: Add eDP support via aux_bus") Cc: stable@vger.kernel.org # 5.19 Signed-off-by: Johan Hovold Reviewed-by: Douglas Anderson Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/502672/ Link: https://lore.kernel.org/r/20220913085320.8577-7-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dp/dp_display.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 352cc09f2069..42de690132cf 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1528,6 +1528,11 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor) } } +static void of_dp_aux_depopulate_bus_void(void *data) +{ + of_dp_aux_depopulate_bus(data); +} + static int dp_display_get_next_bridge(struct msm_dp *dp) { int rc; @@ -1552,10 +1557,16 @@ static int dp_display_get_next_bridge(struct msm_dp *dp) * panel driver is probed asynchronously but is the best we * can do without a bigger driver reorganization. */ - rc = devm_of_dp_aux_populate_ep_devices(dp_priv->aux); + rc = of_dp_aux_populate_bus(dp_priv->aux, NULL); of_node_put(aux_bus); if (rc) goto error; + + rc = devm_add_action_or_reset(dp->drm_dev->dev, + of_dp_aux_depopulate_bus_void, + dp_priv->aux); + if (rc) + goto error; } else if (dp->is_edp) { DRM_ERROR("eDP aux_bus not found\n"); return -ENODEV; -- cgit v1.2.3 From 16194958f888d63839042d1190f7001e5ddec47b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Sep 2022 10:53:17 +0200 Subject: drm/msm/dp: fix bridge lifetime Device-managed resources allocated post component bind must be tied to the lifetime of the aggregate DRM device or they will not necessarily be released when binding of the aggregate device is deferred. This can lead resource leaks or failure to bind the aggregate device when binding is later retried and a second attempt to allocate the resources is made. For the DP bridges, previously allocated bridges will leak on probe deferral. Fix this by amending the DP parser interface and tying the lifetime of the bridge device to the DRM device rather than DP platform device. Fixes: c3bf8e21b38a ("drm/msm/dp: Add eDP support via aux_bus") Cc: stable@vger.kernel.org # 5.19 Reviewed-by: Dmitry Baryshkov Signed-off-by: Johan Hovold Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/502667/ Link: https://lore.kernel.org/r/20220913085320.8577-8-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- drivers/gpu/drm/msm/dp/dp_parser.c | 6 +++--- drivers/gpu/drm/msm/dp/dp_parser.h | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 42de690132cf..a49f6dbbe888 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1579,7 +1579,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp) * For DisplayPort interfaces external bridges are optional, so * silently ignore an error if one is not present (-ENODEV). */ - rc = dp_parser_find_next_bridge(dp_priv->parser); + rc = devm_dp_parser_find_next_bridge(dp->drm_dev->dev, dp_priv->parser); if (!dp->is_edp && rc == -ENODEV) return 0; diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index dd732215d55b..dcbe893d66d7 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -240,12 +240,12 @@ static int dp_parser_clock(struct dp_parser *parser) return 0; } -int dp_parser_find_next_bridge(struct dp_parser *parser) +int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser) { - struct device *dev = &parser->pdev->dev; + struct platform_device *pdev = parser->pdev; struct drm_bridge *bridge; - bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); + bridge = devm_drm_of_get_bridge(dev, pdev->dev.of_node, 1, 0); if (IS_ERR(bridge)) return PTR_ERR(bridge); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 866c1a82bf1a..d30ab773db46 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -138,8 +138,9 @@ struct dp_parser { struct dp_parser *dp_parser_get(struct platform_device *pdev); /** - * dp_parser_find_next_bridge() - find an additional bridge to DP + * devm_dp_parser_find_next_bridge() - find an additional bridge to DP * + * @dev: device to tie bridge lifetime to * @parser: dp_parser data from client * * This function is used to find any additional bridge attached to @@ -147,6 +148,6 @@ struct dp_parser *dp_parser_get(struct platform_device *pdev); * * Return: 0 if able to get the bridge, otherwise negative errno for failure. */ -int dp_parser_find_next_bridge(struct dp_parser *parser); +int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser); #endif -- cgit v1.2.3 From 152d394842bb564148e68b92486a87db0bf54859 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Sep 2022 10:53:18 +0200 Subject: drm/msm/hdmi: fix IRQ lifetime Device-managed resources allocated post component bind must be tied to the lifetime of the aggregate DRM device or they will not necessarily be released when binding of the aggregate device is deferred. This is specifically true for the HDMI IRQ, which will otherwise remain requested so that the next bind attempt fails when requesting the IRQ a second time. Fix this by tying the device-managed lifetime of the HDMI IRQ to the DRM device so that it is released when bind fails. Fixes: 067fef372c73 ("drm/msm/hdmi: refactor bind/init") Cc: stable@vger.kernel.org # 3.19 Reviewed-by: Dmitry Baryshkov Signed-off-by: Johan Hovold Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/502666/ Link: https://lore.kernel.org/r/20220913085320.8577-9-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/hdmi/hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index a0ed6aa8e4e1..f28fb21e3891 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -344,7 +344,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, goto fail; } - ret = devm_request_irq(&pdev->dev, hdmi->irq, + ret = devm_request_irq(dev->dev, hdmi->irq, msm_hdmi_irq, IRQF_TRIGGER_HIGH, "hdmi_isr", hdmi); if (ret < 0) { -- cgit v1.2.3 From 70445dee1b4cf44c9fecc580dfa08079011866f1 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Mon, 12 Sep 2022 09:23:48 -0700 Subject: drm/msm/dp: cleared DP_DOWNSPREAD_CTRL register before start link training DOWNSPREAD_CTRL (0x107) shall be cleared to 0 upon power-on reset or an upstream device disconnect. This patch will enforce this rule by always cleared DOWNSPREAD_CTRL register to 0 before start link training. At rare case that DP MSA timing parameters may be mis-interpreted by the sink which causes audio sampling rate be calculated wrongly and cause audio did not work at sink if DOWNSPREAD_CTRL register is not cleared to 0. Changes in v2: 1) fix spelling at commit text 2) merge ssc variable into encoding[0] Changes in v3: -- correct spelling of DOWNSPREAD_CTRL -- replace err with len of ssize_t Changes in v4: -- split into 2 patches Signed-off-by: Kuogee Hsieh Reviewed-by: Dmitry Baryshkov Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Patchwork: https://patchwork.freedesktop.org/patch/502532/ Link: https://lore.kernel.org/r/1662999830-13916-2-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 3854c9f1f7e9..dd26ca651a05 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1243,8 +1243,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, { int ret = 0; const u8 *dpcd = ctrl->panel->dpcd; - u8 encoding = DP_SET_ANSI_8B10B; - u8 ssc; + u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; u8 assr; struct dp_link_info link_info = {0}; @@ -1256,13 +1255,11 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, dp_aux_link_configure(ctrl->aux, &link_info); - if (drm_dp_max_downspread(dpcd)) { - ssc = DP_SPREAD_AMP_0_5; - drm_dp_dpcd_write(ctrl->aux, DP_DOWNSPREAD_CTRL, &ssc, 1); - } + if (drm_dp_max_downspread(dpcd)) + encoding[0] |= DP_SPREAD_AMP_0_5; - drm_dp_dpcd_write(ctrl->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, - &encoding, 1); + /* config DOWNSPREAD_CTRL and MAIN_LINK_CHANNEL_CODING_SET */ + drm_dp_dpcd_write(ctrl->aux, DP_DOWNSPREAD_CTRL, encoding, 2); if (drm_dp_alternate_scrambler_reset_cap(dpcd)) { assr = DP_ALTERNATE_SCRAMBLER_RESET_ENABLE; -- cgit v1.2.3 From 1f1009ea8ca5a0271ad69afe8a86c887d530b5c8 Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Fri, 9 Sep 2022 12:04:22 +0300 Subject: scsi: target: core: Fix preempt and abort for allreg res Match a key only if SARK is not zero according to SPC-4 and the comment above the code: If an all registrants persistent reservation is present and the SERVICE ACTION RESERVATION KEY field is set to zero, then all registrations shall be removed except for that of the I_T nexus that is being used for the PERSISTENT RESERVE OUT command; Without this patch in case of SARK==0 no registrants will be removed. Link: https://lore.kernel.org/r/20220909090425.14479-2-d.bogdanov@yadro.com Reviewed-by: Mike Christie Signed-off-by: Dmitry Bogdanov Signed-off-by: Martin K. Petersen --- drivers/target/target_core_pr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index a1d67554709f..1521a97ddac2 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3022,7 +3022,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, if (calling_it_nexus) continue; - if (pr_reg->pr_res_key != sa_res_key) + if (sa_res_key && pr_reg->pr_res_key != sa_res_key) continue; pr_reg_nacl = pr_reg->pr_reg_nacl; -- cgit v1.2.3 From f050a7c66ca56aa2f49ab9b53e01d04b3e7e94c5 Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Fri, 9 Sep 2022 12:04:23 +0300 Subject: scsi: target: core: Fix memory leak in preempt_and_abort Always release preempt_and_abort_list to avoid memory leak of t10_pr_registration objects in it. Link: https://lore.kernel.org/r/20220909090425.14479-3-d.bogdanov@yadro.com Reviewed-by: Mike Christie Signed-off-by: Dmitry Bogdanov Signed-off-by: Martin K. Petersen --- drivers/target/target_core_pr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 1521a97ddac2..e3869576f254 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2956,13 +2956,14 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, __core_scsi3_complete_pro_preempt(dev, pr_reg_n, (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL, type, scope, preempt_type); - - if (preempt_type == PREEMPT_AND_ABORT) - core_scsi3_release_preempt_and_abort( - &preempt_and_abort_list, pr_reg_n); } + spin_unlock(&dev->dev_reservation_lock); + if (preempt_type == PREEMPT_AND_ABORT) + core_scsi3_release_preempt_and_abort( + &preempt_and_abort_list, pr_reg_n); + if (pr_tmpl->pr_aptpl_active) core_scsi3_update_and_write_aptpl(cmd->se_dev, true); -- cgit v1.2.3 From 49790e6a582012c36ca17174cda228444f9a2414 Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Fri, 9 Sep 2022 12:04:24 +0300 Subject: scsi: target: core: Abort all preempted regs if requested According to SPC the preempted commands shall be always aborted. SPC-4: 5.12.11.2.6 Preempting and aborting c) all commands from the I_T nexus(es) associated with the persistent reservations or registrations being preempted (i.e., preempted commands) except the PERSISTENT RESERVE OUT command itself shall be aborted as defined in SAM-5; Link: https://lore.kernel.org/r/20220909090425.14479-4-d.bogdanov@yadro.com Reviewed-by: Mike Christie Signed-off-by: Dmitry Bogdanov Signed-off-by: Martin K. Petersen --- drivers/target/target_core_pr.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index e3869576f254..6a5f9504a481 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2960,9 +2960,23 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, spin_unlock(&dev->dev_reservation_lock); - if (preempt_type == PREEMPT_AND_ABORT) + /* + * SPC-4 5.12.11.2.6 Preempting and aborting + * The actions described in this subclause shall be performed + * for all I_T nexuses that are registered with the non-zero + * SERVICE ACTION RESERVATION KEY value, without regard for + * whether the preempted I_T nexuses hold the persistent + * reservation. If the SERVICE ACTION RESERVATION KEY field is + * set to zero and an all registrants persistent reservation is + * present, the device server shall abort all commands for all + * registered I_T nexuses. + */ + if (preempt_type == PREEMPT_AND_ABORT) { + core_tmr_lun_reset(dev, NULL, &preempt_and_abort_list, + cmd); core_scsi3_release_preempt_and_abort( &preempt_and_abort_list, pr_reg_n); + } if (pr_tmpl->pr_aptpl_active) core_scsi3_update_and_write_aptpl(cmd->se_dev, true); -- cgit v1.2.3 From 3e2deba7aa662862c8046aa24148b83b49298a9b Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Fri, 9 Sep 2022 12:04:25 +0300 Subject: scsi: target: core: New key must be used for moved PR According to SPC4 5.12.8: e) Retain the reservation key specified in the SERVICE ACTION RESERVATION KEY field and associated information; But currently sa_res_key is only used for the not existing I_T nexus. Add a changing of the key for the existing I_T nexus the PR moved to. Link: https://lore.kernel.org/r/20220909090425.14479-5-d.bogdanov@yadro.com Reviewed-by: Mike Christie Signed-off-by: Dmitry Bogdanov Signed-off-by: Martin K. Petersen --- drivers/target/target_core_pr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 6a5f9504a481..1493b1d01194 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3440,8 +3440,6 @@ after_iport_check: * transport protocols where port names are not required; * d) Register the reservation key specified in the SERVICE ACTION * RESERVATION KEY field; - * e) Retain the reservation key specified in the SERVICE ACTION - * RESERVATION KEY field and associated information; * * Also, It is not an error for a REGISTER AND MOVE service action to * register an I_T nexus that is already registered with the same @@ -3463,6 +3461,12 @@ after_iport_check: dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, iport_ptr); new_reg = 1; + } else { + /* + * e) Retain the reservation key specified in the SERVICE ACTION + * RESERVATION KEY field and associated information; + */ + dest_pr_reg->pr_res_key = sa_res_key; } /* * f) Release the persistent reservation for the persistent reservation -- cgit v1.2.3 From 6290e23f3bd8cee52fb8fd98980bb1eb31c8284d Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Tue, 13 Sep 2022 19:36:02 +0300 Subject: scsi: target: core: UA on all LUNs after reset Allocate UNIT ATTENTION "BUS DEVICE RESET OCCURRED" on all LUNs on all target ports of the device upon reception of TMF LUN RESET. This change passes libiscsi test SCSI.MultipathIO.Reset. Link: https://lore.kernel.org/r/20220913163602.20597-1-d.bogdanov@yadro.com Signed-off-by: Dmitry Bogdanov Signed-off-by: Martin K. Petersen --- drivers/target/target_core_device.c | 19 +++++++++++++++++++ drivers/target/target_core_internal.h | 1 + drivers/target/target_core_transport.c | 3 +-- 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index b7f16ee8aa0e..cb4f7cc02f8f 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -284,6 +284,25 @@ void target_pr_kref_release(struct kref *kref) complete(&deve->pr_comp); } +/* + * Establish UA condition on SCSI device - all LUNs + */ +void target_dev_ua_allocate(struct se_device *dev, u8 asc, u8 ascq) +{ + struct se_dev_entry *se_deve; + struct se_lun *lun; + + spin_lock(&dev->se_port_lock); + list_for_each_entry(lun, &dev->dev_sep_list, lun_dev_link) { + + spin_lock(&lun->lun_deve_lock); + list_for_each_entry(se_deve, &lun->lun_deve_list, lun_link) + core_scsi3_ua_allocate(se_deve, asc, ascq); + spin_unlock(&lun->lun_deve_lock); + } + spin_unlock(&dev->se_port_lock); +} + static void target_luns_data_has_changed(struct se_node_acl *nacl, struct se_dev_entry *new, bool skip_new) diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 30fcf69e1a1d..38a6d08f75b3 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -89,6 +89,7 @@ int target_configure_device(struct se_device *dev); void target_free_device(struct se_device *); int target_for_each_device(int (*fn)(struct se_device *dev, void *data), void *data); +void target_dev_ua_allocate(struct se_device *dev, u8 asc, u8 ascq); /* target_core_configfs.c */ extern struct configfs_item_operations target_core_dev_item_ops; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7838dc20f713..5926316252eb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3531,8 +3531,7 @@ static void target_tmr_work(struct work_struct *work) tmr->response = (!ret) ? TMR_FUNCTION_COMPLETE : TMR_FUNCTION_REJECTED; if (tmr->response == TMR_FUNCTION_COMPLETE) { - target_ua_allocate_lun(cmd->se_sess->se_node_acl, - cmd->orig_fe_lun, 0x29, + target_dev_ua_allocate(dev, 0x29, ASCQ_29H_BUS_DEVICE_RESET_FUNCTION_OCCURRED); } break; -- cgit v1.2.3 From 9b78d8fadeee078ca947a3b44157f42035fdf8b1 Mon Sep 17 00:00:00 2001 From: Guixin Liu Date: Wed, 14 Sep 2022 16:47:59 +0800 Subject: scsi: megaraid_sas: Correct value passed to scsi_device_lookup() The "id" parameter currently passed to scsi_device_lookup() when removing a device is incorrect. It should be "ld_target_id % MEGASAS_MAX_DEV_PER_CHANNEL". Link: https://lore.kernel.org/r/1663145283-4872-2-git-send-email-kanie@linux.alibaba.com Fixes: ae6874ba4b43 ("scsi: megaraid_sas: Early detection of VD deletion through RaidMap update") Acked-by: Sumit Saxena Signed-off-by: Guixin Liu Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index ae6b9a570fa9..1772b0be88fe 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -8924,7 +8924,7 @@ megasas_aen_polling(struct work_struct *work) sdev1 = scsi_device_lookup(instance->host, MEGASAS_MAX_PD_CHANNELS + (ld_target_id / MEGASAS_MAX_DEV_PER_CHANNEL), - (ld_target_id - MEGASAS_MAX_DEV_PER_CHANNEL), + (ld_target_id % MEGASAS_MAX_DEV_PER_CHANNEL), 0); if (sdev1) megasas_remove_scsi_device(sdev1); -- cgit v1.2.3 From 9b201b5dff81f298cebda10d51767cd25b432a1a Mon Sep 17 00:00:00 2001 From: Guixin Liu Date: Wed, 14 Sep 2022 16:48:00 +0800 Subject: scsi: megaraid_sas: Correct an error message Correct the error message logged when allocation of ioc_init_request fails. Link: https://lore.kernel.org/r/1663145283-4872-3-git-send-email-kanie@linux.alibaba.com Acked-by: Sumit Saxena Signed-off-by: Guixin Liu Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 1772b0be88fe..22c3e3370403 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7226,7 +7226,7 @@ int megasas_alloc_ctrl_dma_buffers(struct megasas_instance *instance) if (!fusion->ioc_init_request) { dev_err(&pdev->dev, - "Failed to allocate PD list buffer\n"); + "Failed to allocate ioc init request\n"); return -ENOMEM; } -- cgit v1.2.3 From 17883cd59f5575ebe5b3cce2fd0f0d91738871bb Mon Sep 17 00:00:00 2001 From: Guixin Liu Date: Wed, 14 Sep 2022 16:48:01 +0800 Subject: scsi: megaraid_sas: Simplify megasas_update_device_list Remove unnecessary dcmd_ret check and goto statement. Link: https://lore.kernel.org/r/1663145283-4872-4-git-send-email-kanie@linux.alibaba.com Acked-by: Sumit Saxena Signed-off-by: Guixin Liu Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 22c3e3370403..4e8b7042e8b3 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -8768,33 +8768,26 @@ static int megasas_update_device_list(struct megasas_instance *instance, int event_type) { - int dcmd_ret = DCMD_SUCCESS; + int dcmd_ret; if (instance->enable_fw_dev_list) { - dcmd_ret = megasas_host_device_list_query(instance, false); - if (dcmd_ret != DCMD_SUCCESS) - goto out; + return megasas_host_device_list_query(instance, false); } else { if (event_type & SCAN_PD_CHANNEL) { dcmd_ret = megasas_get_pd_list(instance); - if (dcmd_ret != DCMD_SUCCESS) - goto out; + return dcmd_ret; } if (event_type & SCAN_VD_CHANNEL) { if (!instance->requestorId || megasas_get_ld_vf_affiliation(instance, 0)) { - dcmd_ret = megasas_ld_list_query(instance, + return megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); - if (dcmd_ret != DCMD_SUCCESS) - goto out; } } } - -out: - return dcmd_ret; + return DCMD_SUCCESS; } /** -- cgit v1.2.3 From ad40d51992392a2336af861f83c17c0b08ca64b6 Mon Sep 17 00:00:00 2001 From: Guixin Liu Date: Wed, 14 Sep 2022 16:48:02 +0800 Subject: scsi: megaraid_sas: Remove unnecessary memset() Remove memset() of pd_list and ld_ids in megasas_get_device_list(). These lists will be cleared by megasas_host_device_list_query(), megasas_get_pd_list(), and megasas_ld_list_query(). Link: https://lore.kernel.org/r/1663145283-4872-5-git-send-email-kanie@linux.alibaba.com Acked-by: Sumit Saxena Signed-off-by: Guixin Liu Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 4e8b7042e8b3..f5e8c7cd0dca 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5876,10 +5876,6 @@ fallback: static int megasas_get_device_list(struct megasas_instance *instance) { - memset(instance->pd_list, 0, - (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); - memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); - if (instance->enable_fw_dev_list) { if (megasas_host_device_list_query(instance, true)) return FAILED; -- cgit v1.2.3 From 27b571cc454e5a5939b4940ed0bf20aaf37f5225 Mon Sep 17 00:00:00 2001 From: Guixin Liu Date: Wed, 14 Sep 2022 16:48:03 +0800 Subject: scsi: megaraid_sas: Move megasas_dbg_lvl init to megasas_init() The megasas_dbg_lvl is a driver level parameter. Do not initialize it in the probe path. Otherwise we will miss the debug print when binding a new device to the megaraid driver. Link: https://lore.kernel.org/r/1663145283-4872-6-git-send-email-kanie@linux.alibaba.com Acked-by: Sumit Saxena Signed-off-by: Guixin Liu Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index f5e8c7cd0dca..465274ba9f1b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7441,7 +7441,6 @@ static inline void megasas_init_ctrl_params(struct megasas_instance *instance) (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) instance->flag_ieee = 1; - megasas_dbg_lvl = 0; instance->flag = 0; instance->unload = 1; instance->last_time = 0; @@ -9011,6 +9010,7 @@ static int __init megasas_init(void) */ pr_info("megasas: %s\n", MEGASAS_VERSION); + megasas_dbg_lvl = 0; support_poll_for_event = 2; support_device_change = 1; support_nvme_encapsulation = true; -- cgit v1.2.3 From 07e433614cdb91e6f85cc79d738bb0a3d8c741a2 Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Fri, 23 Sep 2022 18:12:17 +0800 Subject: scsi: ufs: qcom: Remove redundant dev_err() call devm_ioremap_resource() already prints an error message. Remove the redundant dev_err() call. Link: https://lore.kernel.org/r/20220923101217.18345-1-shangxiaojing@huawei.com Reviewed-by: Bart Van Assche Signed-off-by: Shang XiaoJing Signed-off-by: Martin K. Petersen --- drivers/ufs/host/ufs-qcom-ice.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ufs/host/ufs-qcom-ice.c b/drivers/ufs/host/ufs-qcom-ice.c index 745e48ec598f..62387ccd5b30 100644 --- a/drivers/ufs/host/ufs-qcom-ice.c +++ b/drivers/ufs/host/ufs-qcom-ice.c @@ -118,7 +118,6 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *host) host->ice_mmio = devm_ioremap_resource(dev, res); if (IS_ERR(host->ice_mmio)) { err = PTR_ERR(host->ice_mmio); - dev_err(dev, "Failed to map ICE registers; err=%d\n", err); return err; } -- cgit v1.2.3 From 3ddeabd1536a71abf2b66a577c90df84514a0af2 Mon Sep 17 00:00:00 2001 From: Rafael Mendonca Date: Mon, 26 Sep 2022 20:02:44 -0300 Subject: scsi: qla2xxx: Fix serialization of DCBX TLV data request Commit b6faaaf796d7 ("scsi: qla2xxx: Serialize mailbox request") serialized mailbox requests from userspace using the 'optrom' mutex. However, in the case of DCBX TLV data, if the memory for it is already allocated, then the mailbox request ends up not being serialized because it is done without holding the 'optrom' mutex. Link: https://lore.kernel.org/r/20220926230245.790508-1-rafaelmendsr@gmail.com Fixes: b6faaaf796d7 ("scsi: qla2xxx: Serialize mailbox request") Reviewed-by: Himanshu Madhani Signed-off-by: Rafael Mendonca Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index fa1fcbfb946f..c2bc7f9c728a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -951,9 +951,9 @@ qla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj, if (!capable(CAP_SYS_ADMIN) || off != 0 || count > DCBX_TLV_DATA_SIZE) return 0; + mutex_lock(&vha->hw->optrom_mutex); if (ha->dcbx_tlv) goto do_read; - mutex_lock(&vha->hw->optrom_mutex); if (qla2x00_chip_is_down(vha)) { mutex_unlock(&vha->hw->optrom_mutex); return 0; -- cgit v1.2.3 From f915f58e382e907e2be0b2f5472617dc13f2c390 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 27 Sep 2022 10:22:25 +0200 Subject: scsi: target: iblock: Fold iblock_emulate_read_cap_with_block_size() into iblock_get_blocks() Fold iblock_emulate_read_cap_with_block_size() into its only caller. Link: https://lore.kernel.org/r/20220927082225.271975-1-hch@lst.de Reviewed-by: Mike Christie Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/target/target_core_iblock.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 8351c974cee3..d9266cf558dc 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -230,14 +230,12 @@ static void iblock_unplug_device(struct se_dev_plug *se_plug) clear_bit(IBD_PLUGF_PLUGGED, &ib_dev_plug->flags); } -static unsigned long long iblock_emulate_read_cap_with_block_size( - struct se_device *dev, - struct block_device *bd, - struct request_queue *q) +static sector_t iblock_get_blocks(struct se_device *dev) { - u32 block_size = bdev_logical_block_size(bd); + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + u32 block_size = bdev_logical_block_size(ib_dev->ibd_bd); unsigned long long blocks_long = - div_u64(bdev_nr_bytes(bd), block_size) - 1; + div_u64(bdev_nr_bytes(ib_dev->ibd_bd), block_size) - 1; if (block_size == dev->dev_attrib.block_size) return blocks_long; @@ -829,15 +827,6 @@ fail: return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } -static sector_t iblock_get_blocks(struct se_device *dev) -{ - struct iblock_dev *ib_dev = IBLOCK_DEV(dev); - struct block_device *bd = ib_dev->ibd_bd; - struct request_queue *q = bdev_get_queue(bd); - - return iblock_emulate_read_cap_with_block_size(dev, bd, q); -} - static sector_t iblock_get_alignment_offset_lbas(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); -- cgit v1.2.3 From 0b863257c17c5f57a41e0a48de140ed026957a63 Mon Sep 17 00:00:00 2001 From: Manish Rangankar Date: Tue, 27 Sep 2022 04:59:46 -0700 Subject: scsi: qla2xxx: Use transport-defined speed mask for supported_speeds One of the sysfs values reported for supported_speeds was not valid (20Gb/s reported instead of 64Gb/s). Instead of driver internal speed mask definition, use speed mask defined in transport_fc for reporting host->supported_speeds. Link: https://lore.kernel.org/r/20220927115946.17559-1-njavali@marvell.com Cc: stable@vger.kernel.org Reviewed-by: Himanshu Madhani Signed-off-by: Manish Rangankar Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_attr.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index c2bc7f9c728a..b67ad30d56e6 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -3330,11 +3330,34 @@ struct fc_function_template qla2xxx_transport_vport_functions = { .bsg_timeout = qla24xx_bsg_timeout, }; +static uint +qla2x00_get_host_supported_speeds(scsi_qla_host_t *vha, uint speeds) +{ + uint supported_speeds = FC_PORTSPEED_UNKNOWN; + + if (speeds & FDMI_PORT_SPEED_64GB) + supported_speeds |= FC_PORTSPEED_64GBIT; + if (speeds & FDMI_PORT_SPEED_32GB) + supported_speeds |= FC_PORTSPEED_32GBIT; + if (speeds & FDMI_PORT_SPEED_16GB) + supported_speeds |= FC_PORTSPEED_16GBIT; + if (speeds & FDMI_PORT_SPEED_8GB) + supported_speeds |= FC_PORTSPEED_8GBIT; + if (speeds & FDMI_PORT_SPEED_4GB) + supported_speeds |= FC_PORTSPEED_4GBIT; + if (speeds & FDMI_PORT_SPEED_2GB) + supported_speeds |= FC_PORTSPEED_2GBIT; + if (speeds & FDMI_PORT_SPEED_1GB) + supported_speeds |= FC_PORTSPEED_1GBIT; + + return supported_speeds; +} + void qla2x00_init_host_attr(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - u32 speeds = FC_PORTSPEED_UNKNOWN; + u32 speeds = 0, fdmi_speed = 0; fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); @@ -3344,7 +3367,8 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; - speeds = qla25xx_fdmi_port_speed_capability(ha); + fdmi_speed = qla25xx_fdmi_port_speed_capability(ha); + speeds = qla2x00_get_host_supported_speeds(vha, fdmi_speed); fc_host_supported_speeds(vha->host) = speeds; } -- cgit v1.2.3 From 638eec06c7f4df8eb415a0b33dd18cc6dfc986e6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 28 Sep 2022 23:21:16 +0100 Subject: scsi: lpfc: Fix spelling mistake "unsolicted" -> "unsolicited" There are spelling mistakes in a log message and two comments. Fix them. Link: https://lore.kernel.org/r/20220928222116.68294-1-colin.i.king@gmail.com Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 4 ++-- drivers/scsi/lpfc/lpfc_ct.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index ac0c7ccf2eae..852b025e2fec 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -2582,7 +2582,7 @@ static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi) * * This function obtains the transmit and receive ids required to send * an unsolicited ct command with a payload. A special lpfc FsType and CmdRsp - * flags are used to the unsolicted response handler is able to process + * flags are used to the unsolicited response handler is able to process * the ct command sent on the same port. **/ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, @@ -2874,7 +2874,7 @@ out: * @len: Number of data bytes * * This function allocates and posts a data buffer of sufficient size to receive - * an unsolicted CT command. + * an unsolicited CT command. **/ static int lpfcdiag_sli3_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri, size_t len) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 75fd2bfc212b..e941a99aa965 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -90,7 +90,7 @@ lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, get_job_ulpstatus(phba, piocbq)); } lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "0145 Ignoring unsolicted CT HBQ Size:%d " + "0145 Ignoring unsolicited CT HBQ Size:%d " "status = x%x\n", size, get_job_ulpstatus(phba, piocbq)); } -- cgit v1.2.3 From 67d0a917fb3f9e80c3fb6098ada2080d1b425c94 Mon Sep 17 00:00:00 2001 From: Markus Fuchs Date: Thu, 29 Sep 2022 00:22:42 +0200 Subject: scsi: ufs: core: Remove unneeded casts from void * The end_io_data member of the "struct request" type has type "void *", so no cast is necessary. Link: https://lore.kernel.org/r/20220928222241.131334-1-mklntf@gmail.com Reviewed-by: Bart Van Assche Signed-off-by: Markus Fuchs Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshpb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ufs/core/ufshpb.c b/drivers/ufs/core/ufshpb.c index a1a7a1175a5a..0ce5063bedc5 100644 --- a/drivers/ufs/core/ufshpb.c +++ b/drivers/ufs/core/ufshpb.c @@ -615,14 +615,14 @@ static void ufshpb_activate_subregion(struct ufshpb_lu *hpb, static void ufshpb_umap_req_compl_fn(struct request *req, blk_status_t error) { - struct ufshpb_req *umap_req = (struct ufshpb_req *)req->end_io_data; + struct ufshpb_req *umap_req = req->end_io_data; ufshpb_put_req(umap_req->hpb, umap_req); } static void ufshpb_map_req_compl_fn(struct request *req, blk_status_t error) { - struct ufshpb_req *map_req = (struct ufshpb_req *) req->end_io_data; + struct ufshpb_req *map_req = req->end_io_data; struct ufshpb_lu *hpb = map_req->hpb; struct ufshpb_subregion *srgn; unsigned long flags; -- cgit v1.2.3 From 8777dd9dff4020bba66654ec92e4b0ab6367ad30 Mon Sep 17 00:00:00 2001 From: Krishna Yarlagadda Date: Sat, 1 Oct 2022 17:51:44 +0530 Subject: spi: tegra210-quad: Fix combined sequence Return value should be updated to zero in combined sequence routine if transfer is completed successfully. Currently it holds timeout value resulting in errors. Signed-off-by: Krishna Yarlagadda Link: https://lore.kernel.org/r/20221001122148.9158-1-kyarlagadda@nvidia.com Signed-off-by: Mark Brown --- drivers/spi/spi-tegra210-quad.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index c89592b21ffc..904972606bd4 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -1157,6 +1157,11 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, msg->actual_length += xfer->len; transfer_phase++; } + if (!xfer->cs_change) { + tegra_qspi_transfer_end(spi); + spi_transfer_delay_exec(xfer); + } + ret = 0; exit: msg->status = ret; -- cgit v1.2.3 From 033d2d13a25113b6ffd24d72490f0e363dd3eb4c Mon Sep 17 00:00:00 2001 From: "Bird, Tim" Date: Mon, 3 Oct 2022 19:05:18 +0000 Subject: spi: spi-gxp: fix typo in SPDX identifier line Use '-' instead of '=' in identifier: "GPL-2.0-or-later" Signed-off-by: Tim Bird Link: https://lore.kernel.org/r/BYAPR13MB2503FF6412666D29FEAC8DCDFD5B9@BYAPR13MB2503.namprd13.prod.outlook.com Signed-off-by: Mark Brown --- drivers/spi/spi-gxp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-gxp.c b/drivers/spi/spi-gxp.c index 15b110183839..c900c2f39b57 100644 --- a/drivers/spi/spi-gxp.c +++ b/drivers/spi/spi-gxp.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0=or-later +// SPDX-License-Identifier: GPL-2.0-or-later /* Copyright (C) 2022 Hewlett-Packard Development Company, L.P. */ #include -- cgit v1.2.3 From b25fe93ff705cdd8e98ad8d0435c621ea5462c82 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 6 Oct 2022 07:35:12 +0200 Subject: spi: mpc52xx: Replace NO_IRQ by 0 NO_IRQ is used to check the return of irq_of_parse_and_map(). On some architecture NO_IRQ is 0, on other architectures it is -1. irq_of_parse_and_map() returns 0 on error, independent of NO_IRQ. So use 0 instead of using NO_IRQ. Signed-off-by: Christophe Leroy Link: https://lore.kernel.org/r/f41e09d710879726eacb98daedf16d0847303b9b.1665034444.git.christophe.leroy@csgroup.eu Signed-off-by: Mark Brown --- drivers/spi/spi-mpc52xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c index cb075c1acbee..7b64e64c65cf 100644 --- a/drivers/spi/spi-mpc52xx.c +++ b/drivers/spi/spi-mpc52xx.c @@ -151,7 +151,7 @@ mpc52xx_spi_fsmstate_idle(int irq, struct mpc52xx_spi *ms, u8 status, u8 data) int spr, sppr; u8 ctrl1; - if (status && (irq != NO_IRQ)) + if (status && irq) dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n", status); -- cgit v1.2.3 From 5302e1ff315b40dfc9bb3f08911f5a788cc1de01 Mon Sep 17 00:00:00 2001 From: Chin-Ting Kuo Date: Wed, 5 Oct 2022 16:32:09 +0800 Subject: spi: aspeed: Fix typo in mode_bits field for AST2600 platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both quad SPI TX and RX modes can be supported on AST2600. Correct typo in mode_bits field in both ast2600_fmc_data and ast2600_spi_data structs. Signed-off-by: Chin-Ting Kuo Reviewed-by: Cédric Le Goater Link: https://lore.kernel.org/r/20221005083209.222272-1-chin-ting_kuo@aspeedtech.com Signed-off-by: Mark Brown --- drivers/spi/spi-aspeed-smc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index a334e89add86..33cefcf18392 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -1163,7 +1163,7 @@ static const struct aspeed_spi_data ast2500_spi_data = { static const struct aspeed_spi_data ast2600_fmc_data = { .max_cs = 3, .hastype = false, - .mode_bits = SPI_RX_QUAD | SPI_RX_QUAD, + .mode_bits = SPI_RX_QUAD | SPI_TX_QUAD, .we0 = 16, .ctl0 = CE0_CTRL_REG, .timing = CE0_TIMING_COMPENSATION_REG, @@ -1178,7 +1178,7 @@ static const struct aspeed_spi_data ast2600_fmc_data = { static const struct aspeed_spi_data ast2600_spi_data = { .max_cs = 2, .hastype = false, - .mode_bits = SPI_RX_QUAD | SPI_RX_QUAD, + .mode_bits = SPI_RX_QUAD | SPI_TX_QUAD, .we0 = 16, .ctl0 = CE0_CTRL_REG, .timing = CE0_TIMING_COMPENSATION_REG, -- cgit v1.2.3 From 6a43cd02ddbc597dc9a1f82c1e433f871a2f6f06 Mon Sep 17 00:00:00 2001 From: Mauro Lima Date: Wed, 12 Oct 2022 12:21:35 -0300 Subject: spi: intel: Fix the offset to get the 64K erase opcode According to documentation, the 64K erase opcode is located in VSCC range [16:23] instead of [8:15]. Use the proper value to shift the mask over the correct range. Signed-off-by: Mauro Lima Reviewed-by: Mika Westerberg Link: https://lore.kernel.org/r/20221012152135.28353-1-mauro.lima@eclypsium.com Signed-off-by: Mark Brown --- drivers/spi/spi-intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c index 55f4ee2db002..605acb1bf4b0 100644 --- a/drivers/spi/spi-intel.c +++ b/drivers/spi/spi-intel.c @@ -114,7 +114,7 @@ #define ERASE_OPCODE_SHIFT 8 #define ERASE_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT) #define ERASE_64K_OPCODE_SHIFT 16 -#define ERASE_64K_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT) +#define ERASE_64K_OPCODE_MASK (0xff << ERASE_64K_OPCODE_SHIFT) /* Flash descriptor fields */ #define FLVALSIG_MAGIC 0x0ff0a55a -- cgit v1.2.3 From 83d18e9d9c0150d98dc24e3642ea93f5e245322c Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 13 Oct 2022 15:55:13 -0700 Subject: drm/msm/a6xx: Fix kvzalloc vs state_kcalloc usage adreno_show_object() is a trap! It will re-allocate the pointer it is passed on first call, when the data is ascii85 encoded, using kvmalloc/ kvfree(). Which means the data *passed* to it must be kvmalloc'd, ie. we cannot use the state_kcalloc() helper. This partially reverts commit ec8f1813bf8d ("drm/msm/a6xx: Replace kcalloc() with kvzalloc()"), but adds the missing kvfree() to fix the memory leak that was present previously. And adds a warning comment. Fixes: ec8f1813bf8d ("drm/msm/a6xx: Replace kcalloc() with kvzalloc()") Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/20 Signed-off-by: Rob Clark Reviewed-by: Chia-I Wu Reviewed-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/507014/ Link: https://lore.kernel.org/r/20221013225520.371226-2-robdclark@gmail.com --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 11 ++++++++++- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 7 ++++++- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 3c112a6cc8a2..730355f9e2d4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -819,7 +819,7 @@ static struct msm_gpu_state_bo *a6xx_snapshot_gmu_bo( snapshot->iova = bo->iova; snapshot->size = bo->size; - snapshot->data = state_kcalloc(a6xx_state, 1, snapshot->size); + snapshot->data = kvzalloc(snapshot->size, GFP_KERNEL); if (!snapshot->data) return NULL; @@ -1034,6 +1034,15 @@ static void a6xx_gpu_state_destroy(struct kref *kref) struct a6xx_gpu_state *a6xx_state = container_of(state, struct a6xx_gpu_state, base); + if (a6xx_state->gmu_log) + kvfree(a6xx_state->gmu_log->data); + + if (a6xx_state->gmu_hfi) + kvfree(a6xx_state->gmu_hfi->data); + + if (a6xx_state->gmu_debug) + kvfree(a6xx_state->gmu_debug->data); + list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node) kvfree(obj); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 382fb7f9e497..5a0e8491cd3a 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -729,7 +729,12 @@ static char *adreno_gpu_ascii85_encode(u32 *src, size_t len) return buf; } -/* len is expected to be in bytes */ +/* len is expected to be in bytes + * + * WARNING: *ptr should be allocated with kvmalloc or friends. It can be free'd + * with kvfree() and replaced with a newly kvmalloc'd buffer on the first call + * when the unencoded raw data is encoded + */ void adreno_show_object(struct drm_printer *p, void **ptr, int len, bool *encoded) { -- cgit v1.2.3 From fab384c496a313a1083554fb1eb2332a6756be2e Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 13 Oct 2022 15:55:14 -0700 Subject: drm/msm/a6xx: Skip snapshotting unused GMU buffers Some buffers are unused on certain sub-generations of a6xx. So just skip them. Signed-off-by: Rob Clark Reviewed-by: Chia-I Wu Reviewed-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/507013/ Link: https://lore.kernel.org/r/20221013225520.371226-3-robdclark@gmail.com --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 730355f9e2d4..b0124d0f286c 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -813,6 +813,9 @@ static struct msm_gpu_state_bo *a6xx_snapshot_gmu_bo( { struct msm_gpu_state_bo *snapshot; + if (!bo->size) + return NULL; + snapshot = state_kcalloc(a6xx_state, 1, sizeof(*snapshot)); if (!snapshot) return NULL; -- cgit v1.2.3 From ec4fbd791519423726ce9fd5130de9a95365c8eb Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 13 Oct 2022 15:55:15 -0700 Subject: drm/msm/a6xx: Remove state objects from list before freeing Technically it worked as it was before, only because it was using the _safe version of the iterator. But it is sloppy practice to leave dangling pointers. Signed-off-by: Rob Clark Reviewed-by: Chia-I Wu Reviewed-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/507017/ Link: https://lore.kernel.org/r/20221013225520.371226-4-robdclark@gmail.com --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index b0124d0f286c..a5c3d1ed255a 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -1046,8 +1046,10 @@ static void a6xx_gpu_state_destroy(struct kref *kref) if (a6xx_state->gmu_debug) kvfree(a6xx_state->gmu_debug->data); - list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node) + list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node) { + list_del(&obj->node); kvfree(obj); + } adreno_gpu_state_destroy(state); kfree(a6xx_state); -- cgit v1.2.3 From ccc40d42bd59ac858b58322775004613f1d805af Mon Sep 17 00:00:00 2001 From: Aashish Sharma Date: Tue, 11 Oct 2022 13:25:19 +0530 Subject: drm/msm: Remove redundant check for 'submit' Rectify the below smatch warning: drivers/gpu/drm/msm/msm_gem_submit.c:963 msm_ioctl_gem_submit() warn: variable dereferenced before check 'submit' 'submit' is normally error pointer or valid, so remove its NULL initializer as it's confusing and also remove a redundant check for it's value. Signed-off-by: Aashish Sharma Reported-by: kernel test robot Reported-by: Dan Carpenter Reviewed-by: Guenter Roeck Patchwork: https://patchwork.freedesktop.org/patch/506653/ Link: https://lore.kernel.org/r/20221011075519.3111928-1-shraash@google.com Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem_submit.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index c670591995e6..45a3e5cadc7d 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -706,7 +706,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct msm_drm_private *priv = dev->dev_private; struct drm_msm_gem_submit *args = data; struct msm_file_private *ctx = file->driver_priv; - struct msm_gem_submit *submit = NULL; + struct msm_gem_submit *submit; struct msm_gpu *gpu = priv->gpu; struct msm_gpu_submitqueue *queue; struct msm_ringbuffer *ring; @@ -946,8 +946,7 @@ out_unlock: put_unused_fd(out_fence_fd); mutex_unlock(&queue->lock); out_post_unlock: - if (submit) - msm_gem_submit_put(submit); + msm_gem_submit_put(submit); if (!IS_ERR_OR_NULL(post_deps)) { for (i = 0; i < args->nr_out_syncobjs; ++i) { kfree(post_deps[i].chain); -- cgit v1.2.3 From e0e86f25fd469ca76c1b50091372aed1ff99ca1a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 7 Oct 2022 21:23:38 +0100 Subject: drm/msm: Kconfig: Fix spelling mistake "throught" -> "through" There is a spelling mistake in a Kconfig description. Fix it. Signed-off-by: Colin Ian King Patchwork: https://patchwork.freedesktop.org/patch/506301/ Link: https://lore.kernel.org/r/20221007202338.2755731-1-colin.i.king@gmail.com Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 4e0cbd682725..3c9dfdb0b328 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -155,7 +155,7 @@ config DRM_MSM_HDMI Compile in support for the HDMI output MSM DRM driver. It can be a primary or a secondary display on device. Note that this is used only for the direct HDMI output. If the device outputs HDMI data - throught some kind of DSI-to-HDMI bridge, this option can be disabled. + through some kind of DSI-to-HDMI bridge, this option can be disabled. config DRM_MSM_HDMI_HDCP bool "Enable HDMI HDCP support in MSM DRM driver" -- cgit v1.2.3 From ac5408991ea6b06e29129b4d4861097c4c3e0d59 Mon Sep 17 00:00:00 2001 From: Aman Dhoot Date: Sat, 15 Oct 2022 20:41:17 -0700 Subject: Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI mode The device works fine in native RMI mode, there is no reason to use legacy PS/2 mode with it. Signed-off-by: Aman Dhoot Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index fa021af8506e..b0f776448a1c 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -192,6 +192,7 @@ static const char * const smbus_pnp_ids[] = { "SYN3221", /* HP 15-ay000 */ "SYN323d", /* HP Spectre X360 13-w013dx */ "SYN3257", /* HP Envy 13-ad105ng */ + "SYN3286", /* HP Laptop 15-da3001TU */ NULL }; -- cgit v1.2.3 From ca1c73628f5bd0c1ef6e46073cc3be2450605b06 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 14 Oct 2022 12:25:06 +0300 Subject: phy: stm32: fix an error code in probe If "index > usbphyc->nphys" is true then this returns success but it should return -EINVAL. Fixes: 94c358da3a05 ("phy: stm32: add support for STM32 USB PHY Controller (USBPHYC)") Signed-off-by: Dan Carpenter Reviewed-by: Amelie Delaunay Link: https://lore.kernel.org/r/Y0kq8j6S+5nDdMpr@kili Signed-off-by: Vinod Koul --- drivers/phy/st/phy-stm32-usbphyc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c index a98c911cc37a..5bb9647b078f 100644 --- a/drivers/phy/st/phy-stm32-usbphyc.c +++ b/drivers/phy/st/phy-stm32-usbphyc.c @@ -710,6 +710,8 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) ret = of_property_read_u32(child, "reg", &index); if (ret || index > usbphyc->nphys) { dev_err(&phy->dev, "invalid reg property: %d\n", ret); + if (!ret) + ret = -EINVAL; goto put_child; } -- cgit v1.2.3 From 2a4ea83bb8e54986703187edce59c9130a75eb26 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 10 Oct 2022 14:51:32 +0100 Subject: phy: tegra: xusb: Fix crash during pad power on/down Commit a88520bfc0ec ("usb: gadget: tegra: Reduce pad power") added calls to tegra_phy_xusb_utmi_pad_power_on/down in the Tegra XUDC driver to control the pad power. This change is causing a kernel panic when powering down the pads on entering suspend with the Jetson TX2 platform. The panic occurs because the 'xudc->curr_utmi_phy' is not configured on this platform and we do not check to see if the pointer is valid before attempting to deference the pointer. Fix this by checking to see if the 'phy' pointer passed to tegra_phy_xusb_utmi_pad_power_on/down is valid. Fixes: a88520bfc0ec ("usb: gadget: tegra: Reduce pad power") Signed-off-by: Jon Hunter Link: https://lore.kernel.org/r/20221010135132.30809-1-jonathanh@nvidia.com Signed-off-by: Vinod Koul --- drivers/phy/tegra/xusb.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 95091876c422..dce45fbbd699 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -1461,8 +1461,14 @@ EXPORT_SYMBOL_GPL(tegra_phy_xusb_utmi_port_reset); void tegra_phy_xusb_utmi_pad_power_on(struct phy *phy) { - struct tegra_xusb_lane *lane = phy_get_drvdata(phy); - struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra_xusb_lane *lane; + struct tegra_xusb_padctl *padctl; + + if (!phy) + return; + + lane = phy_get_drvdata(phy); + padctl = lane->pad->padctl; if (padctl->soc->ops->utmi_pad_power_on) padctl->soc->ops->utmi_pad_power_on(phy); @@ -1471,8 +1477,14 @@ EXPORT_SYMBOL_GPL(tegra_phy_xusb_utmi_pad_power_on); void tegra_phy_xusb_utmi_pad_power_down(struct phy *phy) { - struct tegra_xusb_lane *lane = phy_get_drvdata(phy); - struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra_xusb_lane *lane; + struct tegra_xusb_padctl *padctl; + + if (!phy) + return; + + lane = phy_get_drvdata(phy); + padctl = lane->pad->padctl; if (padctl->soc->ops->utmi_pad_power_down) padctl->soc->ops->utmi_pad_power_down(phy); -- cgit v1.2.3 From 0dec4d2f2636b9e54d9d29f17afc7687c5407f78 Mon Sep 17 00:00:00 2001 From: Shreeya Patel Date: Fri, 26 Aug 2022 17:53:52 +0530 Subject: iio: light: tsl2583: Fix module unloading tsl2583 probe() uses devm_iio_device_register() and calling iio_device_unregister() causes the unregister to occur twice. s Switch to iio_device_register() instead of devm_iio_device_register() in probe to avoid the device managed cleanup. Fixes: 371894f5d1a0 ("iio: tsl2583: add runtime power management support") Signed-off-by: Shreeya Patel Link: https://lore.kernel.org/r/20220826122352.288438-1-shreeya.patel@collabora.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2583.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index 0a2ca1a8146d..7bcb5c718922 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -858,7 +858,7 @@ static int tsl2583_probe(struct i2c_client *clientp, TSL2583_POWER_OFF_DELAY_MS); pm_runtime_use_autosuspend(&clientp->dev); - ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); + ret = iio_device_register(indio_dev); if (ret) { dev_err(&clientp->dev, "%s: iio registration failed\n", __func__); -- cgit v1.2.3 From 7578847b5949db3a75163908bd99c46d27e8b19f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 26 Sep 2022 12:10:37 +0300 Subject: iio: adc: mcp3911: fix sizeof() vs ARRAY_SIZE() bug This code uses sizeof() instead of ARRAY_SIZE() so it reads beyond the end of the mcp3911_osr_table[] array. Fixes: 6d965885f4ea ("iio: adc: mcp3911: add support for oversampling ratio") Signed-off-by: Dan Carpenter Reviewed-by: Marcus Folkesson Link: https://lore.kernel.org/r/YzFsjY3xLHUQMjVr@kili Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp3911.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c index b35fd2c9c3c0..015a9ffdb26a 100644 --- a/drivers/iio/adc/mcp3911.c +++ b/drivers/iio/adc/mcp3911.c @@ -248,7 +248,7 @@ static int mcp3911_write_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - for (int i = 0; i < sizeof(mcp3911_osr_table); i++) { + for (int i = 0; i < ARRAY_SIZE(mcp3911_osr_table); i++) { if (val == mcp3911_osr_table[i]) { val = FIELD_PREP(MCP3911_CONFIG_OSR, i); ret = mcp3911_update(adc, MCP3911_REG_CONFIG, MCP3911_CONFIG_OSR, -- cgit v1.2.3 From a83695a666eb3541873c3c9734ec4e1d10ca2d7f Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Tue, 27 Sep 2022 11:25:37 +0200 Subject: iio: adc: mcp3911: return proper error code on failure to allocate trigger smatch warnings: drivers/iio/adc/mcp3911.c:441 mcp3911_probe() warn: passing zero to 'PTR_ERR' Fixes: 08a65f61db69 ("iio: adc: mcp3911: add support for interrupts") Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Marcus Folkesson Link: https://lore.kernel.org/r/20220927092537.94663-1-marcus.folkesson@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp3911.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c index 015a9ffdb26a..7f0b37994fe5 100644 --- a/drivers/iio/adc/mcp3911.c +++ b/drivers/iio/adc/mcp3911.c @@ -496,7 +496,7 @@ static int mcp3911_probe(struct spi_device *spi) indio_dev->name, iio_device_id(indio_dev)); if (!adc->trig) - return PTR_ERR(adc->trig); + return -ENOMEM; adc->trig->ops = &mcp3911_trigger_ops; iio_trigger_set_drvdata(adc->trig, adc); -- cgit v1.2.3 From 815f1647a603a822d66630bbe22cab4bc097c8c3 Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Mon, 10 Oct 2022 21:46:41 +0200 Subject: iio: adc: mcp3911: use correct id bits The device ID should be shifted 6 bits to left according to datasheet. Fixes: 3a89b289df5d ("iio: adc: add support for mcp3911") Signed-off-by: Marcus Folkesson Link: https://lore.kernel.org/r/20221010194641.676484-1-marcus.folkesson@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp3911.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c index 7f0b37994fe5..f57f5eb23d49 100644 --- a/drivers/iio/adc/mcp3911.c +++ b/drivers/iio/adc/mcp3911.c @@ -55,8 +55,8 @@ /* Internal voltage reference in mV */ #define MCP3911_INT_VREF_MV 1200 -#define MCP3911_REG_READ(reg, id) ((((reg) << 1) | ((id) << 5) | (1 << 0)) & 0xff) -#define MCP3911_REG_WRITE(reg, id) ((((reg) << 1) | ((id) << 5) | (0 << 0)) & 0xff) +#define MCP3911_REG_READ(reg, id) ((((reg) << 1) | ((id) << 6) | (1 << 0)) & 0xff) +#define MCP3911_REG_WRITE(reg, id) ((((reg) << 1) | ((id) << 6) | (0 << 0)) & 0xff) #define MCP3911_NUM_CHANNELS 2 -- cgit v1.2.3 From aa6c77d05eb1c57ee5b95a7b83a39384c37df4d9 Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Mon, 10 Oct 2022 21:46:54 +0200 Subject: iio: adc: mcp3911: mask out device ID in debug prints The Device ID should not be included when printing register. Signed-off-by: Marcus Folkesson Link: https://lore.kernel.org/r/20221010194654.676525-1-marcus.folkesson@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp3911.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c index f57f5eb23d49..76b334f5ac61 100644 --- a/drivers/iio/adc/mcp3911.c +++ b/drivers/iio/adc/mcp3911.c @@ -57,6 +57,7 @@ #define MCP3911_REG_READ(reg, id) ((((reg) << 1) | ((id) << 6) | (1 << 0)) & 0xff) #define MCP3911_REG_WRITE(reg, id) ((((reg) << 1) | ((id) << 6) | (0 << 0)) & 0xff) +#define MCP3911_REG_MASK GENMASK(4, 1) #define MCP3911_NUM_CHANNELS 2 @@ -89,8 +90,8 @@ static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len) be32_to_cpus(val); *val >>= ((4 - len) * 8); - dev_dbg(&adc->spi->dev, "reading 0x%x from register 0x%x\n", *val, - reg >> 1); + dev_dbg(&adc->spi->dev, "reading 0x%x from register 0x%lx\n", *val, + FIELD_GET(MCP3911_REG_MASK, reg)); return ret; } -- cgit v1.2.3 From 174dac5dc800e4e2e4552baf6340846a344d01a3 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 12 Oct 2022 16:21:58 +0200 Subject: iio: adc: stm32-adc: fix channel sampling time init Fix channel init for ADC generic channel bindings. In generic channel initialization, stm32_adc_smpr_init() is called to initialize channel sampling time. The "st,min-sample-time-ns" property is an optional property. If it is not defined, stm32_adc_smpr_init() is currently skipped. However stm32_adc_smpr_init() must always be called, to force a minimum sampling time for the internal channels, as the minimum sampling time is known. Make stm32_adc_smpr_init() call unconditional. Fixes: 796e5d0b1e9b ("iio: adc: stm32-adc: use generic binding for sample-time") Signed-off-by: Olivier Moysan Reviewed-by: Andy Shevchenko Reviewed-by: Fabrice Gasnier Link: https://lore.kernel.org/r/20221012142205.13041-2-olivier.moysan@foss.st.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 6256977eb7f7..3cda529f081d 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -2086,18 +2086,19 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev, stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val, vin[1], scan_index, differential); + val = 0; ret = fwnode_property_read_u32(child, "st,min-sample-time-ns", &val); /* st,min-sample-time-ns is optional */ - if (!ret) { - stm32_adc_smpr_init(adc, channels[scan_index].channel, val); - if (differential) - stm32_adc_smpr_init(adc, vin[1], val); - } else if (ret != -EINVAL) { + if (ret && ret != -EINVAL) { dev_err(&indio_dev->dev, "Invalid st,min-sample-time-ns property %d\n", ret); goto err; } + stm32_adc_smpr_init(adc, channels[scan_index].channel, val); + if (differential) + stm32_adc_smpr_init(adc, vin[1], val); + scan_index++; } -- cgit v1.2.3 From 4132f19173211856d35180958d2754f5c56d520a Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Fri, 14 Oct 2022 15:37:22 +0300 Subject: iio: temperature: ltc2983: allocate iio channels once Currently, every time the device wakes up from sleep, the iio_chan array is reallocated, leaking the previous one until the device is removed (basically never). Move the allocation to the probe function to avoid this. Signed-off-by: Cosmin Tanislav Fixes: f110f3188e563 ("iio: temperature: Add support for LTC2983") Cc: Link: https://lore.kernel.org/r/20221014123724.1401011-2-demonsingur@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/ltc2983.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c index b652d2b39bcf..a60ccf183687 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -1385,13 +1385,6 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio) return ret; } - st->iio_chan = devm_kzalloc(&st->spi->dev, - st->iio_channels * sizeof(*st->iio_chan), - GFP_KERNEL); - - if (!st->iio_chan) - return -ENOMEM; - ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG, LTC2983_NOTCH_FREQ_MASK, LTC2983_NOTCH_FREQ(st->filter_notch_freq)); @@ -1514,6 +1507,12 @@ static int ltc2983_probe(struct spi_device *spi) gpiod_set_value_cansleep(gpio, 0); } + st->iio_chan = devm_kzalloc(&spi->dev, + st->iio_channels * sizeof(*st->iio_chan), + GFP_KERNEL); + if (!st->iio_chan) + return -ENOMEM; + ret = ltc2983_setup(st, true); if (ret) return ret; -- cgit v1.2.3 From 54246b9034da08087ceb2083478c0d13403e12b4 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 3 Oct 2022 11:11:33 +0300 Subject: iio: at91-sama5d2_adc: Fix unsafe buffer attributes The iio_triggered_buffer_setup_ext() was changed by commit 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") to silently expect that all attributes given in buffer_attrs array are device-attributes. This expectation was not forced by the API - and some drivers did register attributes created by IIO_CONST_ATTR(). The added attribute "wrapping" does not copy the pointer to stored string constant and when the sysfs file is read the kernel will access to invalid location. Change the IIO_CONST_ATTRs from the driver to IIO_DEVICE_ATTR in order to prevent the invalid memory access. Signed-off-by: Matti Vaittinen Fixes: 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") Tested-by: Claudiu Beznea Link: https://lore.kernel.org/r/be69775aa302159f088b8b91894e6ec449bca65b.1664782676.git.mazziesaccount@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 4294d6539cdb..33e251552214 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -2193,17 +2193,30 @@ static ssize_t at91_adc_get_watermark(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%d\n", st->dma_st.watermark); } +static ssize_t hwfifo_watermark_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", "2"); +} + +static ssize_t hwfifo_watermark_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", AT91_HWFIFO_MAX_SIZE_STR); +} + static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, at91_adc_get_fifo_state, NULL, 0); static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, at91_adc_get_watermark, NULL, 0); - -static IIO_CONST_ATTR(hwfifo_watermark_min, "2"); -static IIO_CONST_ATTR(hwfifo_watermark_max, AT91_HWFIFO_MAX_SIZE_STR); +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0); +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); static const struct attribute *at91_adc_fifo_attributes[] = { - &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, - &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, &iio_dev_attr_hwfifo_watermark.dev_attr.attr, &iio_dev_attr_hwfifo_enabled.dev_attr.attr, NULL, -- cgit v1.2.3 From ab0ee36e90f611f32c3a53afe9dc743de48138e2 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 3 Oct 2022 11:10:51 +0300 Subject: iio: adxl372: Fix unsafe buffer attributes The iio_triggered_buffer_setup_ext() was changed by commit 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") to silently expect that all attributes given in buffer_attrs array are device-attributes. This expectation was not forced by the API - and some drivers did register attributes created by IIO_CONST_ATTR(). The added attribute "wrapping" does not copy the pointer to stored string constant and when the sysfs file is read the kernel will access to invalid location. Change the IIO_CONST_ATTRs from the driver to IIO_DEVICE_ATTR in order to prevent the invalid memory access. Signed-off-by: Matti Vaittinen Fixes: 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") Cc: Link: https://lore.kernel.org/r/19158499623cdf7f9c5efae1f13c9f1a918ff75f.1664782676.git.mazziesaccount@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adxl372.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index e3ecbaee61f7..bc53af809d5d 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -998,17 +998,30 @@ static ssize_t adxl372_get_fifo_watermark(struct device *dev, return sprintf(buf, "%d\n", st->watermark); } -static IIO_CONST_ATTR(hwfifo_watermark_min, "1"); -static IIO_CONST_ATTR(hwfifo_watermark_max, - __stringify(ADXL372_FIFO_SIZE)); +static ssize_t hwfifo_watermark_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", "1"); +} + +static ssize_t hwfifo_watermark_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", __stringify(ADXL372_FIFO_SIZE)); +} + +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0); +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, adxl372_get_fifo_watermark, NULL, 0); static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, adxl372_get_fifo_enabled, NULL, 0); static const struct attribute *adxl372_fifo_attributes[] = { - &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, - &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, &iio_dev_attr_hwfifo_watermark.dev_attr.attr, &iio_dev_attr_hwfifo_enabled.dev_attr.attr, NULL, -- cgit v1.2.3 From 5e23b33d1e84f04c80da6f1d89cbb3d3a3f81e01 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 3 Oct 2022 11:10:29 +0300 Subject: iio: adxl367: Fix unsafe buffer attributes The devm_iio_kfifo_buffer_setup_ext() was changed by commit 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") to silently expect that all attributes given in buffer_attrs array are device-attributes. This expectation was not forced by the API - and some drivers did register attributes created by IIO_CONST_ATTR(). The added attribute "wrapping" does not copy the pointer to stored string constant and when the sysfs file is read the kernel will access to invalid location. Change the IIO_CONST_ATTRs from the driver to IIO_DEVICE_ATTR in order to prevent the invalid memory access. Signed-off-by: Matti Vaittinen Fixes: 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") Cc: Link: https://lore.kernel.org/r/2e2d9ec34fb1df8ab8e2749199822db8cc91d302.1664782676.git.mazziesaccount@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adxl367.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/adxl367.c b/drivers/iio/accel/adxl367.c index 47feb375b70b..7c7d78040793 100644 --- a/drivers/iio/accel/adxl367.c +++ b/drivers/iio/accel/adxl367.c @@ -1185,17 +1185,30 @@ static ssize_t adxl367_get_fifo_watermark(struct device *dev, return sysfs_emit(buf, "%d\n", fifo_watermark); } -static IIO_CONST_ATTR(hwfifo_watermark_min, "1"); -static IIO_CONST_ATTR(hwfifo_watermark_max, - __stringify(ADXL367_FIFO_MAX_WATERMARK)); +static ssize_t hwfifo_watermark_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", "1"); +} + +static ssize_t hwfifo_watermark_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", __stringify(ADXL367_FIFO_MAX_WATERMARK)); +} + +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0); +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, adxl367_get_fifo_watermark, NULL, 0); static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, adxl367_get_fifo_enabled, NULL, 0); static const struct attribute *adxl367_fifo_attributes[] = { - &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, - &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, &iio_dev_attr_hwfifo_watermark.dev_attr.attr, &iio_dev_attr_hwfifo_enabled.dev_attr.attr, NULL, -- cgit v1.2.3 From a10a0f385ab8af08ddb762ac3eca11e1b6d1fe69 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 3 Oct 2022 11:11:12 +0300 Subject: iio: bmc150-accel-core: Fix unsafe buffer attributes The iio_triggered_buffer_setup_ext() was changed by commit 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") to silently expect that all attributes given in buffer_attrs array are device-attributes. This expectation was not forced by the API - and some drivers did register attributes created by IIO_CONST_ATTR(). The added attribute "wrapping" does not copy the pointer to stored string constant and when the sysfs file is read the kernel will access to invalid location. Change the IIO_CONST_ATTRs from the driver to IIO_DEVICE_ATTR in order to prevent the invalid memory access. Signed-off-by: Matti Vaittinen Fixes: 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") Link: https://lore.kernel.org/r/cf8a56658fc38db8bed64f456d898f5ad5a2814f.1664782676.git.mazziesaccount@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel-core.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 57e8a8350cd1..92f8b139acce 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -925,17 +925,30 @@ static const struct iio_chan_spec_ext_info bmc150_accel_ext_info[] = { { } }; -static IIO_CONST_ATTR(hwfifo_watermark_min, "1"); -static IIO_CONST_ATTR(hwfifo_watermark_max, - __stringify(BMC150_ACCEL_FIFO_LENGTH)); +static ssize_t hwfifo_watermark_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", "1"); +} + +static ssize_t hwfifo_watermark_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", __stringify(BMC150_ACCEL_FIFO_LENGTH)); +} + +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0); +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); static IIO_DEVICE_ATTR(hwfifo_enabled, S_IRUGO, bmc150_accel_get_fifo_state, NULL, 0); static IIO_DEVICE_ATTR(hwfifo_watermark, S_IRUGO, bmc150_accel_get_fifo_watermark, NULL, 0); static const struct attribute *bmc150_accel_fifo_attributes[] = { - &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, - &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, &iio_dev_attr_hwfifo_watermark.dev_attr.attr, &iio_dev_attr_hwfifo_enabled.dev_attr.attr, NULL, -- cgit v1.2.3 From 17747577bbcb496e1b1c4096d64c2fc1e7bc0fef Mon Sep 17 00:00:00 2001 From: Siarhei Volkau Date: Sun, 16 Oct 2022 18:35:48 +0300 Subject: pinctrl: Ingenic: JZ4755 bug fixes Fixes UART1 function bits and MMC groups typo. For pins 0x97,0x99 function 0 is designated to PWM3/PWM5 respectively, function is 1 designated to the UART1. Diff from v1: - sent separately - added tag Fixes Cc: stable@vger.kernel.org Fixes: b582b5a434d3 ("pinctrl: Ingenic: Add pinctrl driver for JZ4755.") Tested-by: Siarhei Volkau Signed-off-by: Siarhei Volkau Link: https://lore.kernel.org/r/20221016153548.3024209-1-lis8215@gmail.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ingenic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 7e732076dedf..9e46d83e5138 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -667,7 +667,7 @@ static u8 jz4755_lcd_24bit_funcs[] = { 1, 1, 1, 1, 0, 0, }; static const struct group_desc jz4755_groups[] = { INGENIC_PIN_GROUP("uart0-data", jz4755_uart0_data, 0), INGENIC_PIN_GROUP("uart0-hwflow", jz4755_uart0_hwflow, 0), - INGENIC_PIN_GROUP("uart1-data", jz4755_uart1_data, 0), + INGENIC_PIN_GROUP("uart1-data", jz4755_uart1_data, 1), INGENIC_PIN_GROUP("uart2-data", jz4755_uart2_data, 1), INGENIC_PIN_GROUP("ssi-dt-b", jz4755_ssi_dt_b, 0), INGENIC_PIN_GROUP("ssi-dt-f", jz4755_ssi_dt_f, 0), @@ -721,7 +721,7 @@ static const char *jz4755_ssi_groups[] = { "ssi-ce1-b", "ssi-ce1-f", }; static const char *jz4755_mmc0_groups[] = { "mmc0-1bit", "mmc0-4bit", }; -static const char *jz4755_mmc1_groups[] = { "mmc0-1bit", "mmc0-4bit", }; +static const char *jz4755_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", }; static const char *jz4755_i2c_groups[] = { "i2c-data", }; static const char *jz4755_cim_groups[] = { "cim-data", }; static const char *jz4755_lcd_groups[] = { -- cgit v1.2.3 From 406e14808ee695cbae1eafa5fd3ac563c29470ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=B6hle?= Date: Thu, 13 Oct 2022 11:16:37 +0000 Subject: mmc: block: Remove error check of hw_reset on reset Before switching back to the right partition in mmc_blk_reset there used to be a check if hw_reset was even supported. This return value was removed, so there is no reason to check. Furthermore ensure part_curr is not falsely set to a valid value on reset or partition switch error. As part of this change the code paths of mmc_blk_reset calls were checked to ensure no commands are issued after a failed mmc_blk_reset directly without going through the block layer. Fixes: fefdd3c91e0a ("mmc: core: Drop superfluous validations in mmc_hw|sw_reset()") Cc: stable@vger.kernel.org Signed-off-by: Christian Loehle Reviewed-by: Adrian Hunter Link: https://lore.kernel.org/r/e91be6199d04414a91e20611c81bfe1d@hyperstone.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 54cd009aee50..db6d8a099910 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -134,6 +134,7 @@ struct mmc_blk_data { * track of the current selected device partition. */ unsigned int part_curr; +#define MMC_BLK_PART_INVALID UINT_MAX /* Unknown partition active */ int area_type; /* debugfs files (only in main mmc_blk_data) */ @@ -987,33 +988,39 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host, return ms; } +/* + * Attempts to reset the card and get back to the requested partition. + * Therefore any error here must result in cancelling the block layer + * request, it must not be reattempted without going through the mmc_blk + * partition sanity checks. + */ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, int type) { int err; + struct mmc_blk_data *main_md = dev_get_drvdata(&host->card->dev); if (md->reset_done & type) return -EEXIST; md->reset_done |= type; err = mmc_hw_reset(host->card); + /* + * A successful reset will leave the card in the main partition, but + * upon failure it might not be, so set it to MMC_BLK_PART_INVALID + * in that case. + */ + main_md->part_curr = err ? MMC_BLK_PART_INVALID : main_md->part_type; + if (err) + return err; /* Ensure we switch back to the correct partition */ - if (err) { - struct mmc_blk_data *main_md = - dev_get_drvdata(&host->card->dev); - int part_err; - - main_md->part_curr = main_md->part_type; - part_err = mmc_blk_part_switch(host->card, md->part_type); - if (part_err) { - /* - * We have failed to get back into the correct - * partition, so we need to abort the whole request. - */ - return -ENODEV; - } - } - return err; + if (mmc_blk_part_switch(host->card, md->part_type)) + /* + * We have failed to get back into the correct + * partition, so we need to abort the whole request. + */ + return -ENODEV; + return 0; } static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) @@ -1871,8 +1878,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) return; /* Reset before last retry */ - if (mqrq->retries + 1 == MMC_MAX_RETRIES) - mmc_blk_reset(md, card->host, type); + if (mqrq->retries + 1 == MMC_MAX_RETRIES && + mmc_blk_reset(md, card->host, type)) + return; /* Command errors fail fast, so use all MMC_MAX_RETRIES */ if (brq->sbc.error || brq->cmd.error) -- cgit v1.2.3 From 339e3eb1facd18a98ceb1171d70674780e5014a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=B6hle?= Date: Fri, 7 Oct 2022 15:43:52 +0000 Subject: mmc: queue: Cancel recovery work on cleanup To prevent any recovery work running after the queue cleanup cancel it. Any recovery running post-cleanup dereferenced mq->card as NULL and was not meaningful to begin with. Cc: stable@vger.kernel.org Signed-off-by: Christian Loehle Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/c865c0c9789d428494b67b820a78923e@hyperstone.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/queue.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index fefaa901b50f..86be55d7cf55 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -493,6 +493,13 @@ void mmc_cleanup_queue(struct mmc_queue *mq) if (blk_queue_quiesced(q)) blk_mq_unquiesce_queue(q); + /* + * If the recovery completes the last (and only remaining) request in + * the queue, and the card has been removed, we could end up here with + * the recovery not quite finished yet, so cancel it. + */ + cancel_work_sync(&mq->recovery_work); + blk_mq_free_tag_set(&mq->tag_set); /* -- cgit v1.2.3 From 1ed5c3b22fc78735c539e4767832aea58db6761c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 13 Oct 2022 11:32:48 +0200 Subject: mmc: sdhci-esdhc-imx: Propagate ESDHC_FLAG_HS400* only on 8bit bus The core issues the warning "drop HS400 support since no 8-bit bus" when one of the ESDHC_FLAG_HS400* flags is set on a non 8bit capable host. To avoid this warning set these flags only on hosts that actually can do 8bit, i.e. have bus-width = <8> set in the device tree. Signed-off-by: Sascha Hauer Reviewed-by: Haibo Chen Fixes: 029e2476f9e6 ("mmc: sdhci-esdhc-imx: add HS400_ES support for i.MX8QXP") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221013093248.2220802-1-s.hauer@pengutronix.de Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 55981b0f0b10..747df79d90ee 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1660,6 +1660,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) host->mmc_host_ops.execute_tuning = usdhc_execute_tuning; } + err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); + if (err) + goto disable_ahb_clk; + if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) sdhci_esdhc_ops.platform_execute_tuning = esdhc_executing_tuning; @@ -1667,13 +1671,15 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; - if (imx_data->socdata->flags & ESDHC_FLAG_HS400) + if (host->caps & MMC_CAP_8_BIT_DATA && + imx_data->socdata->flags & ESDHC_FLAG_HS400) host->mmc->caps2 |= MMC_CAP2_HS400; if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; - if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { + if (host->caps & MMC_CAP_8_BIT_DATA && + imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { host->mmc->caps2 |= MMC_CAP2_HS400_ES; host->mmc_host_ops.hs400_enhanced_strobe = esdhc_hs400_enhanced_strobe; @@ -1695,10 +1701,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) goto disable_ahb_clk; } - err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); - if (err) - goto disable_ahb_clk; - sdhci_esdhc_imx_hwinit(host); err = sdhci_add_host(host); -- cgit v1.2.3 From 9dc0033e4658d6f9d9952c3c0c6be3ec25bc2985 Mon Sep 17 00:00:00 2001 From: Patrick Thompson Date: Thu, 13 Oct 2022 17:00:17 -0400 Subject: mmc: sdhci-pci-core: Disable ES for ASUS BIOS on Jasper Lake Enhanced Strobe (ES) does not work correctly on the ASUS 1100 series of devices. Jasper Lake eMMCs (pci_id 8086:4dc4) are supposed to support ES. There are also two system families under the series, thus this is being scoped to the ASUS BIOS. The failing ES prevents the installer from writing to disk. Falling back to HS400 without ES fixes the issue. Signed-off-by: Patrick Thompson Fixes: 315e3bd7ac19 ("mmc: sdhci-pci: Add support for Intel JSL") Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221013210017.3751025-1-ptf@google.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-core.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 169b84761041..34ea1acbb3cc 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -914,6 +914,12 @@ static bool glk_broken_cqhci(struct sdhci_pci_slot *slot) dmi_match(DMI_SYS_VENDOR, "IRBIS")); } +static bool jsl_broken_hs400es(struct sdhci_pci_slot *slot) +{ + return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_JSL_EMMC && + dmi_match(DMI_BIOS_VENDOR, "ASUSTeK COMPUTER INC."); +} + static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot) { int ret = byt_emmc_probe_slot(slot); @@ -922,9 +928,11 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot) slot->host->mmc->caps2 |= MMC_CAP2_CQE; if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) { - slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES; - slot->host->mmc_host_ops.hs400_enhanced_strobe = - intel_hs400_enhanced_strobe; + if (!jsl_broken_hs400es(slot)) { + slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES; + slot->host->mmc_host_ops.hs400_enhanced_strobe = + intel_hs400_enhanced_strobe; + } slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD; } -- cgit v1.2.3 From 9972e6b404884adae9eec7463e30d9b3c9a70b18 Mon Sep 17 00:00:00 2001 From: Matthew Ma Date: Fri, 14 Oct 2022 11:49:51 +0800 Subject: mmc: core: Fix kernel panic when remove non-standard SDIO card SDIO tuple is only allocated for standard SDIO card, especially it causes memory corruption issues when the non-standard SDIO card has removed, which is because the card device's reference counter does not increase for it at sdio_init_func(), but all SDIO card device reference counter gets decreased at sdio_release_func(). Fixes: 6f51be3d37df ("sdio: allow non-standard SDIO cards") Signed-off-by: Matthew Ma Reviewed-by: Weizhao Ouyang Reviewed-by: John Wang Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221014034951.2300386-1-ouyangweizhao@zeku.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_bus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index c6268c38c69e..babf21a0adeb 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -291,7 +291,8 @@ static void sdio_release_func(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); - sdio_free_func_cis(func); + if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO)) + sdio_free_func_cis(func); kfree(func->info); kfree(func->tmpbuf); -- cgit v1.2.3 From d21f4b7ffc22c009da925046b69b15af08de9d75 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Fri, 14 Oct 2022 10:33:18 -0700 Subject: pinctrl: qcom: Avoid glitching lines when we first mux to output Back in the description of commit e440e30e26dd ("arm64: dts: qcom: sc7180: Avoid glitching SPI CS at bootup on trogdor") we described a problem that we were seeing on trogdor devices. I'll re-summarize here but you can also re-read the original commit. On trogdor devices, the BIOS is setting up the SPI chip select as: - mux special function (SPI chip select) - output enable - output low (unused because we've muxed as special function) In the kernel, however, we've moved away from using the chip select line as special function. Since the kernel wants to fully control the chip select it's far more efficient to treat the line as a GPIO rather than sending packet-like commands to the GENI firmware every time we want the line to toggle. When we transition from how the BIOS had the pin configured to how the kernel has the pin configured we end up glitching the line. That's because we _first_ change the mux of the line and then later set its output. This glitch is bad and can confuse the device on the other end of the line. The old commit e440e30e26dd ("arm64: dts: qcom: sc7180: Avoid glitching SPI CS at bootup on trogdor") fixed the glitch, though the solution was far from elegant. It essentially did the thing that everyone always hates: encoding a sequential program in device tree, even if it's a simple one. It also, unfortunately, got broken by commit b991f8c3622c ("pinctrl: core: Handling pinmux and pinconf separately"). After that commit we did all the muxing _first_ even though the config (set the pin to output high) was listed first. :( I looked at ideas for how to solve this more properly. My first thought was to use the "init" pinctrl state. In theory the "init" pinctrl state is supposed to be exactly for achieving glitch-free transitions. My dream would have been for the "init" pinctrl to do nothing at all. That would let us delay the automatic pin muxing until the driver could set things up and call pinctrl_init_done(). In other words, my dream was: /* Request the GPIO; init it 1 (because DT says GPIO_ACTIVE_LOW) */ devm_gpiod_get_index(dev, "cs", GPIOD_OUT_LOW); /* Output should be right, so we can remux, yay! */ pinctrl_init_done(dev); Unfortunately, it didn't work out. The primary reason is that the MSM GPIO driver implements gpio_request_enable(). As documented in pinmux.h, that function automatically remuxes a line as a GPIO. ...and it does this remuxing _before_ specifying the output of the pin. You can see in gpiod_get_index() that we call gpiod_request() before gpiod_configure_flags(). gpiod_request() isn't passed any flags so it has no idea what the eventual output will be. We could have debates about whether or not the automatic remuxing to GPIO for the MSM pinctrl was a good idea or not, but at this point I think there is a plethora of code that's relying on it and I certainly wouldn't suggest changing it. Alternatively, we could try to come up with a way to pass the initial output state to gpio_request_enable() and plumb all that through. That seems like it would be doable, but we'd have to plumb it through several layers in the stack. This patch implements yet another alternative. Here, we specifically avoid glitching the first time a pin is muxed to GPIO function if the direction of the pin is output. The idea is that we can read the state of the pin before we set the mux and make sure that the re-mux won't change the state. NOTES: - We only do this the first time since later swaps between mux states might want to preserve the old output value. In other words, I wouldn't want to break a driver that did: gpiod_set_value(g, 1); pinctrl_select_state(pinctrl, special_state); pinctrl_select_default_state(); /* We should be driving 1 even if "special_state" made the pin 0 */ - It's safe to do this the first time since the driver _couldn't_ have explicitly set a state. In order to even be able to control the GPIO (at least using gpiod) we have to have requested it which would have counted as the first mux. - In theory, instead of keeping track of the first time a pin was set as a GPIO we could enable the glitch-free behavior only when msm_pinmux_request_gpio() is in the callchain. That works an enables my "dream" implementation above where we use an "init" state to solve this. However, it's nice not to have to do this. By handling just the first transition to GPIO we can simply let the normal "default" remuxing happen and we can be assured that there won't be a glitch. Before this change I could see the glitch reported on the EC console when booting. It would say this when booting the kernel: Unexpected state 1 in CSNRE ISR After this change there is no error reported. Note that I haven't reproduced the original problem described in e440e30e26dd ("arm64: dts: qcom: sc7180: Avoid glitching SPI CS at bootup on trogdor") but I could believe it might happen in certain timing conditions. Fixes: b991f8c3622c ("pinctrl: core: Handling pinmux and pinconf separately") Signed-off-by: Douglas Anderson Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20221014103217.1.I656bb2c976ed626e5d37294eb252c1cf3be769dc@changeid Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-msm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index a2abfe987ab1..8bf8b21954fe 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -51,6 +51,7 @@ * detection. * @skip_wake_irqs: Skip IRQs that are handled by wakeup interrupt controller * @disabled_for_mux: These IRQs were disabled because we muxed away. + * @ever_gpio: This bit is set the first time we mux a pin to gpio_func. * @soc: Reference to soc_data of platform specific data. * @regs: Base addresses for the TLMM tiles. * @phys_base: Physical base address @@ -72,6 +73,7 @@ struct msm_pinctrl { DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO); DECLARE_BITMAP(skip_wake_irqs, MAX_NR_GPIO); DECLARE_BITMAP(disabled_for_mux, MAX_NR_GPIO); + DECLARE_BITMAP(ever_gpio, MAX_NR_GPIO); const struct msm_pinctrl_soc_data *soc; void __iomem *regs[MAX_NR_TILES]; @@ -218,6 +220,25 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev, val = msm_readl_ctl(pctrl, g); + /* + * If this is the first time muxing to GPIO and the direction is + * output, make sure that we're not going to be glitching the pin + * by reading the current state of the pin and setting it as the + * output. + */ + if (i == gpio_func && (val & BIT(g->oe_bit)) && + !test_and_set_bit(group, pctrl->ever_gpio)) { + u32 io_val = msm_readl_io(pctrl, g); + + if (io_val & BIT(g->in_bit)) { + if (!(io_val & BIT(g->out_bit))) + msm_writel_io(io_val | BIT(g->out_bit), pctrl, g); + } else { + if (io_val & BIT(g->out_bit)) + msm_writel_io(io_val & ~BIT(g->out_bit), pctrl, g); + } + } + if (egpio_func && i == egpio_func) { if (val & BIT(g->egpio_present)) val &= ~BIT(g->egpio_enable); -- cgit v1.2.3 From b40af6183b685b0cf7870987b858de0d48db9ea0 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 6 Oct 2022 21:48:19 +0200 Subject: spi: qup: support using GPIO as chip select line Most of the device with QUP SPI adapter are actually using GPIO-s for chip select. However, this stopped working after ("spi: Retire legacy GPIO handling") as it introduced a check on ->use_gpio_descriptors flag and since spi-qup driver does not set the flag it meant that all of boards using GPIO-s and with QUP adapter SPI devices stopped working. So, to enable using GPIO-s again set ->use_gpio_descriptors to true and populate ->max_native_cs. Fixes: f48dc6b96649 ("spi: Retire legacy GPIO handling") Signed-off-by: Robert Marko Cc: luka.perkov@sartura.hr Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20221006194819.1536932-1-robert.marko@sartura.hr Signed-off-by: Mark Brown --- drivers/spi/spi-qup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 7d89510dc3f0..678dc51ef017 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -1057,6 +1057,8 @@ static int spi_qup_probe(struct platform_device *pdev) else master->num_chipselect = num_cs; + master->use_gpio_descriptors = true; + master->max_native_cs = SPI_NUM_CHIPSELECTS; master->bus_num = pdev->id; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); -- cgit v1.2.3 From 472a1482325b3a285e0bcf82c0b0edc689b7e8cd Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Sun, 2 Oct 2022 08:04:19 -0400 Subject: counter: Reduce DEFINE_COUNTER_ARRAY_POLARITY() to defining counter_array A spare warning was reported for drivers/counter/ti-ecap-capture.c:: sparse warnings: (new ones prefixed by >>) >> drivers/counter/ti-ecap-capture.c:380:8: sparse: sparse: symbol 'ecap_cnt_pol_array' was not declared. Should it be static? vim +/ecap_cnt_pol_array +380 drivers/counter/ti-ecap-capture.c 379 > 380 static DEFINE_COUNTER_ARRAY_POLARITY(ecap_cnt_pol_array, ecap_cnt_pol_avail, ECAP_NB_CEVT); 381 The first argument to the DEFINE_COUNTER_ARRAY_POLARITY() macro is a token serving as the symbol name in the definition of a new struct counter_array structure. However, this macro actually expands to two statements:: #define DEFINE_COUNTER_ARRAY_POLARITY(_name, _enums, _length) \ DEFINE_COUNTER_AVAILABLE(_name##_available, _enums); \ struct counter_array _name = { \ .type = COUNTER_COMP_SIGNAL_POLARITY, \ .avail = &(_name##_available), \ .length = (_length), \ } Because of this, the "static" on line 380 only applies to the first statement. This patch splits out the DEFINE_COUNTER_AVAILABLE() line and leaves DEFINE_COUNTER_ARRAY_POLARITY() as a simple structure definition to avoid issues like this. Reported-by: kernel test robot Link: https://lore.kernel.org/all/202210020619.NQbyomII-lkp@intel.com/ Cc: Julien Panis Signed-off-by: William Breathitt Gray --- drivers/counter/ti-ecap-capture.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/counter/ti-ecap-capture.c b/drivers/counter/ti-ecap-capture.c index af10de30aba5..b8dbf0212a8e 100644 --- a/drivers/counter/ti-ecap-capture.c +++ b/drivers/counter/ti-ecap-capture.c @@ -377,7 +377,8 @@ static const enum counter_signal_polarity ecap_cnt_pol_avail[] = { COUNTER_SIGNAL_POLARITY_NEGATIVE, }; -static DEFINE_COUNTER_ARRAY_POLARITY(ecap_cnt_pol_array, ecap_cnt_pol_avail, ECAP_NB_CEVT); +static DEFINE_COUNTER_AVAILABLE(ecap_cnt_pol_available, ecap_cnt_pol_avail); +static DEFINE_COUNTER_ARRAY_POLARITY(ecap_cnt_pol_array, ecap_cnt_pol_available, ECAP_NB_CEVT); static struct counter_comp ecap_cnt_signal_ext[] = { COUNTER_COMP_ARRAY_POLARITY(ecap_cnt_pol_read, ecap_cnt_pol_write, ecap_cnt_pol_array), -- cgit v1.2.3 From ec0286dce78c3bb0e6a665c0baade2f2db56ce00 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 12 Oct 2022 17:51:25 +0300 Subject: counter: ti-ecap-capture: fix IS_ERR() vs NULL check The devm_counter_alloc() function returns NULL on error. It doesn't return error pointers. Fixes: 4e2f42aa00b6 ("counter: ti-ecap-capture: capture driver support for ECAP") Signed-off-by: Dan Carpenter Reviewed-by: Julien Panis Acked-by: Vignesh Raghavendra Link: https://lore.kernel.org/r/Y0bUbZvfDJHBG9C6@kili/ Signed-off-by: William Breathitt Gray --- drivers/counter/ti-ecap-capture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/counter/ti-ecap-capture.c b/drivers/counter/ti-ecap-capture.c index b8dbf0212a8e..fb1cb1774674 100644 --- a/drivers/counter/ti-ecap-capture.c +++ b/drivers/counter/ti-ecap-capture.c @@ -480,8 +480,8 @@ static int ecap_cnt_probe(struct platform_device *pdev) int ret; counter_dev = devm_counter_alloc(dev, sizeof(*ecap_dev)); - if (IS_ERR(counter_dev)) - return PTR_ERR(counter_dev); + if (!counter_dev) + return -ENOMEM; counter_dev->name = ECAP_DRV_NAME; counter_dev->parent = dev; -- cgit v1.2.3 From 2ff4ba9e37024735f5cefc5ea2a73fc66addfe0e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 29 Sep 2022 21:55:21 +0200 Subject: clk: rs9: Fix I2C accessors Add custom I2C accessors to this driver, since the regular I2C regmap ones do not generate the exact I2C transfers required by the chip. On I2C write, it is mandatory to send transfer length first, on read the chip returns the transfer length in first byte. Instead of always reading back 8 bytes, which is the default and also the size of the entire register file, set BCP register to 1 to read out 1 byte which is less wasteful. Fixes: 892e0ddea1aa ("clk: rs9: Add Renesas 9-series PCIe clock generator driver") Reported-by: Alexander Stein Signed-off-by: Marek Vasut Link: https://lore.kernel.org/r/20220929195521.284497-1-marex@denx.de Reviewed-by: Alexander Stein Signed-off-by: Stephen Boyd --- drivers/clk/clk-renesas-pcie.c | 65 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c index 4f5df1fc74b4..e6247141d0c0 100644 --- a/drivers/clk/clk-renesas-pcie.c +++ b/drivers/clk/clk-renesas-pcie.c @@ -90,13 +90,66 @@ static const struct regmap_access_table rs9_writeable_table = { .n_yes_ranges = ARRAY_SIZE(rs9_writeable_ranges), }; +static int rs9_regmap_i2c_write(void *context, + unsigned int reg, unsigned int val) +{ + struct i2c_client *i2c = context; + const u8 data[3] = { reg, 1, val }; + const int count = ARRAY_SIZE(data); + int ret; + + ret = i2c_master_send(i2c, data, count); + if (ret == count) + return 0; + else if (ret < 0) + return ret; + else + return -EIO; +} + +static int rs9_regmap_i2c_read(void *context, + unsigned int reg, unsigned int *val) +{ + struct i2c_client *i2c = context; + struct i2c_msg xfer[2]; + u8 txdata = reg; + u8 rxdata[2]; + int ret; + + xfer[0].addr = i2c->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = (void *)&txdata; + + xfer[1].addr = i2c->addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = 2; + xfer[1].buf = (void *)rxdata; + + ret = i2c_transfer(i2c->adapter, xfer, 2); + if (ret < 0) + return ret; + if (ret != 2) + return -EIO; + + /* + * Byte 0 is transfer length, which is always 1 due + * to BCP register programming to 1 in rs9_probe(), + * ignore it and use data from Byte 1. + */ + *val = rxdata[1]; + return 0; +} + static const struct regmap_config rs9_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_FLAT, - .max_register = 0x8, + .cache_type = REGCACHE_NONE, + .max_register = RS9_REG_BCP, .rd_table = &rs9_readable_table, .wr_table = &rs9_writeable_table, + .reg_write = rs9_regmap_i2c_write, + .reg_read = rs9_regmap_i2c_read, }; static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx) @@ -242,11 +295,17 @@ static int rs9_probe(struct i2c_client *client) return ret; } - rs9->regmap = devm_regmap_init_i2c(client, &rs9_regmap_config); + rs9->regmap = devm_regmap_init(&client->dev, NULL, + client, &rs9_regmap_config); if (IS_ERR(rs9->regmap)) return dev_err_probe(&client->dev, PTR_ERR(rs9->regmap), "Failed to allocate register map\n"); + /* Always read back 1 Byte via I2C */ + ret = regmap_write(rs9->regmap, RS9_REG_BCP, 1); + if (ret < 0) + return ret; + /* Register clock */ for (i = 0; i < rs9->chip_info->num_clks; i++) { snprintf(name, 5, "DIF%d", i); -- cgit v1.2.3 From 7e3e6e1b75c9643e25e8ca7d6caf1b1faf8f022e Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 5 Oct 2022 18:13:44 +0100 Subject: clk: sifive: select by default if SOC_SIFIVE With the aim of dropping direct selects of drivers from Kconfig.socs, default the SiFive clock drivers to the value of SOC_SIFIVE. Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20221005171348.167476-2-conor@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/sifive/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig index 9132c3c4aa86..b7fde0aadfcb 100644 --- a/drivers/clk/sifive/Kconfig +++ b/drivers/clk/sifive/Kconfig @@ -2,7 +2,8 @@ menuconfig CLK_SIFIVE bool "SiFive SoC driver support" - depends on RISCV || COMPILE_TEST + depends on SOC_SIFIVE || COMPILE_TEST + default SOC_SIFIVE help SoC drivers for SiFive Linux-capable SoCs. @@ -10,6 +11,7 @@ if CLK_SIFIVE config CLK_SIFIVE_PRCI bool "PRCI driver for SiFive SoCs" + default SOC_SIFIVE select RESET_CONTROLLER select RESET_SIMPLE select CLK_ANALOGBITS_WRPLL_CLN28HPC -- cgit v1.2.3 From 8fbf8636cd37b821ce3482748340008dbbe2dcb5 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sun, 9 Oct 2022 10:50:56 +0800 Subject: clk: mediatek: clk-mt8195-topckgen: Fix error return code in clk_mt8195_topck_probe() If devm_clk_hw_register_mux() fails in clk_mt8195_topck_probe(), it should return error code. Fixes: deeb2af77cf6 ("clk: mediatek: clk-mt8195-topckgen: Register mfg_ck_fast_ref as generic mux") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221009025056.35311-1-yangyingliang@huawei.com Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt8195-topckgen.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/mediatek/clk-mt8195-topckgen.c b/drivers/clk/mediatek/clk-mt8195-topckgen.c index 8cbab5ca2e58..1e016329c1d2 100644 --- a/drivers/clk/mediatek/clk-mt8195-topckgen.c +++ b/drivers/clk/mediatek/clk-mt8195-topckgen.c @@ -1270,8 +1270,10 @@ static int clk_mt8195_topck_probe(struct platform_device *pdev) hw = devm_clk_hw_register_mux(&pdev->dev, "mfg_ck_fast_ref", mfg_fast_parents, ARRAY_SIZE(mfg_fast_parents), CLK_SET_RATE_PARENT, (base + 0x250), 8, 1, 0, &mt8195_clk_lock); - if (IS_ERR(hw)) + if (IS_ERR(hw)) { + r = PTR_ERR(hw); goto unregister_muxes; + } top_clk_data->hws[CLK_TOP_MFG_CK_FAST_REF] = hw; r = clk_mt8195_reg_mfg_mux_notifier(&pdev->dev, -- cgit v1.2.3 From 97074216917b4188f0af3e52cc5b3f2b277bbbca Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Sun, 9 Oct 2022 14:35:20 +0800 Subject: drm/amdgpu: add tmz support for GC 11.0.1 this patch to add tmz support for GC 11.0.1. Signed-off-by: Yifan Zhang Reviewed-by: Tim Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 34233a74248c..9c0d9baab4e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -542,6 +542,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) case IP_VERSION(10, 3, 1): /* YELLOW_CARP*/ case IP_VERSION(10, 3, 3): + case IP_VERSION(11, 0, 1): /* Don't enable it by default yet. */ if (amdgpu_tmz < 1) { -- cgit v1.2.3 From bfa8cb055fef348c896b70b9ac13d1838665031a Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Sun, 9 Oct 2022 14:37:06 +0800 Subject: drm/amdgpu: allow secure submission on gfx11 and sdma6 This patch to allow secure submission on gfx11 and sdma6. Signed-off-by: Yifan Zhang Reviewed-by: Tim Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 + drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 251109723ab6..257b2e4de600 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -6058,6 +6058,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = { .align_mask = 0xff, .nop = PACKET3(PACKET3_NOP, 0x3FFF), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_GFXHUB_0, .get_rptr = gfx_v11_0_ring_get_rptr_gfx, .get_wptr = gfx_v11_0_ring_get_wptr_gfx, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c index da3beb0bf2fa..d9ae69be5ea4 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c @@ -1523,6 +1523,7 @@ static const struct amdgpu_ring_funcs sdma_v6_0_ring_funcs = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_GFXHUB_0, .get_rptr = sdma_v6_0_ring_get_rptr, .get_wptr = sdma_v6_0_ring_get_wptr, -- cgit v1.2.3 From 7a94c8602fbe585fac636dae355cf73b53d50866 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Tue, 17 May 2022 22:10:41 +0800 Subject: drm/amdgpu: extend HWIP_MAX_INSTANCE to 28 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit more ip instances are available Acked-by: Christian König Signed-off-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ae9371b172e3..3ce91f660c3f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -678,7 +678,7 @@ enum amd_hw_ip_block_type { MAX_HWIP }; -#define HWIP_MAX_INSTANCE 11 +#define HWIP_MAX_INSTANCE 28 #define HW_ID_MAX 300 #define IP_VERSION(mj, mn, rv) (((mj) << 16) | ((mn) << 8) | (rv)) -- cgit v1.2.3 From e9ff000b5a2a6b2f34828ebcfb0a829ce2dcdc2a Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Tue, 31 Aug 2021 15:30:08 +0800 Subject: drm/amdgpu: update psp_fw_type enum in amdgpu_ucode header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To match with the definition in psp firmware Acked-by: Christian König Signed-off-by: Hawking Zhang Reviewed-by: Le Ma Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index 1c36235b4539..552e06929229 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -125,6 +125,7 @@ enum psp_fw_type { PSP_FW_TYPE_PSP_INTF_DRV, PSP_FW_TYPE_PSP_DBG_DRV, PSP_FW_TYPE_PSP_RAS_DRV, + PSP_FW_TYPE_MAX_INDEX, }; /* version_major=2, version_minor=0 */ -- cgit v1.2.3 From 886f1816c2ad9e5bf594549cc4977df7a533dde9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 3 Oct 2022 15:00:47 -0400 Subject: drm/amdgpu: convert vega20_ih.c to IP version checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency with newer asics. Acked-by: Christian König Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c index 59dfca093155..1706081d054d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c @@ -267,7 +267,7 @@ static void vega20_ih_reroute_ih(struct amdgpu_device *adev) /* vega20 ih reroute will go through psp this * function is used for newer asics starting arcturus */ - if (adev->asic_type >= CHIP_ARCTURUS) { + if (adev->ip_versions[OSSSYS_HWIP][0] >= IP_VERSION(4, 2, 1)) { /* Reroute to IH ring 1 for VMC */ WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_INDEX, 0x12); tmp = RREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA); @@ -308,7 +308,7 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev) adev->nbio.funcs->ih_control(adev); - if (adev->asic_type == CHIP_ARCTURUS && + if ((adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 2, 1)) && adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN); if (adev->irq.ih.use_bus_addr) { @@ -321,7 +321,7 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev) /* psp firmware won't program IH_CHICKEN for aldebaran * driver needs to program it properly according to * MC_SPACE type in IH_RB_CNTL */ - if (adev->asic_type == CHIP_ALDEBARAN) { + if (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0)) { ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN_ALDEBARAN); if (adev->irq.ih.use_bus_addr) { ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN, -- cgit v1.2.3 From eb1670787eb7b9fe339631605dda1a53603a7699 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 3 Oct 2022 15:09:57 -0400 Subject: drm/amdgpu: convert amdgpu_amdkfd_gpuvm.c to IP version checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency with the rest of the code. Acked-by: Christian König Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 978d3970b5cc..8ad01e1ee4c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -418,9 +418,9 @@ static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem) if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE) mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE; - switch (adev->asic_type) { - case CHIP_ARCTURUS: - case CHIP_ALDEBARAN: + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(9, 4, 1): + case IP_VERSION(9, 4, 2): if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { if (bo_adev == adev) { if (uncached) @@ -429,7 +429,7 @@ static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem) mapping_flags |= AMDGPU_VM_MTYPE_CC; else mapping_flags |= AMDGPU_VM_MTYPE_RW; - if (adev->asic_type == CHIP_ALDEBARAN && + if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) && adev->gmc.xgmi.connected_to_cpu) snoop = true; } else { -- cgit v1.2.3 From 7fe441d8b77a1e4fe09099092945d27607dda69b Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 12 Oct 2022 15:37:07 +0800 Subject: drm/amdgpu/si_dma: remove unused variable in si_dma_stop() After commit 571c05365892 ("drm/amdgpu: switch sdma buffer function tear down to a helper"), the variable 'ring' is not used anymore, it can be removed. Signed-off-by: Yang Yingliang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dma.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 4d5e718540aa..abca8b529721 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -112,14 +112,12 @@ static void si_dma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, static void si_dma_stop(struct amdgpu_device *adev) { - struct amdgpu_ring *ring; u32 rb_cntl; unsigned i; amdgpu_sdma_unset_buffer_funcs_helper(adev); for (i = 0; i < adev->sdma.num_instances; i++) { - ring = &adev->sdma.instance[i].ring; /* dma0 */ rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]); rb_cntl &= ~DMA_RB_ENABLE; -- cgit v1.2.3 From a7310d8de3ba60a6ec4294392daf747b8333b3b2 Mon Sep 17 00:00:00 2001 From: Danijel Slivka Date: Tue, 4 Oct 2022 15:39:44 +0200 Subject: drm/amdgpu: set vm_update_mode=0 as default for Sienna Cichlid in SRIOV case For asic with VF MMIO access protection avoid using CPU for VM table updates. CPU pagetable updates have issues with HDP flush as VF MMIO access protection blocks write to mmBIF_BX_DEV0_EPF0_VF0_HDP_MEM_COHERENCY_FLUSH_CNTL register during sriov runtime. v3: introduce virtualization capability flag AMDGPU_VF_MMIO_ACCESS_PROTECT which indicates that VF MMIO write access is not allowed in sriov runtime Signed-off-by: Danijel Slivka Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index e4af40b9a8aa..9c765b04aae3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -726,6 +726,12 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev) adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE; } + if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID) + /* VF MMIO access (except mailbox range) from CPU + * will be blocked during sriov runtime + */ + adev->virt.caps |= AMDGPU_VF_MMIO_ACCESS_PROTECT; + /* we have the ability to check now */ if (amdgpu_sriov_vf(adev)) { switch (adev->asic_type) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index d94c31e68a14..49c4347d154c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -31,6 +31,7 @@ #define AMDGPU_SRIOV_CAPS_IS_VF (1 << 2) /* this GPU is a virtual function */ #define AMDGPU_PASSTHROUGH_MODE (1 << 3) /* thw whole GPU is pass through for VM */ #define AMDGPU_SRIOV_CAPS_RUNTIME (1 << 4) /* is out of full access mode */ +#define AMDGPU_VF_MMIO_ACCESS_PROTECT (1 << 5) /* MMIO write access is not allowed in sriov runtime */ /* flags for indirect register access path supported by rlcg for sriov */ #define AMDGPU_RLCG_GC_WRITE_LEGACY (0x8 << 28) @@ -297,6 +298,9 @@ struct amdgpu_video_codec_info; #define amdgpu_passthrough(adev) \ ((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE) +#define amdgpu_sriov_vf_mmio_access_protection(adev) \ +((adev)->virt.caps & AMDGPU_VF_MMIO_ACCESS_PROTECT) + static inline bool is_virtual_machine(void) { #if defined(CONFIG_X86) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 83b0c5d86e48..2291aa14d888 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2338,7 +2338,11 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) */ #ifdef CONFIG_X86_64 if (amdgpu_vm_update_mode == -1) { - if (amdgpu_gmc_vram_full_visible(&adev->gmc)) + /* For asic with VF MMIO access protection + * avoid using CPU for VM table updates + */ + if (amdgpu_gmc_vram_full_visible(&adev->gmc) && + !amdgpu_sriov_vf_mmio_access_protection(adev)) adev->vm_manager.vm_update_mode = AMDGPU_VM_USE_CPU_FOR_COMPUTE; else -- cgit v1.2.3 From 6aa5893926371ebc6c2b6ca6ad37b2aec3a11d29 Mon Sep 17 00:00:00 2001 From: Victor Zhao Date: Thu, 13 Oct 2022 10:42:04 +0800 Subject: Revert "drm/amdgpu: add debugfs amdgpu_reset_level" This reverts commit 5bd8d53f6fa53eab5433698d1362dae2aa53c1cc. This commit breaks the reset logic for aldebaran, revert it for now. Will move the mask inside the reset handler. Fixes: 5bd8d53f6fa53e ("drm/amdgpu: add debugfs amdgpu_reset_level") Signed-off-by: Victor Zhao Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ---- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 2 -- drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c | 8 -------- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 3 --- 4 files changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3ce91f660c3f..0e6ddf05c23c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -274,9 +274,6 @@ extern int amdgpu_vcnfw_log; #define AMDGPU_RESET_VCE (1 << 13) #define AMDGPU_RESET_VCE1 (1 << 14) -#define AMDGPU_RESET_LEVEL_SOFT_RECOVERY (1 << 0) -#define AMDGPU_RESET_LEVEL_MODE2 (1 << 1) - /* max cursor sizes (in pixels) */ #define CIK_CURSOR_WIDTH 128 #define CIK_CURSOR_HEIGHT 128 @@ -1065,7 +1062,6 @@ struct amdgpu_device { struct work_struct reset_work; - uint32_t amdgpu_reset_level_mask; bool job_hang; }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 6066aebf491c..de61a85c4b02 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1954,8 +1954,6 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) return PTR_ERR(ent); } - debugfs_create_u32("amdgpu_reset_level", 0600, root, &adev->amdgpu_reset_level_mask); - /* Register debugfs entries for amdgpu_ttm */ amdgpu_ttm_debugfs_init(adev); amdgpu_debugfs_pm_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c index 9da5ead50c90..831fb222139c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c @@ -37,8 +37,6 @@ int amdgpu_reset_init(struct amdgpu_device *adev) { int ret = 0; - adev->amdgpu_reset_level_mask = 0x1; - switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 2): ret = aldebaran_reset_init(adev); @@ -76,9 +74,6 @@ int amdgpu_reset_prepare_hwcontext(struct amdgpu_device *adev, { struct amdgpu_reset_handler *reset_handler = NULL; - if (!(adev->amdgpu_reset_level_mask & AMDGPU_RESET_LEVEL_MODE2)) - return -ENOSYS; - if (test_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context->flags)) return -ENOSYS; @@ -98,9 +93,6 @@ int amdgpu_reset_perform_reset(struct amdgpu_device *adev, int ret; struct amdgpu_reset_handler *reset_handler = NULL; - if (!(adev->amdgpu_reset_level_mask & AMDGPU_RESET_LEVEL_MODE2)) - return -ENOSYS; - if (test_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context->flags)) return -ENOSYS; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 3e316b013fd9..d3558c34d406 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -405,9 +405,6 @@ bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid, { ktime_t deadline = ktime_add_us(ktime_get(), 10000); - if (!(ring->adev->amdgpu_reset_level_mask & AMDGPU_RESET_LEVEL_SOFT_RECOVERY)) - return false; - if (amdgpu_sriov_vf(ring->adev) || !ring->funcs->soft_recovery || !fence) return false; -- cgit v1.2.3 From b98a1648d6616d288e888c6dc6dcd4fa543585b3 Mon Sep 17 00:00:00 2001 From: Victor Zhao Date: Thu, 13 Oct 2022 11:06:33 +0800 Subject: Revert "drm/amdgpu: let mode2 reset fallback to default when failure" This reverts commit dac6b80818ac2353631c5a33d140d8d5508e2957. This commit reverted the AMDGPU_SKIP_MODE2_RESET as it conflicts with the original design of reset handler. Will redesign it. Fixes: dac6b80818ac23 ("drm/amdgpu: let mode2 reset fallback to default when failure") Signed-off-by: Victor Zhao Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +------ drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c | 6 ------ drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h | 3 +-- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 1 - drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 1 - drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c | 1 - 9 files changed, 2 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 03bbfaa51cbc..0561812aa0a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -134,7 +134,6 @@ static void amdgpu_amdkfd_reset_work(struct work_struct *work) reset_context.method = AMD_RESET_METHOD_NONE; reset_context.reset_req_dev = adev; clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); - clear_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context.flags); amdgpu_device_gpu_recover(adev, NULL, &reset_context); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ab8f970b2849..bb73fb420ffc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -5210,7 +5210,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, reset_context->job = job; reset_context->hive = hive; - /* * Build list of devices to reset. * In case we are in XGMI hive mode, resort the device list @@ -5337,11 +5336,8 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ amdgpu_ras_resume(adev); } else { r = amdgpu_do_asic_reset(device_list_handle, reset_context); - if (r && r == -EAGAIN) { - set_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context->flags); - adev->asic_reset_res = 0; + if (r && r == -EAGAIN) goto retry; - } if (!r && gpu_reset_for_dev_remove) goto recover_end; @@ -5777,7 +5773,6 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev) reset_context.reset_req_dev = adev; set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags); - set_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context.flags); adev->no_hw_access = true; r = amdgpu_device_pre_asic_reset(adev, &reset_context); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 46c99331d7f1..cd968e781077 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -72,7 +72,6 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) reset_context.method = AMD_RESET_METHOD_NONE; reset_context.reset_req_dev = adev; clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); - clear_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context.flags); r = amdgpu_device_gpu_recover(ring->adev, job, &reset_context); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 2dad7aa9a03b..75f1402101f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1950,7 +1950,6 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) reset_context.method = AMD_RESET_METHOD_NONE; reset_context.reset_req_dev = adev; clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); - clear_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context.flags); amdgpu_device_gpu_recover(ras->adev, NULL, &reset_context); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c index 831fb222139c..f778466bb9db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c @@ -74,9 +74,6 @@ int amdgpu_reset_prepare_hwcontext(struct amdgpu_device *adev, { struct amdgpu_reset_handler *reset_handler = NULL; - if (test_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context->flags)) - return -ENOSYS; - if (adev->reset_cntl && adev->reset_cntl->get_reset_handler) reset_handler = adev->reset_cntl->get_reset_handler( adev->reset_cntl, reset_context); @@ -93,9 +90,6 @@ int amdgpu_reset_perform_reset(struct amdgpu_device *adev, int ret; struct amdgpu_reset_handler *reset_handler = NULL; - if (test_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context->flags)) - return -ENOSYS; - if (adev->reset_cntl) reset_handler = adev->reset_cntl->get_reset_handler( adev->reset_cntl, reset_context); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h index f5318fedf2f0..f4a501ff87d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h @@ -30,8 +30,7 @@ enum AMDGPU_RESET_FLAGS { AMDGPU_NEED_FULL_RESET = 0, AMDGPU_SKIP_HW_RESET = 1, - AMDGPU_SKIP_MODE2_RESET = 2, - AMDGPU_RESET_FOR_DEVICE_REMOVE = 3, + AMDGPU_RESET_FOR_DEVICE_REMOVE = 2, }; struct amdgpu_reset_context { diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index a2f04b249132..12906ba74462 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -290,7 +290,6 @@ flr_done: reset_context.method = AMD_RESET_METHOD_NONE; reset_context.reset_req_dev = adev; clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); - clear_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context.flags); amdgpu_device_gpu_recover(adev, NULL, &reset_context); } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index a977f0027928..e07757eea7ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -317,7 +317,6 @@ flr_done: reset_context.method = AMD_RESET_METHOD_NONE; reset_context.reset_req_dev = adev; clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); - clear_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context.flags); amdgpu_device_gpu_recover(adev, NULL, &reset_context); } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c index fd14fa9b9cd7..288c414babdf 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c @@ -529,7 +529,6 @@ static void xgpu_vi_mailbox_flr_work(struct work_struct *work) reset_context.method = AMD_RESET_METHOD_NONE; reset_context.reset_req_dev = adev; clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); - clear_bit(AMDGPU_SKIP_MODE2_RESET, &reset_context.flags); amdgpu_device_gpu_recover(adev, NULL, &reset_context); } -- cgit v1.2.3 From 16e311612456df01308585b89227854b1f495041 Mon Sep 17 00:00:00 2001 From: Victor Zhao Date: Thu, 13 Oct 2022 15:53:19 +0800 Subject: drm/amdgpu: Refactor mode2 reset logic for v11.0.7 - refactor mode2 on v11.0.7 to align with aldebaran - comment out using mode2 reset as default for now, will introduce another controller to replace previous reset_level_mask v2: squash in unused variable removal (Alex) Signed-off-by: Victor Zhao Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c index 7aa570c1ce4a..81a6d5b94987 100644 --- a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c +++ b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c @@ -31,12 +31,23 @@ #include "amdgpu_psp.h" #include "amdgpu_xgmi.h" +static bool sienna_cichlid_is_mode2_default(struct amdgpu_reset_control *reset_ctl) +{ +#if 0 + struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle; + + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7) && + adev->pm.fw_version >= 0x3a5500 && !amdgpu_sriov_vf(adev)) + return true; +#endif + return false; +} + static struct amdgpu_reset_handler * sienna_cichlid_get_reset_handler(struct amdgpu_reset_control *reset_ctl, struct amdgpu_reset_context *reset_context) { struct amdgpu_reset_handler *handler; - struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle; if (reset_context->method != AMD_RESET_METHOD_NONE) { list_for_each_entry(handler, &reset_ctl->reset_handlers, @@ -44,15 +55,13 @@ sienna_cichlid_get_reset_handler(struct amdgpu_reset_control *reset_ctl, if (handler->reset_method == reset_context->method) return handler; } - } else { - list_for_each_entry(handler, &reset_ctl->reset_handlers, + } + + if (sienna_cichlid_is_mode2_default(reset_ctl)) { + list_for_each_entry (handler, &reset_ctl->reset_handlers, handler_list) { - if (handler->reset_method == AMD_RESET_METHOD_MODE2 && - adev->pm.fw_version >= 0x3a5500 && - !amdgpu_sriov_vf(adev)) { - reset_context->method = AMD_RESET_METHOD_MODE2; + if (handler->reset_method == AMD_RESET_METHOD_MODE2) return handler; - } } } -- cgit v1.2.3 From e5b781c56d46c44c52caa915f1b65064f2f7c1ba Mon Sep 17 00:00:00 2001 From: Asher Song Date: Fri, 14 Oct 2022 11:36:33 +0800 Subject: drm/amdgpu: Revert "drm/amdgpu: getting fan speed pwm for vega10 properly" This reverts commit 16fb4dca95daa9d8e037201166a58de8284f4268. Unfortunately, that commit causes fan monitors can't be read and written properly. Fixes: 16fb4dca95daa9 ("drm/amdgpu: getting fan speed pwm for vega10 properly") Signed-off-by: Asher Song Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- .../drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index 190af79f3236..dad3e3741a4e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -67,21 +67,22 @@ int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, int vega10_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr, uint32_t *speed) { - struct amdgpu_device *adev = hwmgr->adev; - uint32_t duty100, duty; - uint64_t tmp64; + uint32_t current_rpm; + uint32_t percent = 0; - duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), - CG_FDO_CTRL1, FMAX_DUTY100); - duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS), - CG_THERMAL_STATUS, FDO_PWM_DUTY); + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; - if (!duty100) - return -EINVAL; + if (vega10_get_current_rpm(hwmgr, ¤t_rpm)) + return -1; + + if (hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM != 0) + percent = current_rpm * 255 / + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM; - tmp64 = (uint64_t)duty * 255; - do_div(tmp64, duty100); - *speed = MIN((uint32_t)tmp64, 255); + *speed = MIN(percent, 255); return 0; } -- cgit v1.2.3 From 8a7b97672dfdb97691dfb15e350b38339f7c69f3 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Sat, 30 Jul 2022 10:58:37 +0800 Subject: drm/amd/pm: temporarily disable thermal alert on smu_v13_0_10 temporarily disable thermal alert on smu_v13_0_10 due to kfd test fail. will enable it again after confirming the thermal hardware setting. Signed-off-by: Kenneth Feng Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 13c5c7f1ecb9..3d436e7f6e95 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1312,10 +1312,12 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } - ret = smu_enable_thermal_alert(smu); - if (ret) { - dev_err(adev->dev, "Failed to enable thermal alert!\n"); - return ret; + if (adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 10)) { + ret = smu_enable_thermal_alert(smu); + if (ret) { + dev_err(adev->dev, "Failed to enable thermal alert!\n"); + return ret; + } } ret = smu_notify_display_change(smu); -- cgit v1.2.3 From e77422a5d4518109511334e6c2274422fa1559c8 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Wed, 7 Sep 2022 15:40:34 +0800 Subject: drm/amd/pm: remove the pptable id override on smu_v13_0_10 remove the pptable id override on smu_v13_0_10, and the id is fetched from vbios now. Signed-off-by: Kenneth Feng Reviewed-by: Likun Gao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index 93fffdbab4f0..d9323293179a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -454,9 +454,6 @@ int smu_v13_0_setup_pptable(struct smu_context *smu) dev_info(adev->dev, "override pptable id %d\n", pptable_id); } else { pptable_id = smu->smu_table.boot_values.pp_table_id; - - if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 10)) - pptable_id = 6666; } /* force using vbios pptable in sriov mode */ -- cgit v1.2.3 From 4ecdb30ec49d76ccb803c9b9c1464fcf27d6d041 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Wed, 7 Sep 2022 17:05:34 +0800 Subject: drm/amd/amdgpu: enable gfx clock gating features on smu_v13_0_10 enable gfx clock gating features on smu_v13_0_10 Signed-off-by: Kenneth Feng Reviewed-by: Jack Gui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 + drivers/gpu/drm/amd/amdgpu/soc21.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 257b2e4de600..73106f53246d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -5076,6 +5076,7 @@ static int gfx_v11_0_set_clockgating_state(void *handle, case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 2): + case IP_VERSION(11, 0, 3): gfx_v11_0_update_gfx_clock_gating(adev, state == AMD_CG_STATE_GATE); break; diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 795706b3b092..fdd842a3fcb6 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -636,7 +636,11 @@ static int soc21_common_early_init(void *handle) break; case IP_VERSION(11, 0, 3): adev->cg_flags = AMD_CG_SUPPORT_VCN_MGCG | - AMD_CG_SUPPORT_JPEG_MGCG; + AMD_CG_SUPPORT_JPEG_MGCG | + AMD_CG_SUPPORT_GFX_CGCG | + AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_REPEATER_FGCG | + AMD_CG_SUPPORT_GFX_MGCG; adev->pg_flags = AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_VCN_DPG | AMD_PG_SUPPORT_JPEG; -- cgit v1.2.3 From 7faf684b15f5533142ebeed5ec09d5ea9d9239c4 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Mon, 26 Sep 2022 17:15:04 +0800 Subject: drm/amd/pm: skip loading pptable from driver on secure board for smu_v13_0_10 skip loading pptable from driver on secure board since it's loaded from psp. Signed-off-by: Kenneth Feng Reviewed-by: Guan Yu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index d9323293179a..c4552ade8d44 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -211,7 +211,8 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu) return 0; if ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7)) || - (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0))) + (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0)) || + (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 10))) return 0; /* override pptable_id from driver parameter */ -- cgit v1.2.3 From bbce8cdb8390c4cae8ebe99f13a82c846995e8d9 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Mon, 25 Jul 2022 20:02:40 +0800 Subject: drm/amdgpu: skip mes self test for gc 11.0.3 Temporary disable mes self teset for gc 11.0.3. Signed-off-by: Likun Gao Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 5cec6b259b7f..133804e6018a 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -1296,7 +1296,8 @@ static int mes_v11_0_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (!amdgpu_in_reset(adev)) + if (!amdgpu_in_reset(adev) && + (adev->ip_versions[GC_HWIP][0] != IP_VERSION(11, 0, 3))) amdgpu_mes_self_test(adev); return 0; -- cgit v1.2.3 From 2e26bf1e461fb934cbd5e34142068705ceba1fc1 Mon Sep 17 00:00:00 2001 From: YiPeng Chai Date: Tue, 27 Sep 2022 13:16:27 +0800 Subject: drm/amdgpu: Enable gmc soft reset on gmc_v11_0_3 Enable gmc soft reset on gmc_v11_0_3. Signed-off-by: YiPeng Chai Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index fdd842a3fcb6..e08044008186 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -423,6 +423,7 @@ static bool soc21_need_full_reset(struct amdgpu_device *adev) case IP_VERSION(11, 0, 0): return amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC); case IP_VERSION(11, 0, 2): + case IP_VERSION(11, 0, 3): return false; default: return true; -- cgit v1.2.3 From 073285efde229ae82d3b853c7f4bcca81f97a55f Mon Sep 17 00:00:00 2001 From: YiPeng Chai Date: Tue, 27 Sep 2022 14:06:42 +0800 Subject: drm/amdgpu: Enable ras support for mp0 v13_0_0 and v13_0_10 V1: Enable ras support for CHIP_IP_DISCOVERY asic type. V2: 1. Change commit comment. 2. Enable ras support for mp0 v13_0_0 and v13_0_10. Signed-off-by: YiPeng Chai Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 75f1402101f4..4a8f73cc4cb5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2267,6 +2267,16 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev) static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev) { + if (adev->asic_type == CHIP_IP_DISCOVERY) { + switch (adev->ip_versions[MP0_HWIP][0]) { + case IP_VERSION(13, 0, 0): + case IP_VERSION(13, 0, 10): + return true; + default: + return false; + } + } + return adev->asic_type == CHIP_VEGA10 || adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS || -- cgit v1.2.3 From 82835055c62fa49b50dc00736743e8f99ed93638 Mon Sep 17 00:00:00 2001 From: YiPeng Chai Date: Wed, 28 Sep 2022 15:52:02 +0800 Subject: drm/amdgpu: Add sriov vf ras support in amdgpu_ras_asic_supported V2: Add sriov vf ras support in amdgpu_ras_asic_supported. Signed-off-by: YiPeng Chai Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 4a8f73cc4cb5..a4b47e1bd111 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2267,6 +2267,15 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev) static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev) { + if (amdgpu_sriov_vf(adev)) { + switch (adev->ip_versions[MP0_HWIP][0]) { + case IP_VERSION(13, 0, 2): + return true; + default: + return false; + } + } + if (adev->asic_type == CHIP_IP_DISCOVERY) { switch (adev->ip_versions[MP0_HWIP][0]) { case IP_VERSION(13, 0, 0): @@ -2320,11 +2329,6 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev) !amdgpu_ras_asic_supported(adev)) return; - /* If driver run on sriov guest side, only enable ras for aldebaran */ - if (amdgpu_sriov_vf(adev) && - adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 2)) - return; - if (!adev->gmc.xgmi.connected_to_cpu) { if (amdgpu_atomfirmware_mem_ecc_supported(adev)) { dev_info(adev->dev, "MEM ECC is active.\n"); -- cgit v1.2.3 From c6863be231791fa80dca203b9295780488671195 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 29 Sep 2022 10:24:51 +0800 Subject: drm/amd/pm: fulfill SMU13.0.0 cstate control interface Fulfill the functionality for cstate control. Signed-off-by: Evan Quan Reviewed-by: Hawking Zhang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 1d454485e0d9..29529328152d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -119,6 +119,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] = MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0), MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 0), MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0), + MSG_MAP(DFCstateControl, PPSMC_MSG_SetExternalClientDfCstateAllow, 0), }; static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = { @@ -1753,6 +1754,15 @@ static int smu_v13_0_0_set_mp1_state(struct smu_context *smu, return ret; } +static int smu_v13_0_0_set_df_cstate(struct smu_context *smu, + enum pp_df_cstate state) +{ + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_DFCstateControl, + state, + NULL); +} + static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask, .set_default_dpm_table = smu_v13_0_0_set_default_dpm_table, @@ -1822,6 +1832,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .mode1_reset_is_support = smu_v13_0_0_is_mode1_reset_supported, .mode1_reset = smu_v13_0_mode1_reset, .set_mp1_state = smu_v13_0_0_set_mp1_state, + .set_df_cstate = smu_v13_0_0_set_df_cstate, }; void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu) -- cgit v1.2.3 From 3cf377ee8df7dc4ae5e543c37833ae5a5b2a78d3 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 29 Sep 2022 10:30:01 +0800 Subject: drm/amd/pm: fulfill SMU13.0.7 cstate control interface Fulfill the functionality for cstate control. Signed-off-by: Evan Quan Reviewed-by: Hawking Zhang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index c422bf8a09b1..c4102cfb734c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -121,6 +121,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] = MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 0), MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0), MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), + MSG_MAP(DFCstateControl, PPSMC_MSG_SetExternalClientDfCstateAllow, 0), }; static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = { @@ -1587,6 +1588,16 @@ static bool smu_v13_0_7_is_mode1_reset_supported(struct smu_context *smu) return true; } + +static int smu_v13_0_7_set_df_cstate(struct smu_context *smu, + enum pp_df_cstate state) +{ + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_DFCstateControl, + state, + NULL); +} + static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask, .set_default_dpm_table = smu_v13_0_7_set_default_dpm_table, @@ -1649,6 +1660,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .mode1_reset_is_support = smu_v13_0_7_is_mode1_reset_supported, .mode1_reset = smu_v13_0_mode1_reset, .set_mp1_state = smu_v13_0_7_set_mp1_state, + .set_df_cstate = smu_v13_0_7_set_df_cstate, }; void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu) -- cgit v1.2.3 From b31d6ada8346574ce04656e5ce9676ec763f5144 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 29 Sep 2022 10:50:44 +0800 Subject: drm/amd/pm: disable cstate feature for gpu reset scenario Suggested by PMFW team and same as what did for gfxoff feature. This can address some Mode1Reset failures observed on SMU13.0.0. Signed-off-by: Evan Quan Reviewed-by: Hawking Zhang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++++++++ drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 8 ++++++++ drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 9 +++++++++ 3 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index bb73fb420ffc..e0445e8cc342 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2928,6 +2928,14 @@ static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev) amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE); amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE); + /* + * Per PMFW team's suggestion, driver needs to handle gfxoff + * and df cstate features disablement for gpu reset(e.g. Mode1Reset) + * scenario. Add the missing df cstate disablement here. + */ + if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW)) + dev_warn(adev->dev, "Failed to disallow df cstate"); + for (i = adev->num_ip_blocks - 1; i >= 0; i--) { if (!adev->ip_blocks[i].status.valid) continue; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 445005571f76..9cd005131f56 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2242,9 +2242,17 @@ static void arcturus_get_unique_id(struct smu_context *smu) static int arcturus_set_df_cstate(struct smu_context *smu, enum pp_df_cstate state) { + struct amdgpu_device *adev = smu->adev; uint32_t smu_version; int ret; + /* + * Arcturus does not need the cstate disablement + * prerequisite for gpu reset. + */ + if (amdgpu_in_reset(adev) || adev->in_suspend) + return 0; + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); if (ret) { dev_err(smu->adev->dev, "Failed to get smu version!\n"); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 619aee51b123..d30ec3005ea1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1640,6 +1640,15 @@ static bool aldebaran_is_baco_supported(struct smu_context *smu) static int aldebaran_set_df_cstate(struct smu_context *smu, enum pp_df_cstate state) { + struct amdgpu_device *adev = smu->adev; + + /* + * Aldebaran does not need the cstate disablement + * prerequisite for gpu reset. + */ + if (amdgpu_in_reset(adev) || adev->in_suspend) + return 0; + return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state, NULL); } -- cgit v1.2.3 From 5af392a89bd009aced92e9079589bd82f249010a Mon Sep 17 00:00:00 2001 From: ZhenGuo Yin Date: Wed, 12 Oct 2022 16:54:38 +0800 Subject: drm/amd/pm: Init pm_attr_list when dpm is disabled [Why] In SRIOV multi-vf, dpm is always disabled, and pm_attr_list won't be initialized. There will be a NULL pointer call trace after removing the dpm check condition in amdgpu_pm_sysfs_fini. BUG: kernel NULL pointer dereference, address: 0000000000000000 RIP: 0010:amdgpu_device_attr_remove_groups+0x20/0x90 [amdgpu] Call Trace: amdgpu_pm_sysfs_fini+0x2f/0x40 [amdgpu] amdgpu_device_fini_hw+0xdf/0x290 [amdgpu] [How] List pm_attr_list should be initialized when dpm is disabled. Fixes: a6ad27cec585fe ("drm/amd/pm: Remove redundant check condition") Signed-off-by: ZhenGuo Yin Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 948cc75376f8..236657eece47 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3362,11 +3362,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) if (adev->pm.sysfs_initialized) return 0; + INIT_LIST_HEAD(&adev->pm.pm_attr_list); + if (adev->pm.dpm_enabled == 0) return 0; - INIT_LIST_HEAD(&adev->pm.pm_attr_list); - adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev, DRIVER_NAME, adev, hwmon_groups); -- cgit v1.2.3 From d1bb3afc0527ab55d118852b398fd0f1d2fe802d Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Thu, 29 Sep 2022 14:39:21 +0800 Subject: drm/amd/pm: update SMU IP v13.0.4 driver interface version Update the SMU driver interface version to V7. Signed-off-by: Tim Huang Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- .../amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h index ae2d337158f3..f77401709d83 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h @@ -27,7 +27,7 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define PMFW_DRIVER_IF_VERSION 5 +#define PMFW_DRIVER_IF_VERSION 7 typedef struct { int32_t value; @@ -163,8 +163,8 @@ typedef struct { uint16_t DclkFrequency; //[MHz] uint16_t MemclkFrequency; //[MHz] uint16_t spare; //[centi] - uint16_t UvdActivity; //[centi] uint16_t GfxActivity; //[centi] + uint16_t UvdActivity; //[centi] uint16_t Voltage[2]; //[mV] indices: VDDCR_VDD, VDDCR_SOC uint16_t Current[2]; //[mA] indices: VDDCR_VDD, VDDCR_SOC @@ -199,6 +199,19 @@ typedef struct { uint16_t DeviceState; uint16_t CurTemp; //[centi-Celsius] uint16_t spare2; + + uint16_t AverageGfxclkFrequency; + uint16_t AverageFclkFrequency; + uint16_t AverageGfxActivity; + uint16_t AverageSocclkFrequency; + uint16_t AverageVclkFrequency; + uint16_t AverageVcnActivity; + uint16_t AverageDRAMReads; //Filtered DF Bandwidth::DRAM Reads + uint16_t AverageDRAMWrites; //Filtered DF Bandwidth::DRAM Writes + uint16_t AverageSocketPower; //Filtered value of CurrentSocketPower + uint16_t AverageCorePower; //Filtered of [sum of CorePower[8]]) + uint16_t AverageCoreC0Residency[8]; //Filtered of [average C0 residency % per core] + uint32_t MetricsCounter; //Counts the # of metrics table parameter reads per update to the metrics table, i.e. if the metrics table update happens every 1 second, this value could be up to 1000 if the smu collected metrics data every cycle, or as low as 0 if the smu was asleep the whole time. Reset to 0 after writing. } SmuMetrics_t; typedef struct { -- cgit v1.2.3 From 027bf0cee89a27325a9a4f2240c21dd5fb81e4fa Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Thu, 29 Sep 2022 15:06:47 +0800 Subject: drm/amd/pm: add SMU IP v13.0.4 IF version define to V7 The pmfw has changed the driver interface version, so keep same with the fw. Signed-off-by: Tim Huang Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 9d62ea2af132..8f72202aea8e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -28,7 +28,7 @@ #define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08 -#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x05 +#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x07 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x30 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x2C -- cgit v1.2.3 From 6c0ca748205dc815505c6de79ecf565953390b66 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Fri, 14 Oct 2022 15:17:43 +0800 Subject: drm/amdgpu: move convert_error_address out of umc_ras RAS error address translation algorithm is common across dGPU and A + A platform as along as the SOC integrates the same generation of UMC IP. UMC RAS is managed by x86 MCA on A + A platform, umc_ras in GPU driver is not initialized at all on A + A platform. In such case, any umc_ras callback implemented for dGPU config shouldn't be invoked from A + A specific callback. The change moves convert_error_address out of dGPU umc_ras structure and makes it share between A + A and dGPU config. Signed-off-by: Hawking Zhang Reviewed-by: Stanley Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 16 ++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 3 --- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 7 +++---- drivers/gpu/drm/amd/amdgpu/umc_v6_7.h | 4 +++- 4 files changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index a4b47e1bd111..21a47f2bb87b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -36,6 +36,7 @@ #include "ivsrcid/nbio/irqsrcs_nbif_7_4.h" #include "atom.h" #include "amdgpu_reset.h" +#include "umc_v6_7.h" #ifdef CONFIG_X86_MCE_AMD #include @@ -2899,10 +2900,17 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb, /* * Translate UMC channel address to Physical address */ - if (adev->umc.ras && - adev->umc.ras->convert_ras_error_address) - adev->umc.ras->convert_ras_error_address(adev, - &err_data, m->addr, ch_inst, umc_inst); + switch (adev->ip_versions[UMC_HWIP][0]) { + case IP_VERSION(6, 7, 0): + umc_v6_7_convert_error_address(adev, + &err_data, m->addr, ch_inst, umc_inst); + break; + default: + dev_warn(adev->dev, + "UMC address to Physical address translation is not supported\n"); + kfree(err_data.err_addr); + return NOTIFY_DONE; + } if (amdgpu_bad_page_threshold != 0) { amdgpu_ras_add_bad_pages(adev, err_data.err_addr, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index e46439274f3a..3629d8f292ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -51,9 +51,6 @@ struct amdgpu_umc_ras { struct amdgpu_ras_block_object ras_block; void (*err_cnt_init)(struct amdgpu_device *adev); bool (*query_ras_poison_mode)(struct amdgpu_device *adev); - void (*convert_ras_error_address)(struct amdgpu_device *adev, - struct ras_err_data *err_data, uint64_t err_addr, - uint32_t ch_inst, uint32_t umc_inst); void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev, void *ras_error_status); void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index 5d5d031c9e7d..72fd963f178b 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -187,9 +187,9 @@ static void umc_v6_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev, } } -static void umc_v6_7_convert_error_address(struct amdgpu_device *adev, - struct ras_err_data *err_data, uint64_t err_addr, - uint32_t ch_inst, uint32_t umc_inst) +void umc_v6_7_convert_error_address(struct amdgpu_device *adev, + struct ras_err_data *err_data, uint64_t err_addr, + uint32_t ch_inst, uint32_t umc_inst) { uint32_t channel_index; uint64_t soc_pa, retired_page, column; @@ -553,5 +553,4 @@ struct amdgpu_umc_ras umc_v6_7_ras = { .query_ras_poison_mode = umc_v6_7_query_ras_poison_mode, .ecc_info_query_ras_error_count = umc_v6_7_ecc_info_query_ras_error_count, .ecc_info_query_ras_error_address = umc_v6_7_ecc_info_query_ras_error_address, - .convert_ras_error_address = umc_v6_7_convert_error_address, }; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h index fe41ed2f5945..105245d5b6e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h @@ -71,5 +71,7 @@ extern const uint32_t umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM]; extern const uint32_t umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM]; - +void umc_v6_7_convert_error_address(struct amdgpu_device *adev, + struct ras_err_data *err_data, uint64_t err_addr, + uint32_t ch_inst, uint32_t umc_inst); #endif -- cgit v1.2.3 From 45950d88709ce1cd77756aec2e78b2b8dfc58894 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 13 Oct 2022 11:25:23 -0700 Subject: drm/amd/display: Increase frame size limit for display_mode_vba_util_32.o MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building 32-bit images may fail with the following error. drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn32/display_mode_vba_util_32.c: In function ‘dml32_UseMinimumDCFCLK’: drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn32/display_mode_vba_util_32.c:3142:1: error: the frame size of 1096 bytes is larger than 1024 bytes This is seen when building i386:allmodconfig with any of the following compilers. gcc (Debian 12.2.0-3) 12.2.0 gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 The problem is not seen if the compiler supports GCC_PLUGIN_LATENT_ENTROPY because in that case CONFIG_FRAME_WARN is already set to 2048 even for 32-bit builds. dml32_UseMinimumDCFCLK() was introduced with commit dda4fb85e433 ("drm/amd/display: DML changes for DCN32/321"). It declares a large number of local variables. Increase the frame size for the affected file to 2048, similar to other files in the same directory, to enable 32-bit build tests with affected compilers. Fixes: dda4fb85e433 ("drm/amd/display: DML changes for DCN32/321") Cc: Aurabindo Pillai Reported-by: Łukasz Bartosik Signed-off-by: Guenter Roeck Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index d70838edba80..ca7d24000621 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -77,7 +77,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/dcn30_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/dcn32_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_32.o := $(dml_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/display_rq_dlg_calc_32.o := $(dml_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_util_32.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_util_32.o := $(dml_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml/dcn321/dcn321_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/dcn31_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags) -- cgit v1.2.3 From cdabbde1ed262090bff45929e1f5c1153ba5003e Mon Sep 17 00:00:00 2001 From: "Fabio M. De Francesco" Date: Thu, 13 Oct 2022 23:07:14 +0200 Subject: drm/radeon: Replace kmap() with kmap_local_page() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The use of kmap() is being deprecated in favor of kmap_local_page(). There are two main problems with kmap(): (1) It comes with an overhead as the mapping space is restricted and protected by a global lock for synchronization and (2) it also requires global TLB invalidation when the kmap’s pool wraps and it might block when the mapping space is fully utilized until a slot becomes available. With kmap_local_page() the mappings are per thread, CPU local, can take page faults, and can be called from any context (including interrupts). It is faster than kmap() in kernels with HIGHMEM enabled. Furthermore, the tasks can be preempted and, when they are scheduled to run again, the kernel virtual addresses are restored and still valid. Therefore, replace kmap() with kmap_local_page() in radeon_ttm_gtt_read(). Cc: "Venkataramanan, Anirudh" Reviewed-by: Kees Cook Reviewed-by: Christian König Suggested-by: Ira Weiny Signed-off-by: Fabio M. De Francesco Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_ttm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index d33fec488713..bdb4c0e0736b 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -869,11 +869,11 @@ static ssize_t radeon_ttm_gtt_read(struct file *f, char __user *buf, page = rdev->gart.pages[p]; if (page) { - ptr = kmap(page); + ptr = kmap_local_page(page); ptr += off; r = copy_to_user(buf, ptr, cur_size); - kunmap(rdev->gart.pages[p]); + kunmap_local(ptr); } else r = clear_user(buf, cur_size); -- cgit v1.2.3 From a2c554262d39f81be7422fd8bee2f2fe3779f7f5 Mon Sep 17 00:00:00 2001 From: "Fabio M. De Francesco" Date: Sun, 16 Oct 2022 19:41:58 +0200 Subject: drm/amd/amdgpu: Replace kmap() with kmap_local_page() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kmap() is being deprecated in favor of kmap_local_page(). There are two main problems with kmap(): (1) It comes with an overhead as mapping space is restricted and protected by a global lock for synchronization and (2) it also requires global TLB invalidation when the kmap’s pool wraps and it might block when the mapping space is fully utilized until a slot becomes available. With kmap_local_page() the mappings are per thread, CPU local, can take page faults, and can be called from any context (including interrupts). It is faster than kmap() in kernels with HIGHMEM enabled. Furthermore, the tasks can be preempted and, when they are scheduled to run again, the kernel virtual addresses are restored and are still valid. Since its use in amdgpu/amdgpu_ttm.c is safe, it should be preferred. Therefore, replace kmap() with kmap_local_page() in amdgpu/amdgpu_ttm.c. Suggested-by: Ira Weiny Acked-by: Christian König Signed-off-by: Fabio M. De Francesco Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index dc262d2c2925..8782fc6bcd2c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2292,9 +2292,9 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, if (p->mapping != adev->mman.bdev.dev_mapping) return -EPERM; - ptr = kmap(p); + ptr = kmap_local_page(p); r = copy_to_user(buf, ptr + off, bytes); - kunmap(p); + kunmap_local(ptr); if (r) return -EFAULT; @@ -2343,9 +2343,9 @@ static ssize_t amdgpu_iomem_write(struct file *f, const char __user *buf, if (p->mapping != adev->mman.bdev.dev_mapping) return -EPERM; - ptr = kmap(p); + ptr = kmap_local_page(p); r = copy_from_user(ptr + off, buf, bytes); - kunmap(p); + kunmap_local(ptr); if (r) return -EFAULT; -- cgit v1.2.3 From e299b00adf3d4505132e624894f549422ad05eeb Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 17 Oct 2022 09:28:38 -0700 Subject: drm/amdkfd: Fix type of reset_type parameter in hqd_destroy() callback When booting a kernel compiled with CONFIG_CFI_CLANG on a machine with an RX 6700 XT, there is a CFI failure in kfd_destroy_mqd_cp(): [ 12.894543] CFI failure at kfd_destroy_mqd_cp+0x2a/0x40 [amdgpu] (target: hqd_destroy_v10_3+0x0/0x260 [amdgpu]; expected type: 0x8594d794) Clang's kernel Control Flow Integrity (kCFI) makes sure that all indirect call targets have a type that exactly matches the function pointer prototype. In this case, hqd_destroy()'s third parameter, reset_type, should have a type of 'uint32_t' but every implementation of this callback has a third parameter type of 'enum kfd_preempt_type'. Update the function pointer prototype to match reality so that there is no more CFI violation. Link: https://github.com/ClangBuiltLinux/linux/issues/1738 Signed-off-by: Nathan Chancellor Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index e85364dff4e0..5cb3e8634739 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -262,8 +262,9 @@ struct kfd2kgd_calls { uint32_t queue_id); int (*hqd_destroy)(struct amdgpu_device *adev, void *mqd, - uint32_t reset_type, unsigned int timeout, - uint32_t pipe_id, uint32_t queue_id); + enum kfd_preempt_type reset_type, + unsigned int timeout, uint32_t pipe_id, + uint32_t queue_id); bool (*hqd_sdma_is_occupied)(struct amdgpu_device *adev, void *mqd); -- cgit v1.2.3 From b3372fa74d2a7f840bea706607ee2224dfd24039 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Fri, 14 Oct 2022 10:29:46 -0400 Subject: drm/amd/display: add an ASSERT() to irq service functions Currently, if we encounter unimplemented functions, it is difficult to tell what caused them just by looking at dmesg and that is compounded by the fact that it is often hard to reproduce said issues, for instance we have had reports of this condition being triggered when removing a secondary display that is setup in mirror mode and is connected using usb-c. So, to have access to more detailed debugging information, add an ASSERT() to dal_irq_service_ack() and dal_irq_service_set() that only triggers when we encounter an unimplemented function. Reviewed-by: Harry Wentland Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index 7bad39bba86b..d100edaedbbb 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -112,8 +112,15 @@ bool dal_irq_service_set( dal_irq_service_ack(irq_service, source); - if (info->funcs && info->funcs->set) + if (info->funcs && info->funcs->set) { + if (info->funcs->set == dal_irq_service_dummy_set) { + DC_LOG_WARNING("%s: src: %d, st: %d\n", __func__, + source, enable); + ASSERT(0); + } + return info->funcs->set(irq_service, info, enable); + } dal_irq_service_set_generic(irq_service, info, enable); @@ -146,8 +153,14 @@ bool dal_irq_service_ack( return false; } - if (info->funcs && info->funcs->ack) + if (info->funcs && info->funcs->ack) { + if (info->funcs->ack == dal_irq_service_dummy_ack) { + DC_LOG_WARNING("%s: src: %d\n", __func__, source); + ASSERT(0); + } + return info->funcs->ack(irq_service, info); + } dal_irq_service_ack_generic(irq_service, info); -- cgit v1.2.3 From ba5284ebe497044f37c9bb9c7b1564932f4b6610 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 7 Oct 2022 15:10:00 +0200 Subject: clk: renesas: r8a779g0: Add SASYNCPER clocks On R-Car V4H, all PLLs except PLL5 support Spread Spectrum and/or Fractional Multiplication to reduce electromagnetic interference. Add the SASYNCPER and SASYNCPERD[124] clocks, which are used as clock sources for modules that must not be affected by Spread Spectrum and/or Fractional Multiplication. Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Link: https://lore.kernel.org/r/d0f35c35e1f96c5a649ab477e7ba5d8025957cd0.1665147497.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779g0-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c index 9641122133b5..3e8c93facfa1 100644 --- a/drivers/clk/renesas/r8a779g0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c @@ -47,6 +47,7 @@ enum clk_ids { CLK_S0_VIO, CLK_S0_VC, CLK_S0_HSC, + CLK_SASYNCPER, CLK_SV_VIP, CLK_SV_IR, CLK_SDSRC, @@ -84,6 +85,7 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = { DEF_FIXED(".s0_vio", CLK_S0_VIO, CLK_PLL1_DIV2, 2, 1), DEF_FIXED(".s0_vc", CLK_S0_VC, CLK_PLL1_DIV2, 2, 1), DEF_FIXED(".s0_hsc", CLK_S0_HSC, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".sasyncper", CLK_SASYNCPER, CLK_PLL5_DIV4, 3, 1), DEF_FIXED(".sv_vip", CLK_SV_VIP, CLK_PLL1, 5, 1), DEF_FIXED(".sv_ir", CLK_SV_IR, CLK_PLL1, 5, 1), DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5), @@ -128,6 +130,9 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = { DEF_FIXED("s0d4_hsc", R8A779G0_CLK_S0D4_HSC, CLK_S0_HSC, 4, 1), DEF_FIXED("cl16m_hsc", R8A779G0_CLK_CL16M_HSC, CLK_S0_HSC, 48, 1), DEF_FIXED("s0d2_cc", R8A779G0_CLK_S0D2_CC, CLK_S0, 2, 1), + DEF_FIXED("sasyncperd1",R8A779G0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1), + DEF_FIXED("sasyncperd2",R8A779G0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1), + DEF_FIXED("sasyncperd4",R8A779G0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1), DEF_FIXED("svd1_ir", R8A779G0_CLK_SVD1_IR, CLK_SV_IR, 1, 1), DEF_FIXED("svd2_ir", R8A779G0_CLK_SVD2_IR, CLK_SV_IR, 2, 1), DEF_FIXED("svd1_vip", R8A779G0_CLK_SVD1_VIP, CLK_SV_VIP, 1, 1), -- cgit v1.2.3 From 9989bc33c4894e0751679b91fc6eb585772487b9 Mon Sep 17 00:00:00 2001 From: Sai Krishna Potthuri Date: Mon, 17 Oct 2022 18:33:02 +0530 Subject: Revert "pinctrl: pinctrl-zynqmp: Add support for output-enable and bias-high-impedance" This reverts commit ad2bea79ef0144043721d4893eef719c907e2e63. On systems with older PMUFW (Xilinx ZynqMP Platform Management Firmware) using these pinctrl properties can cause system hang because there is missing feature autodetection. When this feature is implemented in the PMUFW, support for these two properties should bring back. Cc: stable@vger.kernel.org Signed-off-by: Sai Krishna Potthuri Acked-by: Michal Simek Link: https://lore.kernel.org/r/20221017130303.21746-2-sai.krishna.potthuri@amd.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-zynqmp.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c index 7d2fbf8a02cd..c98f35ad8921 100644 --- a/drivers/pinctrl/pinctrl-zynqmp.c +++ b/drivers/pinctrl/pinctrl-zynqmp.c @@ -412,10 +412,6 @@ static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: - param = PM_PINCTRL_CONFIG_TRI_STATE; - arg = PM_PINCTRL_TRI_STATE_ENABLE; - ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); - break; case PIN_CONFIG_MODE_LOW_POWER: /* * These cases are mentioned in dts but configurable @@ -424,11 +420,6 @@ static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev, */ ret = 0; break; - case PIN_CONFIG_OUTPUT_ENABLE: - param = PM_PINCTRL_CONFIG_TRI_STATE; - arg = PM_PINCTRL_TRI_STATE_DISABLE; - ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); - break; default: dev_warn(pctldev->dev, "unsupported configuration parameter '%u'\n", -- cgit v1.2.3 From 69d04ca999499bccb6ca849fa2bfc5e6448f7233 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 23 Sep 2022 12:34:41 +0300 Subject: mtd: spi-nor: core: Ignore -ENOTSUPP in spi_nor_init() The Intel SPI-NOR controller does not support the 4-byte address opcode so ->set_4byte_addr_mode() ends up returning -ENOTSUPP and the SPI flash chip probe fail like this: [ 12.291082] spi-nor: probe of spi0.0 failed with error -524 Whereas previously before commit 08412e72afba ("mtd: spi-nor: core: Return error code from set_4byte_addr_mode()") it worked just fine. Fix this by ignoring -ENOTSUPP in spi_nor_init(). Fixes: 08412e72afba ("mtd: spi-nor: core: Return error code from set_4byte_addr_mode()") Cc: stable@vger.kernel.org Reported-by: Hongyu Ning Signed-off-by: Mika Westerberg Reviewed-by: Michael Walle Acked-by: Tudor Ambarus Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20220923093441.3178-1-mika.westerberg@linux.intel.com --- drivers/mtd/spi-nor/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index f2c64006f8d7..bee8fc4c9f07 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2724,7 +2724,9 @@ static int spi_nor_init(struct spi_nor *nor) */ WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET, "enabling reset hack; may not recover from unexpected reboots\n"); - return nor->params->set_4byte_addr_mode(nor, true); + err = nor->params->set_4byte_addr_mode(nor, true); + if (err && err != -ENOTSUPP) + return err; } return 0; -- cgit v1.2.3 From 12b58961de0bd88b3c7dfa5d21f6d67f4678b780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 18 Oct 2022 07:18:22 +0200 Subject: mtd: core: add missing of_node_get() in dynamic partitions code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes unbalanced of_node_put(): [ 1.078910] 6 cmdlinepart partitions found on MTD device gpmi-nand [ 1.085116] Creating 6 MTD partitions on "gpmi-nand": [ 1.090181] 0x000000000000-0x000008000000 : "nandboot" [ 1.096952] 0x000008000000-0x000009000000 : "nandfit" [ 1.103547] 0x000009000000-0x00000b000000 : "nandkernel" [ 1.110317] 0x00000b000000-0x00000c000000 : "nanddtb" [ 1.115525] ------------[ cut here ]------------ [ 1.120141] refcount_t: addition on 0; use-after-free. [ 1.125328] WARNING: CPU: 0 PID: 1 at lib/refcount.c:25 refcount_warn_saturate+0xdc/0x148 [ 1.133528] Modules linked in: [ 1.136589] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc7-next-20220930-04543-g8cf3f7 [ 1.146342] Hardware name: Freescale i.MX8DXL DDR3L EVK (DT) [ 1.151999] pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 1.158965] pc : refcount_warn_saturate+0xdc/0x148 [ 1.163760] lr : refcount_warn_saturate+0xdc/0x148 [ 1.168556] sp : ffff800009ddb080 [ 1.171866] x29: ffff800009ddb080 x28: ffff800009ddb35a x27: 0000000000000002 [ 1.179015] x26: ffff8000098b06ad x25: ffffffffffffffff x24: ffff0a00ffffff05 [ 1.186165] x23: ffff00001fdf6470 x22: ffff800009ddb367 x21: 0000000000000000 [ 1.193314] x20: ffff00001fdfebe8 x19: ffff00001fdfec50 x18: ffffffffffffffff [ 1.200464] x17: 0000000000000000 x16: 0000000000000118 x15: 0000000000000004 [ 1.207614] x14: 0000000000000fff x13: ffff800009bca248 x12: 0000000000000003 [ 1.214764] x11: 00000000ffffefff x10: c0000000ffffefff x9 : 4762cb2ccb52de00 [ 1.221914] x8 : 4762cb2ccb52de00 x7 : 205d313431303231 x6 : 312e31202020205b [ 1.229063] x5 : ffff800009d55c1f x4 : 0000000000000001 x3 : 0000000000000000 [ 1.236213] x2 : 0000000000000000 x1 : ffff800009954be6 x0 : 000000000000002a [ 1.243365] Call trace: [ 1.245806] refcount_warn_saturate+0xdc/0x148 [ 1.250253] kobject_get+0x98/0x9c [ 1.253658] of_node_get+0x20/0x34 [ 1.257072] of_fwnode_get+0x3c/0x54 [ 1.260652] fwnode_get_nth_parent+0xd8/0xf4 [ 1.264926] fwnode_full_name_string+0x3c/0xb4 [ 1.269373] device_node_string+0x498/0x5b4 [ 1.273561] pointer+0x41c/0x5d0 [ 1.276793] vsnprintf+0x4d8/0x694 [ 1.280198] vprintk_store+0x164/0x528 [ 1.283951] vprintk_emit+0x98/0x164 [ 1.287530] vprintk_default+0x44/0x6c [ 1.291284] vprintk+0xf0/0x134 [ 1.294428] _printk+0x54/0x7c [ 1.297486] of_node_release+0xe8/0x128 [ 1.301326] kobject_put+0x98/0xfc [ 1.304732] of_node_put+0x1c/0x28 [ 1.308137] add_mtd_device+0x484/0x6d4 [ 1.311977] add_mtd_partitions+0xf0/0x1d0 [ 1.316078] parse_mtd_partitions+0x45c/0x518 [ 1.320439] mtd_device_parse_register+0xb0/0x274 [ 1.325147] gpmi_nand_probe+0x51c/0x650 [ 1.329074] platform_probe+0xa8/0xd0 [ 1.332740] really_probe+0x130/0x334 [ 1.336406] __driver_probe_device+0xb4/0xe0 [ 1.340681] driver_probe_device+0x3c/0x1f8 [ 1.344869] __driver_attach+0xdc/0x1a4 [ 1.348708] bus_for_each_dev+0x80/0xcc [ 1.352548] driver_attach+0x24/0x30 [ 1.356127] bus_add_driver+0x108/0x1f4 [ 1.359967] driver_register+0x78/0x114 [ 1.363807] __platform_driver_register+0x24/0x30 [ 1.368515] gpmi_nand_driver_init+0x1c/0x28 [ 1.372798] do_one_initcall+0xbc/0x238 [ 1.376638] do_initcall_level+0x94/0xb4 [ 1.380565] do_initcalls+0x54/0x94 [ 1.384058] do_basic_setup+0x1c/0x28 [ 1.387724] kernel_init_freeable+0x110/0x188 [ 1.392084] kernel_init+0x20/0x1a0 [ 1.395578] ret_from_fork+0x10/0x20 [ 1.399157] ---[ end trace 0000000000000000 ]--- [ 1.403782] ------------[ cut here ]------------ Reported-by: Han Xu Fixes: ad9b10d1eaada169 ("mtd: core: introduce of support for dynamic partitions") Signed-off-by: Rafał Miłecki Tested-by: Han Xu Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20221018051822.28685-1-zajec5@gmail.com --- drivers/mtd/mtdcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 18aa54460d36..0b4ca0aa4132 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -562,7 +562,7 @@ static void mtd_check_of_node(struct mtd_info *mtd) if (!mtd_is_partition(mtd)) return; parent = mtd->parent; - parent_dn = dev_of_node(&parent->dev); + parent_dn = of_node_get(dev_of_node(&parent->dev)); if (!parent_dn) return; -- cgit v1.2.3 From 3c6174f9ffcb63ac8b54809c8043d7800b185bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 17 Oct 2022 21:52:50 +0200 Subject: fbdev: da8xx-fb: Fix error handling in .remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even in the presence of problems (here: regulator_disable() might fail), it's important to unregister all resources acquired during .probe() and disable the device (i.e. DMA activity) because even if .remove() returns an error code, the device is removed and the .remove() callback is never called again later to catch up. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Signed-off-by: Helge Deller Fixes: 611097d5daea ("fbdev: da8xx: add support for a regulator") --- drivers/video/fbdev/da8xx-fb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index ae76a2111c77..11922b009ed7 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -1076,7 +1076,8 @@ static int fb_remove(struct platform_device *dev) if (par->lcd_supply) { ret = regulator_disable(par->lcd_supply); if (ret) - return ret; + dev_warn(&dev->dev, "Failed to disable regulator (%pe)\n", + ERR_PTR(ret)); } lcd_disable_raster(DA8XX_FRAME_WAIT); -- cgit v1.2.3 From 776d875fd4cbb3884860ea7f63c3958f02b0c80e Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 14 Oct 2022 20:01:17 +0200 Subject: fbdev: stifb: Fall back to cfb_fillrect() on 32-bit HCRX cards When the text console is scrolling text upwards it calls the fillrect() function to empty the new line. The current implementation doesn't seem to work correctly on HCRX cards in 32-bit mode and leave garbage in that line instead. Fix it by falling back to standard cfb_fillrect() in that case. Signed-off-by: Helge Deller Cc: --- drivers/video/fbdev/stifb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 7753e586e65a..3feb6e40d56d 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -1055,7 +1055,8 @@ stifb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct stifb_info *fb = container_of(info, struct stifb_info, info); - if (rect->rop != ROP_COPY) + if (rect->rop != ROP_COPY || + (fb->id == S9000_ID_HCRX && fb->info.var.bits_per_pixel == 32)) return cfb_fillrect(info, rect); SETUP_HW(fb); -- cgit v1.2.3 From 9750737130dc7b2e4c6f4f33e7e2381e49014299 Mon Sep 17 00:00:00 2001 From: Xuezhi Zhang Date: Tue, 18 Oct 2022 14:25:48 +0800 Subject: fbdev: sm501fb: Convert sysfs snprintf to sysfs_emit Follow the advice of the Documentation/filesystems/sysfs.rst and show() should only use sysfs_emit() or sysfs_emit_at() when formatting the value to be returned to user space. Signed-off-by: Xuezhi Zhang Signed-off-by: Helge Deller --- drivers/video/fbdev/sm501fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index fce6cfbadfd6..f743bfbde2a6 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -1166,7 +1166,7 @@ static ssize_t sm501fb_crtsrc_show(struct device *dev, ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); ctrl &= SM501_DC_CRT_CONTROL_SEL; - return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel"); + return sysfs_emit(buf, "%s\n", ctrl ? "crt" : "panel"); } /* sm501fb_crtsrc_show -- cgit v1.2.3 From 1f3b494d1fc18ebb37aaa47107e9b84bf5b54ff7 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sat, 24 Sep 2022 21:10:10 +0800 Subject: mtd: rawnand: intel: Add missing of_node_put() in ebu_nand_probe() The 'chip_np' returned by of_get_next_child() with refcount decremented, of_node_put() need be called in error path to decrease the refcount. Fixes: bfc618fcc3f1 ("mtd: rawnand: intel: Read the chip-select line from the correct OF node") Signed-off-by: Yang Yingliang Reviewed-by: Martin Blumenstingl Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20220924131010.957117-1-yangyingliang@huawei.com --- drivers/mtd/nand/raw/intel-nand-controller.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c index d4a0987e93ac..6f4cea81f97c 100644 --- a/drivers/mtd/nand/raw/intel-nand-controller.c +++ b/drivers/mtd/nand/raw/intel-nand-controller.c @@ -608,11 +608,12 @@ static int ebu_nand_probe(struct platform_device *pdev) ret = of_property_read_u32(chip_np, "reg", &cs); if (ret) { dev_err(dev, "failed to get chip select: %d\n", ret); - return ret; + goto err_of_node_put; } if (cs >= MAX_CS) { dev_err(dev, "got invalid chip select: %d\n", cs); - return -EINVAL; + ret = -EINVAL; + goto err_of_node_put; } ebu_host->cs_num = cs; @@ -620,18 +621,22 @@ static int ebu_nand_probe(struct platform_device *pdev) resname = devm_kasprintf(dev, GFP_KERNEL, "nand_cs%d", cs); ebu_host->cs[cs].chipaddr = devm_platform_ioremap_resource_byname(pdev, resname); - if (IS_ERR(ebu_host->cs[cs].chipaddr)) - return PTR_ERR(ebu_host->cs[cs].chipaddr); + if (IS_ERR(ebu_host->cs[cs].chipaddr)) { + ret = PTR_ERR(ebu_host->cs[cs].chipaddr); + goto err_of_node_put; + } ebu_host->clk = devm_clk_get(dev, NULL); - if (IS_ERR(ebu_host->clk)) - return dev_err_probe(dev, PTR_ERR(ebu_host->clk), - "failed to get clock\n"); + if (IS_ERR(ebu_host->clk)) { + ret = dev_err_probe(dev, PTR_ERR(ebu_host->clk), + "failed to get clock\n"); + goto err_of_node_put; + } ret = clk_prepare_enable(ebu_host->clk); if (ret) { dev_err(dev, "failed to enable clock: %d\n", ret); - return ret; + goto err_of_node_put; } ebu_host->dma_tx = dma_request_chan(dev, "tx"); @@ -695,6 +700,8 @@ err_cleanup_dma: ebu_dma_cleanup(ebu_host); err_disable_unprepare_clk: clk_disable_unprepare(ebu_host->clk); +err_of_node_put: + of_node_put(chip_np); return ret; } -- cgit v1.2.3 From 0a974e6ae43b3a6aac63dfdfdf171be205fa370c Mon Sep 17 00:00:00 2001 From: Xuezhi Zhang Date: Tue, 18 Oct 2022 15:51:18 +0800 Subject: fbdev: gbefb: Convert sysfs snprintf to sysfs_emit Follow the advice of the Documentation/filesystems/sysfs.rst and show() should only use sysfs_emit() or sysfs_emit_at() when formatting the value to be returned to user space. Signed-off-by: Xuezhi Zhang Signed-off-by: Helge Deller --- drivers/video/fbdev/gbefb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/gbefb.c b/drivers/video/fbdev/gbefb.c index 1582c718329c..000b4aa44241 100644 --- a/drivers/video/fbdev/gbefb.c +++ b/drivers/video/fbdev/gbefb.c @@ -1060,14 +1060,14 @@ static const struct fb_ops gbefb_ops = { static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%u\n", gbe_mem_size); + return sysfs_emit(buf, "%u\n", gbe_mem_size); } static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL); static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision); + return sysfs_emit(buf, "%d\n", gbe_revision); } static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL); -- cgit v1.2.3 From 3ada71310d2c68eebb57772df6bb1f5f033ae802 Mon Sep 17 00:00:00 2001 From: Zhang Qilong Date: Mon, 26 Sep 2022 16:44:56 +0800 Subject: mtd: rawnand: tegra: Fix PM disable depth imbalance in probe The pm_runtime_enable will increase power disable depth. Thus a pairing decrement is needed on the error handling path to keep it balanced according to context. Cc: stable@vger.kernel.org Fixes: d7d9f8ec77fe9 ("mtd: rawnand: add NVIDIA Tegra NAND Flash controller driver") Signed-off-by: Zhang Qilong Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20220926084456.98160-1-zhangqilong3@huawei.com --- drivers/mtd/nand/raw/tegra_nand.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index e12f9f580a15..a9b9031ce616 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -1181,7 +1181,7 @@ static int tegra_nand_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); err = pm_runtime_resume_and_get(&pdev->dev); if (err) - return err; + goto err_dis_pm; err = reset_control_reset(rst); if (err) { @@ -1215,6 +1215,8 @@ static int tegra_nand_probe(struct platform_device *pdev) err_put_pm: pm_runtime_put_sync_suspend(ctrl->dev); pm_runtime_force_suspend(ctrl->dev); +err_dis_pm: + pm_runtime_disable(&pdev->dev); return err; } -- cgit v1.2.3 From ce107713b722af57c4b7f2477594d445b496420e Mon Sep 17 00:00:00 2001 From: Tony O'Brien Date: Tue, 27 Sep 2022 15:47:28 +1300 Subject: mtd: rawnand: marvell: Use correct logic for nand-keep-config Originally the absence of the marvell,nand-keep-config property caused the setup_data_interface function to be provided. However when setup_data_interface was moved into nand_controller_ops the logic was unintentionally inverted. Update the logic so that only if the marvell,nand-keep-config property is present the bootloader NAND config kept. Cc: stable@vger.kernel.org Fixes: 7a08dbaedd36 ("mtd: rawnand: Move ->setup_data_interface() to nand_controller_ops") Signed-off-by: Tony O'Brien Signed-off-by: Chris Packham Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20220927024728.28447-1-chris.packham@alliedtelesis.co.nz --- drivers/mtd/nand/raw/marvell_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index d9f2f1d0b5ef..b9d1e96e3334 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2678,7 +2678,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, chip->controller = &nfc->controller; nand_set_flash_node(chip, np); - if (!of_property_read_bool(np, "marvell,nand-keep-config")) + if (of_property_read_bool(np, "marvell,nand-keep-config")) chip->options |= NAND_KEEP_TIMINGS; mtd = nand_to_mtd(chip); -- cgit v1.2.3 From e9945b2633deccda74a769d94060df49c53ff181 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Tue, 18 Oct 2022 09:09:59 +0200 Subject: pinctrl: ocelot: Fix incorrect trigger of the interrupt. The interrupt controller can detect only link changes. So in case an external device generated a level based interrupt, then the interrupt controller detected correctly the first edge. But the problem was that the interrupt controller was detecting also the edge when the interrupt was cleared. So it would generate another interrupt. The fix for this is to clear the second interrupt but still check the interrupt line status. Fixes: c297561bc98a ("pinctrl: ocelot: Fix interrupt controller") Signed-off-by: Horatiu Vultur Tested-by: Michael Walle Link: https://lore.kernel.org/r/20221018070959.1322606-1-horatiu.vultur@microchip.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ocelot.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c index 62ce3957abe4..687aaa601555 100644 --- a/drivers/pinctrl/pinctrl-ocelot.c +++ b/drivers/pinctrl/pinctrl-ocelot.c @@ -1864,19 +1864,28 @@ static void ocelot_irq_unmask_level(struct irq_data *data) if (val & bit) ack = true; + /* Try to clear any rising edges */ + if (!active && ack) + regmap_write_bits(info->map, REG(OCELOT_GPIO_INTR, info, gpio), + bit, bit); + /* Enable the interrupt now */ gpiochip_enable_irq(chip, gpio); regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), bit, bit); /* - * In case the interrupt line is still active and the interrupt - * controller has not seen any changes in the interrupt line, then it - * means that there happen another interrupt while the line was active. + * In case the interrupt line is still active then it means that + * there happen another interrupt while the line was active. * So we missed that one, so we need to kick the interrupt again * handler. */ - if (active && !ack) { + regmap_read(info->map, REG(OCELOT_GPIO_IN, info, gpio), &val); + if ((!(val & bit) && trigger_level == IRQ_TYPE_LEVEL_LOW) || + (val & bit && trigger_level == IRQ_TYPE_LEVEL_HIGH)) + active = true; + + if (active) { struct ocelot_irq_work *work; work = kmalloc(sizeof(*work), GFP_ATOMIC); -- cgit v1.2.3 From 05e258c6ec669d6d18c494ea03d35962d6f5b545 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 18 Oct 2022 11:11:29 +0200 Subject: mtd: parsers: bcm47xxpart: Fix halfblock reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is some code in the parser that tries to read 0x8000 bytes into a block to "read in the middle" of the block. Well that only works if the block is also 0x10000 bytes all the time, else we get these parse errors as we reach the end of the flash: spi-nor spi0.0: mx25l1606e (2048 Kbytes) mtd_read error while parsing (offset: 0x200000): -22 mtd_read error while parsing (offset: 0x201000): -22 (...) Fix the code to do what I think was intended. Cc: stable@vger.kernel.org Fixes: f0501e81fbaa ("mtd: bcm47xxpart: alternative MAGIC for board_data partition") Cc: Rafał Miłecki Cc: Florian Fainelli Signed-off-by: Linus Walleij Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20221018091129.280026-1-linus.walleij@linaro.org --- drivers/mtd/parsers/bcm47xxpart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/parsers/bcm47xxpart.c b/drivers/mtd/parsers/bcm47xxpart.c index 50fcf4c2174b..13daf9bffd08 100644 --- a/drivers/mtd/parsers/bcm47xxpart.c +++ b/drivers/mtd/parsers/bcm47xxpart.c @@ -233,11 +233,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } /* Read middle of the block */ - err = mtd_read(master, offset + 0x8000, 0x4, &bytes_read, + err = mtd_read(master, offset + (blocksize / 2), 0x4, &bytes_read, (uint8_t *)buf); if (err && !mtd_is_bitflip(err)) { pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", - offset + 0x8000, err); + offset + (blocksize / 2), err); continue; } -- cgit v1.2.3 From 0782b66ed2fbb035dda76111df0954515e417b24 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 18 Oct 2022 18:09:31 +0200 Subject: rtc: cmos: Fix wake alarm breakage Commit 4919d3eb2ec0 ("rtc: cmos: Fix event handler registration ordering issue") overlooked the fact that cmos_do_probe() depended on the preparations carried out by cmos_wake_setup() and the wake alarm stopped working after the ordering of them had been changed. Address this by partially reverting commit 4919d3eb2ec0 so that cmos_wake_setup() is called before cmos_do_probe() again and moving the rtc_wake_setup() invocation from cmos_wake_setup() directly to the callers of cmos_do_probe() where it will happen after a successful completion of the latter. Fixes: 4919d3eb2ec0 ("rtc: cmos: Fix event handler registration ordering issue") Reported-by: Zhang Rui Reported-by: Todd Brandt Signed-off-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/5887691.lOV4Wx5bFT@kreacher Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 610413b4e9ca..01fb31f8e534 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -1233,6 +1233,9 @@ static u32 rtc_handler(void *context) static inline void rtc_wake_setup(struct device *dev) { + if (acpi_disabled) + return; + acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, dev); /* * After the RTC handler is installed, the Fixed_RTC event should @@ -1286,7 +1289,6 @@ static void cmos_wake_setup(struct device *dev) use_acpi_alarm_quirks(); - rtc_wake_setup(dev); acpi_rtc_info.wake_on = rtc_wake_on; acpi_rtc_info.wake_off = rtc_wake_off; @@ -1354,6 +1356,8 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) { int irq, ret; + cmos_wake_setup(&pnp->dev); + if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) { irq = 0; #ifdef CONFIG_X86 @@ -1372,7 +1376,7 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) if (ret) return ret; - cmos_wake_setup(&pnp->dev); + rtc_wake_setup(&pnp->dev); return 0; } @@ -1461,6 +1465,7 @@ static int __init cmos_platform_probe(struct platform_device *pdev) int irq, ret; cmos_of_init(pdev); + cmos_wake_setup(&pdev->dev); if (RTC_IOMAPPED) resource = platform_get_resource(pdev, IORESOURCE_IO, 0); @@ -1474,7 +1479,7 @@ static int __init cmos_platform_probe(struct platform_device *pdev) if (ret) return ret; - cmos_wake_setup(&pdev->dev); + rtc_wake_setup(&pdev->dev); return 0; } -- cgit v1.2.3 From 7e2c58320ed59c9326e82cf9c00090f6a912fb64 Mon Sep 17 00:00:00 2001 From: Yifan Zha Date: Wed, 7 Sep 2022 14:13:02 +0800 Subject: drm/amdgpu: Program GC registers through RLCG interface in gfx_v11/gmc_v11 [Why] L1 blocks most of GC registers accessing by MMIO. [How] Use RLCG interface to program GC registers under SRIOV VF in full access time. Signed-off-by: Yifan Zha Reviewed-by: Hawking Zhang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 18 +++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c index 0b0a72ca5695..7e80caa05060 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c @@ -111,7 +111,7 @@ static int init_interrupts_v11(struct amdgpu_device *adev, uint32_t pipe_id) lock_srbm(adev, mec, pipe, 0, 0); - WREG32(SOC15_REG_OFFSET(GC, 0, regCPC_INT_CNTL), + WREG32_SOC15(GC, 0, regCPC_INT_CNTL, CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK | CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 73106f53246d..e3842dc100d6 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1571,7 +1571,7 @@ static void gfx_v11_0_init_compute_vmid(struct amdgpu_device *adev) WREG32_SOC15(GC, 0, regSH_MEM_BASES, sh_mem_bases); /* Enable trap for each kfd vmid. */ - data = RREG32(SOC15_REG_OFFSET(GC, 0, regSPI_GDBG_PER_VMID_CNTL)); + data = RREG32_SOC15(GC, 0, regSPI_GDBG_PER_VMID_CNTL); data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1); } soc21_grbm_select(adev, 0, 0, 0, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index 846ccb6cf07d..66dfb574cc7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -186,6 +186,10 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, /* Use register 17 for GART */ const unsigned eng = 17; unsigned int i; + unsigned char hub_ip = 0; + + hub_ip = (vmhub == AMDGPU_GFXHUB_0) ? + GC_HWIP : MMHUB_HWIP; spin_lock(&adev->gmc.invalidate_lock); /* @@ -199,8 +203,8 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, if (use_semaphore) { for (i = 0; i < adev->usec_timeout; i++) { /* a read return value of 1 means semaphore acuqire */ - tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + - hub->eng_distance * eng); + tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem + + hub->eng_distance * eng, hub_ip); if (tmp & 0x1) break; udelay(1); @@ -210,12 +214,12 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n"); } - WREG32_NO_KIQ(hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req); + WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req, hub_ip); /* Wait for ACK with a delay.*/ for (i = 0; i < adev->usec_timeout; i++) { - tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_ack + - hub->eng_distance * eng); + tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_ack + + hub->eng_distance * eng, hub_ip); tmp &= 1 << vmid; if (tmp) break; @@ -229,8 +233,8 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, * add semaphore release after invalidation, * write with 0 means semaphore release */ - WREG32_NO_KIQ(hub->vm_inv_eng0_sem + - hub->eng_distance * eng, 0); + WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem + + hub->eng_distance * eng, 0, hub_ip); /* Issue additional private vm invalidation to MMHUB */ if ((vmhub != AMDGPU_GFXHUB_0) && -- cgit v1.2.3 From c520ba3fad335c76f4fad2ab49485eb9edf3de54 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Fri, 14 Oct 2022 15:19:51 +0800 Subject: drm/amd/pm: enable thermal alert on smu_v13_0_10 enable thermal alert on smu_v13_0_10 Signed-off-by: Kenneth Feng Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 3d436e7f6e95..4fe75dd2b329 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1312,12 +1312,10 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } - if (adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 10)) { - ret = smu_enable_thermal_alert(smu); - if (ret) { - dev_err(adev->dev, "Failed to enable thermal alert!\n"); - return ret; - } + ret = smu_enable_thermal_alert(smu); + if (ret) { + dev_err(adev->dev, "Failed to enable thermal alert!\n"); + return ret; } ret = smu_notify_display_change(smu); -- cgit v1.2.3 From c4dfad81e444ba27ea9944c9af061a789ab91201 Mon Sep 17 00:00:00 2001 From: YuBiao Wang Date: Thu, 13 Oct 2022 11:31:55 +0800 Subject: drm/amdgpu: dequeue mes scheduler during fini [Why] If mes is not dequeued during fini, mes will be in an uncleaned state during reload, then mes couldn't receive some commands which leads to reload failure. [How] Perform MES dequeue via MMIO after all the unmap jobs are done by mes and before kiq fini. v2: Move the dequeue operation inside kiq_hw_fini. Signed-off-by: YuBiao Wang Reviewed-by: Jack Xiao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 42 +++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 133804e6018a..fef7d020bc5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -1156,6 +1156,42 @@ static int mes_v11_0_sw_fini(void *handle) return 0; } +static void mes_v11_0_kiq_dequeue_sched(struct amdgpu_device *adev) +{ + uint32_t data; + int i; + + mutex_lock(&adev->srbm_mutex); + soc21_grbm_select(adev, 3, AMDGPU_MES_SCHED_PIPE, 0, 0); + + /* disable the queue if it's active */ + if (RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) & 1) { + WREG32_SOC15(GC, 0, regCP_HQD_DEQUEUE_REQUEST, 1); + for (i = 0; i < adev->usec_timeout; i++) { + if (!(RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) & 1)) + break; + udelay(1); + } + } + data = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); + data = REG_SET_FIELD(data, CP_HQD_PQ_DOORBELL_CONTROL, + DOORBELL_EN, 0); + data = REG_SET_FIELD(data, CP_HQD_PQ_DOORBELL_CONTROL, + DOORBELL_HIT, 1); + WREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL, data); + + WREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL, 0); + + WREG32_SOC15(GC, 0, regCP_HQD_PQ_WPTR_LO, 0); + WREG32_SOC15(GC, 0, regCP_HQD_PQ_WPTR_HI, 0); + WREG32_SOC15(GC, 0, regCP_HQD_PQ_RPTR, 0); + + soc21_grbm_select(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); + + adev->mes.ring.sched.ready = false; +} + static void mes_v11_0_kiq_setting(struct amdgpu_ring *ring) { uint32_t tmp; @@ -1207,6 +1243,9 @@ failure: static int mes_v11_0_kiq_hw_fini(struct amdgpu_device *adev) { + if (adev->mes.ring.sched.ready) + mes_v11_0_kiq_dequeue_sched(adev); + mes_v11_0_enable(adev, false); return 0; } @@ -1262,9 +1301,6 @@ failure: static int mes_v11_0_hw_fini(void *handle) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - adev->mes.ring.sched.ready = false; return 0; } -- cgit v1.2.3 From df768a9770271b0d9faab25f42dfc7bdec87b21c Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam Date: Tue, 18 Oct 2022 07:08:38 -0700 Subject: drm/amdgpu: Fix for BO move issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A user reported a bug on CAPE VERDE system where uvd_v3_1 IP component failed to initialize as there is an issue with BO move code from one memory to other. In function amdgpu_mem_visible() called by amdgpu_bo_move(), when there are no blocks to compare or if we have a single block then break the loop. Fixes: 312b4dc11d4f ("drm/amdgpu: Fix VRAM BO swap issue") Signed-off-by: Arunpravin Paneer Selvam Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8782fc6bcd2c..0de9bc12793d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -439,6 +439,9 @@ static bool amdgpu_mem_visible(struct amdgpu_device *adev, while (cursor.remaining) { amdgpu_res_next(&cursor, cursor.size); + if (!cursor.remaining) + break; + /* ttm_resource_ioremap only supports contiguous memory */ if (end != cursor.start) return false; -- cgit v1.2.3 From 8f8033d5663b18e6efb33feb61f2287a04605ab5 Mon Sep 17 00:00:00 2001 From: Rafael Mendonca Date: Mon, 17 Oct 2022 21:53:57 -0300 Subject: drm/amdgpu/powerplay/psm: Fix memory leak in power state init Commit 902bc65de0b3 ("drm/amdgpu/powerplay/psm: return an error in power state init") made the power state init function return early in case of failure to get an entry from the powerplay table, but it missed to clean up the allocated memory for the current power state before returning. Fixes: 902bc65de0b3 ("drm/amdgpu/powerplay/psm: return an error in power state init") Reviewed-by: Evan Quan Signed-off-by: Rafael Mendonca Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c index 67d7da0b6fed..1d829402cd2e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c @@ -75,8 +75,10 @@ int psm_init_power_state_table(struct pp_hwmgr *hwmgr) for (i = 0; i < table_entries; i++) { result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); if (result) { + kfree(hwmgr->current_ps); kfree(hwmgr->request_ps); kfree(hwmgr->ps); + hwmgr->current_ps = NULL; hwmgr->request_ps = NULL; hwmgr->ps = NULL; return -EINVAL; -- cgit v1.2.3 From db4e955ae333567dea02822624106c0b96a2f84f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 18 Oct 2022 22:35:11 +0200 Subject: rtc: cmos: fix build on non-ACPI platforms Now that rtc_wake_setup is called outside of cmos_wake_setup, it also need to be defined on non-ACPI platforms. Reported-by: kernel test robot Link: https://lore.kernel.org/r/20221018203512.2532407-1-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 01fb31f8e534..58cc2bae2f8a 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -1346,6 +1346,9 @@ static void cmos_check_acpi_rtc_status(struct device *dev, { } +static void rtc_wake_setup(struct device *dev) +{ +} #endif #ifdef CONFIG_PNP -- cgit v1.2.3 From eb83f502adb036cd56c27e13b9ca3b2aabfa790b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Bugge?= Date: Wed, 12 Oct 2022 16:15:42 +0200 Subject: RDMA/cma: Use output interface for net_dev check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 27cfde795a96 ("RDMA/cma: Fix arguments order in net device validation") swapped the src and dst addresses in the call to validate_net_dev(). As a consequence, the test in validate_ipv4_net_dev() to see if the net_dev is the right one, is incorrect for port 1 <-> 2 communication when the ports are on the same sub-net. This is fixed by denoting the flowi4_oif as the device instead of the incoming one. The bug has not been observed using IPv6 addresses. Fixes: 27cfde795a96 ("RDMA/cma: Fix arguments order in net device validation") Signed-off-by: Håkon Bugge Link: https://lore.kernel.org/r/20221012141542.16925-1-haakon.bugge@oracle.com Reviewed-by: Leon Romanovsky Signed-off-by: Leon Romanovsky --- drivers/infiniband/core/cma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index cc2222b85c88..26d1772179b8 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1556,7 +1556,7 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev, return false; memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_iif = net_dev->ifindex; + fl4.flowi4_oif = net_dev->ifindex; fl4.daddr = daddr; fl4.saddr = saddr; -- cgit v1.2.3 From 1afac08b39d85437187bb2a92d89a741b1078f55 Mon Sep 17 00:00:00 2001 From: Dean Luick Date: Tue, 18 Oct 2022 10:27:50 -0400 Subject: IB/hfi1: Correctly move list in sc_disable() Commit 13bac861952a ("IB/hfi1: Fix abba locking issue with sc_disable()") incorrectly tries to move a list from one list head to another. The result is a kernel crash. The crash is triggered when a link goes down and there are waiters for a send to complete. The following signature is seen: BUG: kernel NULL pointer dereference, address: 0000000000000030 [...] Call Trace: sc_disable+0x1ba/0x240 [hfi1] pio_freeze+0x3d/0x60 [hfi1] handle_freeze+0x27/0x1b0 [hfi1] process_one_work+0x1b0/0x380 ? process_one_work+0x380/0x380 worker_thread+0x30/0x360 ? process_one_work+0x380/0x380 kthread+0xd7/0x100 ? kthread_complete_and_exit+0x20/0x20 ret_from_fork+0x1f/0x30 The fix is to use the correct call to move the list. Fixes: 13bac861952a ("IB/hfi1: Fix abba locking issue with sc_disable()") Signed-off-by: Dean Luick Signed-off-by: Dennis Dalessandro Link: https://lore.kernel.org/r/166610327042.674422.6146908799669288976.stgit@awfm-02.cornelisnetworks.com Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/hfi1/pio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c index 3d42bd2b36bd..51ae58c02b15 100644 --- a/drivers/infiniband/hw/hfi1/pio.c +++ b/drivers/infiniband/hw/hfi1/pio.c @@ -913,8 +913,7 @@ void sc_disable(struct send_context *sc) spin_unlock(&sc->release_lock); write_seqlock(&sc->waitlock); - if (!list_empty(&sc->piowait)) - list_move(&sc->piowait, &wake_list); + list_splice_init(&sc->piowait, &wake_list); write_sequnlock(&sc->waitlock); while (!list_empty(&wake_list)) { struct iowait *wait; -- cgit v1.2.3 From 5a637f83d96fc9f27e93385924e7253a5f5187bc Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Mon, 17 Oct 2022 15:14:13 +0200 Subject: dmaengine: stm32-mdma: memset stm32_mdma_chan_config struct before using it New bool m2m_hw has been added at the end of stm32_mdma_chan_config struct to support the STM32 DMA MDMA chaining. m2m_hw is set true in stm32_mdma_slave_config() if peripheral_size is set, but m2m_hw is never initialized false. To ensure this case, and any further new update of the structure, memset it to 0 before using it. Fixes: 696874322771 ("dmaengine: stm32-mdma: add support to be triggered by STM32 DMA") Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20221017131413.202567-1-amelie.delaunay@foss.st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index e28acbcb53f4..b9d4c843635f 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1539,6 +1539,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, return NULL; } + memset(&config, 0, sizeof(config)); config.request = dma_spec->args[0]; config.priority_level = dma_spec->args[1]; config.transfer_config = dma_spec->args[2]; -- cgit v1.2.3 From 0ec8ce07394442d722806fe61b901a5b2b17249d Mon Sep 17 00:00:00 2001 From: Fenghua Yu Date: Fri, 14 Oct 2022 15:25:41 -0700 Subject: dmaengine: idxd: Do not enable user type Work Queue without Shared Virtual Addressing When the idxd_user_drv driver is bound to a Work Queue (WQ) device without IOMMU or with IOMMU Passthrough without Shared Virtual Addressing (SVA), the application gains direct access to physical memory via the device by programming physical address to a submitted descriptor. This allows direct userspace read and write access to arbitrary physical memory. This is inconsistent with the security goals of a good kernel API. Unlike vfio_pci driver, the IDXD char device driver does not provide any ways to pin user pages and translate the address from user VA to IOVA or PA without IOMMU SVA. Therefore the application has no way to instruct the device to perform DMA function. This makes the char device not usable for normal application usage. Since user type WQ without SVA cannot be used for normal application usage and presents the security issue, bind idxd_user_drv driver and enable user type WQ only when SVA is enabled (i.e. user PASID is enabled). Fixes: 448c3de8ac83 ("dmaengine: idxd: create user driver for wq 'device'") Cc: stable@vger.kernel.org Suggested-by: Arjan Van De Ven Signed-off-by: Fenghua Yu Reviewed-by: Dave Jiang Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20221014222541.3912195-1-fenghua.yu@intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/cdev.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c index c2808fd081d6..a9b96b18772f 100644 --- a/drivers/dma/idxd/cdev.c +++ b/drivers/dma/idxd/cdev.c @@ -312,6 +312,24 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev) if (idxd->state != IDXD_DEV_ENABLED) return -ENXIO; + /* + * User type WQ is enabled only when SVA is enabled for two reasons: + * - If no IOMMU or IOMMU Passthrough without SVA, userspace + * can directly access physical address through the WQ. + * - The IDXD cdev driver does not provide any ways to pin + * user pages and translate the address from user VA to IOVA or + * PA without IOMMU SVA. Therefore the application has no way + * to instruct the device to perform DMA function. This makes + * the cdev not usable for normal application usage. + */ + if (!device_user_pasid_enabled(idxd)) { + idxd->cmd_status = IDXD_SCMD_WQ_USER_NO_IOMMU; + dev_dbg(&idxd->pdev->dev, + "User type WQ cannot be enabled without SVA.\n"); + + return -EOPNOTSUPP; + } + mutex_lock(&wq->wq_lock); wq->type = IDXD_WQT_USER; rc = drv_enable_wq(wq); -- cgit v1.2.3 From f8aa6c895d482847c9b799dcdac8bbdb56cb8e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Sun, 16 Oct 2022 17:57:22 +0200 Subject: spi: aspeed: Fix window offset of CE1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The offset value of the mapping window in the kernel structure is calculated using the value of the previous window offset. This doesn't reflect how the HW is configured and can lead to erroneous setting of the second flash device (CE1). Cc: Chin-Ting Kuo Fixes: e3228ed92893 ("spi: spi-mem: Convert Aspeed SMC driver to spi-mem") Signed-off-by: Cédric Le Goater Reviewed-by: Joel Stanley Link: https://lore.kernel.org/r/20221016155722.3520802-1-clg@kaod.org Signed-off-by: Mark Brown --- drivers/spi/spi-aspeed-smc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 33cefcf18392..b90571396a60 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -398,7 +398,7 @@ static void aspeed_spi_get_windows(struct aspeed_spi *aspi, windows[cs].cs = cs; windows[cs].size = data->segment_end(aspi, reg_val) - data->segment_start(aspi, reg_val); - windows[cs].offset = cs ? windows[cs - 1].offset + windows[cs - 1].size : 0; + windows[cs].offset = data->segment_start(aspi, reg_val) - aspi->ahb_base_phy; dev_vdbg(aspi->dev, "CE%d offset=0x%.8x size=0x%x\n", cs, windows[cs].offset, windows[cs].size); } -- cgit v1.2.3 From 097a4a1612389c31d2c4b95dfa816b91212d7f54 Mon Sep 17 00:00:00 2001 From: Jiangshan Yi Date: Sun, 9 Oct 2022 16:39:44 +0800 Subject: watchdog: sp805_wdt: fix spelling typo in comment Fix spelling typo in comment. Reported-by: k2ci Signed-off-by: Jiangshan Yi Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221009083944.2988237-1-13667453960@163.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sp805_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 78ba36689eec..2756ed54ca3d 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -88,7 +88,7 @@ static bool wdt_is_running(struct watchdog_device *wdd) return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK; } -/* This routine finds load value that will reset system in required timout */ +/* This routine finds load value that will reset system in required timeout */ static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout) { struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); -- cgit v1.2.3 From 82ebbe65d781064cfb0a6a8af221a9cebcaaac9e Mon Sep 17 00:00:00 2001 From: Manank Patel Date: Thu, 13 Oct 2022 15:22:58 +0530 Subject: drivers: watchdog: exar_wdt.c fix use after free fix use after free by storing the result of PTR_ERR(n->pdev) to a local variable before returning. Signed-off-by: Manank Patel Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221013095258.1424967-1-pmanank200502@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/exar_wdt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/exar_wdt.c b/drivers/watchdog/exar_wdt.c index 35058d8b21bc..7c61ff343271 100644 --- a/drivers/watchdog/exar_wdt.c +++ b/drivers/watchdog/exar_wdt.c @@ -355,8 +355,10 @@ static int __init exar_wdt_register(struct wdt_priv *priv, const int idx) &priv->wdt_res, 1, priv, sizeof(*priv)); if (IS_ERR(n->pdev)) { + int err = PTR_ERR(n->pdev); + kfree(n); - return PTR_ERR(n->pdev); + return err; } list_add_tail(&n->list, &pdev_list); -- cgit v1.2.3 From a4f7fcd7023ba63bdfe82a054c4ceb636a55d155 Mon Sep 17 00:00:00 2001 From: Jilin Yuan Date: Wed, 19 Oct 2022 20:57:38 +0800 Subject: fbdev: sisfb: fix repeated word in comment Signed-off-by: Jilin Yuan Signed-off-by: Helge Deller --- drivers/video/fbdev/sis/sis_accel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/sis/sis_accel.c b/drivers/video/fbdev/sis/sis_accel.c index 1914ab5a5a91..5850e4325f07 100644 --- a/drivers/video/fbdev/sis/sis_accel.c +++ b/drivers/video/fbdev/sis/sis_accel.c @@ -202,7 +202,7 @@ SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int * and destination blitting areas overlap and * adapt the bitmap addresses synchronously * if the coordinates exceed the valid range. - * The the areas do not overlap, we do our + * The areas do not overlap, we do our * normal check. */ if((mymax - mymin) < height) { -- cgit v1.2.3 From 70281592bf3fb7a2a193dced4d4e58a9ee96aa6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 19 Oct 2022 15:24:22 +0200 Subject: fbdev: xilinxfb: Make xilinxfb_release() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function xilinxfb_release() returns zero unconditionally. Make it return void. There is no semantic change, the only effect is that it becomes obvious that the driver's .remove() callback always returns zero. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Signed-off-by: Helge Deller --- drivers/video/fbdev/xilinxfb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c index 438e2c78142f..1ac83900a21c 100644 --- a/drivers/video/fbdev/xilinxfb.c +++ b/drivers/video/fbdev/xilinxfb.c @@ -376,7 +376,7 @@ err_cmap: return rc; } -static int xilinxfb_release(struct device *dev) +static void xilinxfb_release(struct device *dev) { struct xilinxfb_drvdata *drvdata = dev_get_drvdata(dev); @@ -402,8 +402,6 @@ static int xilinxfb_release(struct device *dev) if (!(drvdata->flags & BUS_ACCESS_FLAG)) dcr_unmap(drvdata->dcr_host, drvdata->dcr_len); #endif - - return 0; } /* --------------------------------------------------------------------- @@ -480,7 +478,9 @@ static int xilinxfb_of_probe(struct platform_device *pdev) static int xilinxfb_of_remove(struct platform_device *op) { - return xilinxfb_release(&op->dev); + xilinxfb_release(&op->dev); + + return 0; } /* Match table for of_platform binding */ -- cgit v1.2.3 From 7d1aa08aff0621a595c1b42efb493c475eefeeb3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 19 Oct 2022 09:12:01 +0300 Subject: gpio: tegra: Convert to immutable irq chip Update the driver to use an immutable IRQ chip to fix this warning: "not an immutable chip, please consider fixing it!" Preserve per-chip labels by adding an ->irq_print_chip() callback. Tested-by: Svyatoslav Ryhel # TF201 T30 Tested-by: Robert Eckelmann # TF101 T20 Signed-off-by: Svyatoslav Ryhel Reviewed-by: Dmitry Osipenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tegra.c | 60 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index e4fb4cb38a0f..5b265a6fd3c1 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -94,7 +95,6 @@ struct tegra_gpio_info { struct tegra_gpio_bank *bank_info; const struct tegra_gpio_soc_config *soc; struct gpio_chip gc; - struct irq_chip ic; u32 bank_count; unsigned int *irqs; }; @@ -288,6 +288,7 @@ static void tegra_gpio_irq_mask(struct irq_data *d) unsigned int gpio = d->hwirq; tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 0); + gpiochip_disable_irq(chip, gpio); } static void tegra_gpio_irq_unmask(struct irq_data *d) @@ -296,6 +297,7 @@ static void tegra_gpio_irq_unmask(struct irq_data *d) struct tegra_gpio_info *tgi = gpiochip_get_data(chip); unsigned int gpio = d->hwirq; + gpiochip_enable_irq(chip, gpio); tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 1); } @@ -598,10 +600,47 @@ static void tegra_gpio_irq_release_resources(struct irq_data *d) tegra_gpio_enable(tgi, d->hwirq); } +static void tegra_gpio_irq_print_chip(struct irq_data *d, struct seq_file *s) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + + seq_printf(s, dev_name(chip->parent)); +} + +static const struct irq_chip tegra_gpio_irq_chip = { + .irq_shutdown = tegra_gpio_irq_shutdown, + .irq_ack = tegra_gpio_irq_ack, + .irq_mask = tegra_gpio_irq_mask, + .irq_unmask = tegra_gpio_irq_unmask, + .irq_set_type = tegra_gpio_irq_set_type, +#ifdef CONFIG_PM_SLEEP + .irq_set_wake = tegra_gpio_irq_set_wake, +#endif + .irq_print_chip = tegra_gpio_irq_print_chip, + .irq_request_resources = tegra_gpio_irq_request_resources, + .irq_release_resources = tegra_gpio_irq_release_resources, + .flags = IRQCHIP_IMMUTABLE, +}; + +static const struct irq_chip tegra210_gpio_irq_chip = { + .irq_shutdown = tegra_gpio_irq_shutdown, + .irq_ack = tegra_gpio_irq_ack, + .irq_mask = tegra_gpio_irq_mask, + .irq_unmask = tegra_gpio_irq_unmask, + .irq_set_affinity = tegra_gpio_irq_set_affinity, + .irq_set_type = tegra_gpio_irq_set_type, +#ifdef CONFIG_PM_SLEEP + .irq_set_wake = tegra_gpio_irq_set_wake, +#endif + .irq_print_chip = tegra_gpio_irq_print_chip, + .irq_request_resources = tegra_gpio_irq_request_resources, + .irq_release_resources = tegra_gpio_irq_release_resources, + .flags = IRQCHIP_IMMUTABLE, +}; + #ifdef CONFIG_DEBUG_FS #include -#include static int tegra_dbg_gpio_show(struct seq_file *s, void *unused) { @@ -689,18 +728,6 @@ static int tegra_gpio_probe(struct platform_device *pdev) tgi->gc.ngpio = tgi->bank_count * 32; tgi->gc.parent = &pdev->dev; - tgi->ic.name = "GPIO"; - tgi->ic.irq_ack = tegra_gpio_irq_ack; - tgi->ic.irq_mask = tegra_gpio_irq_mask; - tgi->ic.irq_unmask = tegra_gpio_irq_unmask; - tgi->ic.irq_set_type = tegra_gpio_irq_set_type; - tgi->ic.irq_shutdown = tegra_gpio_irq_shutdown; -#ifdef CONFIG_PM_SLEEP - tgi->ic.irq_set_wake = tegra_gpio_irq_set_wake; -#endif - tgi->ic.irq_request_resources = tegra_gpio_irq_request_resources; - tgi->ic.irq_release_resources = tegra_gpio_irq_release_resources; - platform_set_drvdata(pdev, tgi); if (tgi->soc->debounce_supported) @@ -733,7 +760,6 @@ static int tegra_gpio_probe(struct platform_device *pdev) } irq = &tgi->gc.irq; - irq->chip = &tgi->ic; irq->fwnode = of_node_to_fwnode(pdev->dev.of_node); irq->child_to_parent_hwirq = tegra_gpio_child_to_parent_hwirq; irq->populate_parent_alloc_arg = tegra_gpio_populate_parent_fwspec; @@ -752,7 +778,9 @@ static int tegra_gpio_probe(struct platform_device *pdev) if (!irq->parent_domain) return -EPROBE_DEFER; - tgi->ic.irq_set_affinity = tegra_gpio_irq_set_affinity; + gpio_irq_chip_set_chip(irq, &tegra210_gpio_irq_chip); + } else { + gpio_irq_chip_set_chip(irq, &tegra_gpio_irq_chip); } tgi->regs = devm_platform_ioremap_resource(pdev, 0); -- cgit v1.2.3 From 23722fb46725da42b80bc55a91a9bac69e35188a Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 21 Jul 2022 14:03:29 +0100 Subject: coresight: Fix possible deadlock with lock dependency With lockdeps enabled, we get the following warning: ====================================================== WARNING: possible circular locking dependency detected ------------------------------------------------------ kworker/u12:1/53 is trying to acquire lock: ffff80000adce220 (coresight_mutex){+.+.}-{4:4}, at: coresight_set_assoc_ectdev_mutex+0x3c/0x5c but task is already holding lock: ffff80000add1f60 (ect_mutex){+.+.}-{4:4}, at: cti_probe+0x318/0x394 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (ect_mutex){+.+.}-{4:4}: __mutex_lock_common+0xd8/0xe60 mutex_lock_nested+0x44/0x50 cti_add_assoc_to_csdev+0x4c/0x184 coresight_register+0x2f0/0x314 tmc_probe+0x33c/0x414 -> #0 (coresight_mutex){+.+.}-{4:4}: __lock_acquire+0x1a20/0x32d0 lock_acquire+0x160/0x308 __mutex_lock_common+0xd8/0xe60 mutex_lock_nested+0x44/0x50 coresight_set_assoc_ectdev_mutex+0x3c/0x5c cti_update_conn_xrefs+0x6c/0xf8 cti_probe+0x33c/0x394 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(ect_mutex); lock(coresight_mutex); lock(ect_mutex); lock(coresight_mutex); *** DEADLOCK *** 4 locks held by kworker/u12:1/53: #0: ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_one_work+0x1fc/0x63c #1: (deferred_probe_work){+.+.}-{0:0}, at: process_one_work+0x228/0x63c #2: (&dev->mutex){....}-{4:4}, at: __device_attach+0x48/0x1a8 #3: (ect_mutex){+.+.}-{4:4}, at: cti_probe+0x318/0x394 To fix the same, call cti_add_assoc_to_csdev without the holding coresight_mutex and confine the locking while setting the associated ect / cti device using coresight_set_assoc_ectdev_mutex(). Fixes: 177af8285b59 ("coresight: cti: Enable CTI associated with devices") Cc: Mathieu Poirier Cc: Suzuki K Poulose Cc: Mike Leach Cc: Leo Yan Signed-off-by: Sudeep Holla Reviewed-by: Mike Leach Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20220721130329.3787211-1-sudeep.holla@arm.com --- drivers/hwtracing/coresight/coresight-core.c | 7 ++++--- drivers/hwtracing/coresight/coresight-cti-core.c | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index d5dbc67bacb4..f3068175ca9d 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1687,14 +1687,15 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) ret = coresight_fixup_device_conns(csdev); if (!ret) ret = coresight_fixup_orphan_conns(csdev); - if (!ret && cti_assoc_ops && cti_assoc_ops->add) - cti_assoc_ops->add(csdev); out_unlock: mutex_unlock(&coresight_mutex); /* Success */ - if (!ret) + if (!ret) { + if (cti_assoc_ops && cti_assoc_ops->add) + cti_assoc_ops->add(csdev); return csdev; + } /* Unregister the device if needed */ if (registered) { diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index 8988b2ed2ea6..1be92342b5b9 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -541,7 +541,7 @@ cti_match_fixup_csdev(struct cti_device *ctidev, const char *node_name, /* * Search the cti list to add an associated CTI into the supplied CS device * This will set the association if CTI declared before the CS device. - * (called from coresight_register() with coresight_mutex locked). + * (called from coresight_register() without coresight_mutex locked). */ static void cti_add_assoc_to_csdev(struct coresight_device *csdev) { @@ -569,7 +569,8 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev) * if we found a matching csdev then update the ECT * association pointer for the device with this CTI. */ - csdev->ect_dev = ect_item->csdev; + coresight_set_assoc_ectdev_mutex(csdev->ect_dev, + ect_item->csdev); break; } } -- cgit v1.2.3 From 665c157e0204176023860b51a46528ba0ba62c33 Mon Sep 17 00:00:00 2001 From: James Clark Date: Wed, 5 Oct 2022 14:14:52 +0100 Subject: coresight: cti: Fix hang in cti_disable_hw() cti_enable_hw() and cti_disable_hw() are called from an atomic context so shouldn't use runtime PM because it can result in a sleep when communicating with firmware. Since commit 3c6656337852 ("Revert "firmware: arm_scmi: Add clock management to the SCMI power domain""), this causes a hang on Juno when running the Perf Coresight tests or running this command: perf record -e cs_etm//u -- ls This was also missed until the revert commit because pm_runtime_put() was called with the wrong device until commit 692c9a499b28 ("coresight: cti: Correct the parameter for pm_runtime_put") With lock and scheduler debugging enabled the following is output: coresight cti_sys0: cti_enable_hw -- dev:cti_sys0 parent: 20020000.cti BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1151 in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 330, name: perf-exec preempt_count: 2, expected: 0 RCU nest depth: 0, expected: 0 INFO: lockdep is turned off. irq event stamp: 0 hardirqs last enabled at (0): [<0000000000000000>] 0x0 hardirqs last disabled at (0): [] copy_process+0xa0c/0x1948 softirqs last enabled at (0): [] copy_process+0xa0c/0x1948 softirqs last disabled at (0): [<0000000000000000>] 0x0 CPU: 3 PID: 330 Comm: perf-exec Not tainted 6.0.0-00053-g042116d99298 #7 Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform, BIOS EDK II Sep 13 2022 Call trace: dump_backtrace+0x134/0x140 show_stack+0x20/0x58 dump_stack_lvl+0x8c/0xb8 dump_stack+0x18/0x34 __might_resched+0x180/0x228 __might_sleep+0x50/0x88 __pm_runtime_resume+0xac/0xb0 cti_enable+0x44/0x120 coresight_control_assoc_ectdev+0xc0/0x150 coresight_enable_path+0xb4/0x288 etm_event_start+0x138/0x170 etm_event_add+0x48/0x70 event_sched_in.isra.122+0xb4/0x280 merge_sched_in+0x1fc/0x3d0 visit_groups_merge.constprop.137+0x16c/0x4b0 ctx_sched_in+0x114/0x1f0 perf_event_sched_in+0x60/0x90 ctx_resched+0x68/0xb0 perf_event_exec+0x138/0x508 begin_new_exec+0x52c/0xd40 load_elf_binary+0x6b8/0x17d0 bprm_execve+0x360/0x7f8 do_execveat_common.isra.47+0x218/0x238 __arm64_sys_execve+0x48/0x60 invoke_syscall+0x4c/0x110 el0_svc_common.constprop.4+0xfc/0x120 do_el0_svc+0x34/0xc0 el0_svc+0x40/0x98 el0t_64_sync_handler+0x98/0xc0 el0t_64_sync+0x170/0x174 Fix the issue by removing the runtime PM calls completely. They are not needed here because it must have already been done when building the path for a trace. Fixes: 835d722ba10a ("coresight: cti: Initial CoreSight CTI Driver") Reported-by: Aishwarya TCV Reported-by: Cristian Marussi Suggested-by: Suzuki Poulose Signed-off-by: James Clark Reviewed-by: Mike Leach Tested-by: Mike Leach Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20221005131452.1506328-1-james.clark@arm.com --- drivers/hwtracing/coresight/coresight-cti-core.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index 1be92342b5b9..4a02ae23d3a0 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -94,7 +94,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) unsigned long flags; int rc = 0; - pm_runtime_get_sync(dev->parent); spin_lock_irqsave(&drvdata->spinlock, flags); /* no need to do anything if enabled or unpowered*/ @@ -119,7 +118,6 @@ cti_state_unchanged: /* cannot enable due to error */ cti_err_not_enabled: spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(dev->parent); return rc; } @@ -175,7 +173,6 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); spin_unlock(&drvdata->spinlock); - pm_runtime_put(dev->parent); return 0; /* not disabled this call */ -- cgit v1.2.3 From cf00b33058b196b4db928419dde68993b15a975b Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Mon, 15 Aug 2022 16:40:43 +0100 Subject: cxl/mbox: Add a check on input payload size A bug in the LSA code resulted in transfers slightly larger than the mailbox size. Let us make it easier to catch similar issues in future by adding a low level check. Signed-off-by: Jonathan Cameron Link: https://lore.kernel.org/r/20220815154044.24733-2-Jonathan.Cameron@huawei.com Signed-off-by: Dan Williams --- drivers/cxl/core/mbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 16176b9278b4..0c90f13870a4 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -174,7 +174,7 @@ int cxl_mbox_send_cmd(struct cxl_dev_state *cxlds, u16 opcode, void *in, }; int rc; - if (out_size > cxlds->payload_size) + if (in_size > cxlds->payload_size || out_size > cxlds->payload_size) return -E2BIG; rc = cxlds->mbox_send(cxlds, &mbox_cmd); -- cgit v1.2.3 From 2816e24b0510e0c185c0c46acff1ce7aa4c4443f Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 18 Aug 2022 17:42:10 +0100 Subject: cxl/region: Fix null pointer dereference due to pass through decoder commit Not all decoders have a commit callback. The CXL specification allows a host bridge with a single root port to have no explicit HDM decoders. Currently the region driver assumes there are none. As such the CXL core creates a special pass through decoder instance without a commit callback. Prior to this patch, the ->commit() callback was called unconditionally. Thus a configuration with 1 Host Bridge, 1 Root Port, 1 switch with multiple downstream ports below which there are multiple CXL type 3 devices results in a situation where committing the region causes a null pointer dereference. Reported-by: Bobo WL Fixes: 176baefb2eb5 ("cxl/hdm: Commit decoder state to hardware") Signed-off-by: Jonathan Cameron Reviewed-by: Vishal Verma Link: https://lore.kernel.org/r/20220818164210.2084-1-Jonathan.Cameron@huawei.com Signed-off-by: Dan Williams --- drivers/cxl/core/region.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index 401148016978..c49d9a5f1091 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -174,7 +174,8 @@ static int cxl_region_decode_commit(struct cxl_region *cxlr) iter = to_cxl_port(iter->dev.parent)) { cxl_rr = cxl_rr_load(iter, cxlr); cxld = cxl_rr->decoder; - rc = cxld->commit(cxld); + if (cxld->commit) + rc = cxld->commit(cxld); if (rc) break; } -- cgit v1.2.3 From f010c75c05299ecd65adfd31a7841eea3476ce1f Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Mon, 15 Aug 2022 16:40:44 +0100 Subject: cxl/pmem: Fix failure to account for 8 byte header for writes to the device LSA. Writes to the device must include an offset and size as defined in CXL 2.0 8.2.9.5.2.4 Set LSA (Opcode 4103h) Fixes tag is non obvious as this code has been through several reworks and variable names + wasn't in use until the addition of the region code. Due to a bug in QEMU CXL emulation this overrun resulted in QEMU crashing. Reported-by: Bobo WL Signed-off-by: Jonathan Cameron Fixes: 60b8f17215de ("cxl/pmem: Translate NVDIMM label commands to CXL label commands") Link: https://lore.kernel.org/r/20220815154044.24733-3-Jonathan.Cameron@huawei.com Signed-off-by: Dan Williams --- drivers/cxl/pmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 7dc0a2fa1a6b..115a7b79f343 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -107,7 +107,7 @@ static int cxl_pmem_get_config_size(struct cxl_dev_state *cxlds, *cmd = (struct nd_cmd_get_config_size) { .config_size = cxlds->lsa_size, - .max_xfer = cxlds->payload_size, + .max_xfer = cxlds->payload_size - sizeof(struct cxl_mbox_set_lsa), }; return 0; -- cgit v1.2.3 From 94423589689124e8cd145b38a1034be7f25835b2 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 19 Oct 2022 14:41:04 +0800 Subject: net: netsec: fix error handling in netsec_register_mdio() If phy_device_register() fails, phy_device_free() need be called to put refcount, so memory of phy device and device name can be freed in callback function. If get_phy_device() fails, mdiobus_unregister() need be called, or it will cause warning in mdiobus_free() and kobject is leaked. Fixes: 533dd11a12f6 ("net: socionext: Add Synquacer NetSec driver") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221019064104.3228892-1-yangyingliang@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/socionext/netsec.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index 2240f6d0b89b..9b46579b5a10 100644 --- a/drivers/net/ethernet/socionext/netsec.c +++ b/drivers/net/ethernet/socionext/netsec.c @@ -1961,11 +1961,13 @@ static int netsec_register_mdio(struct netsec_priv *priv, u32 phy_addr) ret = PTR_ERR(priv->phydev); dev_err(priv->dev, "get_phy_device err(%d)\n", ret); priv->phydev = NULL; + mdiobus_unregister(bus); return -ENODEV; } ret = phy_device_register(priv->phydev); if (ret) { + phy_device_free(priv->phydev); mdiobus_unregister(bus); dev_err(priv->dev, "phy_device_register err(%d)\n", ret); -- cgit v1.2.3 From f8c1c66b99a570c08b9d26e4347276f00e49bba7 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Wed, 19 Oct 2022 10:30:56 +0200 Subject: net: lan966x: Fix the rx drop counter Currently the rx drop is calculated as the sum of multiple HW drop counters. The issue is that not all the HW drop counters were added for the rx drop counter. So if for example you have a police that drops frames, they were not see in the rx drop counter. Fix this by updating how the rx drop counter is calculated. It is required to add also RX_RED_PRIO_* HW counters. Fixes: 12c2d0a5b8e2 ("net: lan966x: add ethtool configuration and statistics") Signed-off-by: Horatiu Vultur Link: https://lore.kernel.org/r/20221019083056.2744282-1-horatiu.vultur@microchip.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c index e58a27fd8b50..fea42542be28 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c @@ -656,7 +656,15 @@ void lan966x_stats_get(struct net_device *dev, stats->rx_dropped = dev->stats.rx_dropped + lan966x->stats[idx + SYS_COUNT_RX_LONG] + lan966x->stats[idx + SYS_COUNT_DR_LOCAL] + - lan966x->stats[idx + SYS_COUNT_DR_TAIL]; + lan966x->stats[idx + SYS_COUNT_DR_TAIL] + + lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_0] + + lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_1] + + lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_2] + + lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_3] + + lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_4] + + lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_5] + + lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_6] + + lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_7]; for (i = 0; i < LAN966X_NUM_TC; i++) { stats->rx_dropped += -- cgit v1.2.3 From c0605cd6750f2db9890c43a91ea4d77be8fb4908 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 19 Oct 2022 17:57:51 +0800 Subject: net: hinic: fix incorrect assignment issue in hinic_set_interrupt_cfg() The value of lli_credit_cnt is incorrectly assigned, fix it. Fixes: a0337c0dee68 ("hinic: add support to set and get irq coalesce") Signed-off-by: Zhengchao Shao Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 94f470556295..27795288c586 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -877,7 +877,7 @@ int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev, if (err) return -EINVAL; - interrupt_info->lli_credit_cnt = temp_info.lli_timer_cnt; + interrupt_info->lli_credit_cnt = temp_info.lli_credit_cnt; interrupt_info->lli_timer_cnt = temp_info.lli_timer_cnt; err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM, -- cgit v1.2.3 From 4c1f602df8956bc0decdafd7e4fc7eef50c550b1 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 19 Oct 2022 17:57:52 +0800 Subject: net: hinic: fix memory leak when reading function table When the input parameter idx meets the expected case option in hinic_dbg_get_func_table(), read_data is not released. Fix it. Fixes: 5215e16244ee ("hinic: add support to query function table") Signed-off-by: Zhengchao Shao Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/huawei/hinic/hinic_debugfs.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c b/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c index 19eb839177ec..061952c6c21a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c @@ -85,6 +85,7 @@ static int hinic_dbg_get_func_table(struct hinic_dev *nic_dev, int idx) struct tag_sml_funcfg_tbl *funcfg_table_elem; struct hinic_cmd_lt_rd *read_data; u16 out_size = sizeof(*read_data); + int ret = ~0; int err; read_data = kzalloc(sizeof(*read_data), GFP_KERNEL); @@ -111,20 +112,25 @@ static int hinic_dbg_get_func_table(struct hinic_dev *nic_dev, int idx) switch (idx) { case VALID: - return funcfg_table_elem->dw0.bs.valid; + ret = funcfg_table_elem->dw0.bs.valid; + break; case RX_MODE: - return funcfg_table_elem->dw0.bs.nic_rx_mode; + ret = funcfg_table_elem->dw0.bs.nic_rx_mode; + break; case MTU: - return funcfg_table_elem->dw1.bs.mtu; + ret = funcfg_table_elem->dw1.bs.mtu; + break; case RQ_DEPTH: - return funcfg_table_elem->dw13.bs.cfg_rq_depth; + ret = funcfg_table_elem->dw13.bs.cfg_rq_depth; + break; case QUEUE_NUM: - return funcfg_table_elem->dw13.bs.cfg_q_num; + ret = funcfg_table_elem->dw13.bs.cfg_q_num; + break; } kfree(read_data); - return ~0; + return ret; } static ssize_t hinic_dbg_cmd_read(struct file *filp, char __user *buffer, size_t count, -- cgit v1.2.3 From 363cc87767f6ddcfb9158ad2e2afa2f8d5c4b94e Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 19 Oct 2022 17:57:53 +0800 Subject: net: hinic: fix the issue of CMDQ memory leaks When hinic_set_cmdq_depth() fails in hinic_init_cmdqs(), the cmdq memory is not released correctly. Fix it. Fixes: 72ef908bb3ff ("hinic: add three net_device_ops of vf") Signed-off-by: Zhengchao Shao Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index 78190e88cd75..d39eec9c62bf 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -924,7 +924,7 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif, err_set_cmdq_depth: hinic_ceq_unregister_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ); - + free_cmdq(&cmdqs->cmdq[HINIC_CMDQ_SYNC]); err_cmdq_ctxt: hinic_wqs_cmdq_free(&cmdqs->cmdq_pages, cmdqs->saved_wqs, HINIC_MAX_CMDQ_TYPES); -- cgit v1.2.3 From 8ec2f4c6b2e11a4249bba77460f0cfe6d95a82f8 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 19 Oct 2022 17:57:54 +0800 Subject: net: hinic: fix the issue of double release MBOX callback of VF In hinic_vf_func_init(), if VF fails to register information with PF through the MBOX, the MBOX callback function of VF is released once. But it is released again in hinic_init_hwdev(). Remove one. Fixes: 7dd29ee12865 ("hinic: add sriov feature support") Signed-off-by: Zhengchao Shao Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/huawei/hinic/hinic_sriov.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c index a5f08b969e3f..f7e05b41385b 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c @@ -1174,7 +1174,6 @@ int hinic_vf_func_init(struct hinic_hwdev *hwdev) dev_err(&hwdev->hwif->pdev->dev, "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n", err, register_info.status, out_size); - hinic_unregister_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC); return -EIO; } } else { -- cgit v1.2.3 From 15a9dbec631cd69dfbbfc4e2cbf90c9dd8432a8f Mon Sep 17 00:00:00 2001 From: Sergiu Moga Date: Wed, 19 Oct 2022 15:09:32 +0300 Subject: net: macb: Specify PHY PM management done by MAC The `macb_resume`/`macb_suspend` methods already call the `phylink_start`/`phylink_stop` methods during their execution so explicitly say that the PM of the PHY is done by MAC by using the `mac_managed_pm` flag of the `struct phylink_config`. This also fixes the warning message issued during resume: WARNING: CPU: 0 PID: 237 at drivers/net/phy/phy_device.c:323 mdio_bus_phy_resume+0x144/0x148 Depends-on: 96de900ae78e ("net: phylink: add mac_managed_pm in phylink_config structure") Fixes: 744d23c71af3 ("net: phy: Warn about incorrect mdio_bus_phy_resume() state") Signed-off-by: Sergiu Moga Reviewed-by: Florian Fainelli Reviewed-by: Claudiu Beznea Link: https://lore.kernel.org/r/20221019120929.63098-1-sergiu.moga@microchip.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/cadence/macb_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 51c9fd6f68a4..4f63f1ba3161 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -806,6 +806,7 @@ static int macb_mii_probe(struct net_device *dev) bp->phylink_config.dev = &dev->dev; bp->phylink_config.type = PHYLINK_NETDEV; + bp->phylink_config.mac_managed_pm = true; if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { bp->phylink_config.poll_fixed_state = true; -- cgit v1.2.3 From e840d8f4a1b323973052a1af5ad4edafcde8ae3d Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Thu, 20 Oct 2022 11:05:05 +0800 Subject: nfc: virtual_ncidev: Fix memory leak in virtual_nci_send() skb should be free in virtual_nci_send(), otherwise kmemleak will report memleak. Steps for reproduction (simulated in qemu): cd tools/testing/selftests/nci make ./nci_dev BUG: memory leak unreferenced object 0xffff888107588000 (size 208): comm "nci_dev", pid 206, jiffies 4294945376 (age 368.248s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<000000008d94c8fd>] __alloc_skb+0x1da/0x290 [<00000000278bc7f8>] nci_send_cmd+0xa3/0x350 [<0000000081256a22>] nci_reset_req+0x6b/0xa0 [<000000009e721112>] __nci_request+0x90/0x250 [<000000005d556e59>] nci_dev_up+0x217/0x5b0 [<00000000e618ce62>] nfc_dev_up+0x114/0x220 [<00000000981e226b>] nfc_genl_dev_up+0x94/0xe0 [<000000009bb03517>] genl_family_rcv_msg_doit.isra.14+0x228/0x2d0 [<00000000b7f8c101>] genl_rcv_msg+0x35c/0x640 [<00000000c94075ff>] netlink_rcv_skb+0x11e/0x350 [<00000000440cfb1e>] genl_rcv+0x24/0x40 [<0000000062593b40>] netlink_unicast+0x43f/0x640 [<000000001d0b13cc>] netlink_sendmsg+0x73a/0xbf0 [<000000003272487f>] __sys_sendto+0x324/0x370 [<00000000ef9f1747>] __x64_sys_sendto+0xdd/0x1b0 [<000000001e437841>] do_syscall_64+0x3f/0x90 Fixes: e624e6c3e777 ("nfc: Add a virtual nci device driver") Signed-off-by: Shang XiaoJing Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20221020030505.15572-1-shangxiaojing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/nfc/virtual_ncidev.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/nfc/virtual_ncidev.c b/drivers/nfc/virtual_ncidev.c index f577449e4935..85c06dbb2c44 100644 --- a/drivers/nfc/virtual_ncidev.c +++ b/drivers/nfc/virtual_ncidev.c @@ -54,16 +54,19 @@ static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb) mutex_lock(&nci_mutex); if (state != virtual_ncidev_enabled) { mutex_unlock(&nci_mutex); + kfree_skb(skb); return 0; } if (send_buff) { mutex_unlock(&nci_mutex); + kfree_skb(skb); return -1; } send_buff = skb_copy(skb, GFP_KERNEL); mutex_unlock(&nci_mutex); wake_up_interruptible(&wq); + consume_skb(skb); return 0; } -- cgit v1.2.3 From cc67482c9e5f2c80d62f623bcc347c29f9f648e1 Mon Sep 17 00:00:00 2001 From: Hyunwoo Kim Date: Thu, 20 Oct 2022 18:15:44 -0700 Subject: fbdev: smscufx: Fix several use-after-free bugs Several types of UAFs can occur when physically removing a USB device. Adds ufx_ops_destroy() function to .fb_destroy of fb_ops, and in this function, there is kref_put() that finally calls ufx_free(). This fix prevents multiple UAFs. Signed-off-by: Hyunwoo Kim Link: https://lore.kernel.org/linux-fbdev/20221011153436.GA4446@ubuntu/ Cc: Signed-off-by: Helge Deller --- drivers/video/fbdev/smscufx.c | 55 +++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c index e65bdc499c23..9343b7a4ac89 100644 --- a/drivers/video/fbdev/smscufx.c +++ b/drivers/video/fbdev/smscufx.c @@ -97,7 +97,6 @@ struct ufx_data { struct kref kref; int fb_count; bool virtualized; /* true when physical usb device not present */ - struct delayed_work free_framebuffer_work; atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ u8 *edid; /* null until we read edid from hw or get from sysfs */ @@ -1117,15 +1116,24 @@ static void ufx_free(struct kref *kref) { struct ufx_data *dev = container_of(kref, struct ufx_data, kref); - /* this function will wait for all in-flight urbs to complete */ - if (dev->urbs.count > 0) - ufx_free_urb_list(dev); + kfree(dev); +} - pr_debug("freeing ufx_data %p", dev); +static void ufx_ops_destory(struct fb_info *info) +{ + struct ufx_data *dev = info->par; + int node = info->node; - kfree(dev); + /* Assume info structure is freed after this point */ + framebuffer_release(info); + + pr_debug("fb_info for /dev/fb%d has been freed", node); + + /* release reference taken by kref_init in probe() */ + kref_put(&dev->kref, ufx_free); } + static void ufx_release_urb_work(struct work_struct *work) { struct urb_node *unode = container_of(work, struct urb_node, @@ -1134,14 +1142,9 @@ static void ufx_release_urb_work(struct work_struct *work) up(&unode->dev->urbs.limit_sem); } -static void ufx_free_framebuffer_work(struct work_struct *work) +static void ufx_free_framebuffer(struct ufx_data *dev) { - struct ufx_data *dev = container_of(work, struct ufx_data, - free_framebuffer_work.work); struct fb_info *info = dev->info; - int node = info->node; - - unregister_framebuffer(info); if (info->cmap.len != 0) fb_dealloc_cmap(&info->cmap); @@ -1153,11 +1156,6 @@ static void ufx_free_framebuffer_work(struct work_struct *work) dev->info = NULL; - /* Assume info structure is freed after this point */ - framebuffer_release(info); - - pr_debug("fb_info for /dev/fb%d has been freed", node); - /* ref taken in probe() as part of registering framebfufer */ kref_put(&dev->kref, ufx_free); } @@ -1169,11 +1167,13 @@ static int ufx_ops_release(struct fb_info *info, int user) { struct ufx_data *dev = info->par; + mutex_lock(&disconnect_mutex); + dev->fb_count--; /* We can't free fb_info here - fbmem will touch it when we return */ if (dev->virtualized && (dev->fb_count == 0)) - schedule_delayed_work(&dev->free_framebuffer_work, HZ); + ufx_free_framebuffer(dev); if ((dev->fb_count == 0) && (info->fbdefio)) { fb_deferred_io_cleanup(info); @@ -1186,6 +1186,8 @@ static int ufx_ops_release(struct fb_info *info, int user) kref_put(&dev->kref, ufx_free); + mutex_unlock(&disconnect_mutex); + return 0; } @@ -1292,6 +1294,7 @@ static const struct fb_ops ufx_ops = { .fb_blank = ufx_ops_blank, .fb_check_var = ufx_ops_check_var, .fb_set_par = ufx_ops_set_par, + .fb_destroy = ufx_ops_destory, }; /* Assumes &info->lock held by caller @@ -1673,9 +1676,6 @@ static int ufx_usb_probe(struct usb_interface *interface, goto destroy_modedb; } - INIT_DELAYED_WORK(&dev->free_framebuffer_work, - ufx_free_framebuffer_work); - retval = ufx_reg_read(dev, 0x3000, &id_rev); check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval); dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev); @@ -1748,10 +1748,12 @@ e_nomem: static void ufx_usb_disconnect(struct usb_interface *interface) { struct ufx_data *dev; + struct fb_info *info; mutex_lock(&disconnect_mutex); dev = usb_get_intfdata(interface); + info = dev->info; pr_debug("USB disconnect starting\n"); @@ -1765,12 +1767,15 @@ static void ufx_usb_disconnect(struct usb_interface *interface) /* if clients still have us open, will be freed on last close */ if (dev->fb_count == 0) - schedule_delayed_work(&dev->free_framebuffer_work, 0); + ufx_free_framebuffer(dev); - /* release reference taken by kref_init in probe() */ - kref_put(&dev->kref, ufx_free); + /* this function will wait for all in-flight urbs to complete */ + if (dev->urbs.count > 0) + ufx_free_urb_list(dev); - /* consider ufx_data freed */ + pr_debug("freeing ufx_data %p", dev); + + unregister_framebuffer(info); mutex_unlock(&disconnect_mutex); } -- cgit v1.2.3 From e8a18e3f00f3ee8d07c17ab1ea3ad4df4a3b6fe0 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 21 Oct 2022 07:44:49 +0200 Subject: parisc: Make 8250_gsc driver dependend on CONFIG_PARISC Although the name of the driver 8250_gsc.c suggests that it handles only serial ports on the GSC bus, it does handle serial ports listed in the parisc machine inventory as well, e.g. the serial ports in a C8000 PCI-only workstation. Change the dependency to CONFIG_PARISC, so that the driver gets included in the kernel even if CONFIG_GSC isn't set. Reported-by: Mikulas Patocka Cc: Signed-off-by: Helge Deller --- drivers/tty/serial/8250/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index d0b49e15fbf5..7b3ffb7f50ab 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -118,7 +118,7 @@ config SERIAL_8250_CONSOLE config SERIAL_8250_GSC tristate - depends on SERIAL_8250 && GSC + depends on SERIAL_8250 && PARISC default SERIAL_8250 config SERIAL_8250_DMA -- cgit v1.2.3 From 9e4e2ce1a78ed92ed91135e90c85f27d75388129 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 21 Oct 2022 08:02:31 +0200 Subject: parisc/serial: Rename 8250_gsc.c to 8250_parisc.c The file name of this driver is misleading - it handles various serial ports on parisc machines, not just such on the GSC bus. Rename the file to make this clearer. Suggested-by: Mikulas Patocka Signed-off-by: Helge Deller --- drivers/tty/serial/8250/8250_gsc.c | 130 ---------------------------------- drivers/tty/serial/8250/8250_parisc.c | 130 ++++++++++++++++++++++++++++++++++ drivers/tty/serial/8250/Kconfig | 2 +- drivers/tty/serial/8250/Makefile | 2 +- 4 files changed, 132 insertions(+), 132 deletions(-) delete mode 100644 drivers/tty/serial/8250/8250_gsc.c create mode 100644 drivers/tty/serial/8250/8250_parisc.c (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c deleted file mode 100644 index 948d0a1c6ae8..000000000000 --- a/drivers/tty/serial/8250/8250_gsc.c +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Serial Device Initialisation for Lasi/Asp/Wax/Dino - * - * (c) Copyright Matthew Wilcox 2001-2002 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "8250.h" - -static int __init serial_init_chip(struct parisc_device *dev) -{ - struct uart_8250_port uart; - unsigned long address; - int err; - -#if defined(CONFIG_64BIT) && defined(CONFIG_IOSAPIC) - if (!dev->irq && (dev->id.sversion == 0xad)) - dev->irq = iosapic_serial_irq(dev); -#endif - - if (!dev->irq) { - /* We find some unattached serial ports by walking native - * busses. These should be silently ignored. Otherwise, - * what we have here is a missing parent device, so tell - * the user what they're missing. - */ - if (parisc_parent(dev)->id.hw_type != HPHW_IOA) - dev_info(&dev->dev, - "Serial: device 0x%llx not configured.\n" - "Enable support for Wax, Lasi, Asp or Dino.\n", - (unsigned long long)dev->hpa.start); - return -ENODEV; - } - - address = dev->hpa.start; - if (dev->id.sversion != 0x8d) - address += 0x800; - - memset(&uart, 0, sizeof(uart)); - uart.port.iotype = UPIO_MEM; - /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */ - uart.port.uartclk = (dev->id.sversion != 0xad) ? - 7272727 : 1843200; - uart.port.mapbase = address; - uart.port.membase = ioremap(address, 16); - if (!uart.port.membase) { - dev_warn(&dev->dev, "Failed to map memory\n"); - return -ENOMEM; - } - uart.port.irq = dev->irq; - uart.port.flags = UPF_BOOT_AUTOCONF; - uart.port.dev = &dev->dev; - - err = serial8250_register_8250_port(&uart); - if (err < 0) { - dev_warn(&dev->dev, - "serial8250_register_8250_port returned error %d\n", - err); - iounmap(uart.port.membase); - return err; - } - - return 0; -} - -static const struct parisc_device_id serial_tbl[] __initconst = { - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 }, - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c }, - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d }, - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x000ad }, - { 0 } -}; - -/* Hack. Some machines have SERIAL_0 attached to Lasi and SERIAL_1 - * attached to Dino. Unfortunately, Dino appears before Lasi in the device - * tree. To ensure that ttyS0 == SERIAL_0, we register two drivers; one - * which only knows about Lasi and then a second which will find all the - * other serial ports. HPUX ignores this problem. - */ -static const struct parisc_device_id lasi_tbl[] __initconst = { - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */ - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */ - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */ - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */ - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */ - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */ - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */ - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */ - { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */ - { 0 } -}; - - -MODULE_DEVICE_TABLE(parisc, serial_tbl); - -static struct parisc_driver lasi_driver __refdata = { - .name = "serial_1", - .id_table = lasi_tbl, - .probe = serial_init_chip, -}; - -static struct parisc_driver serial_driver __refdata = { - .name = "serial", - .id_table = serial_tbl, - .probe = serial_init_chip, -}; - -static int __init probe_serial_gsc(void) -{ - register_parisc_driver(&lasi_driver); - register_parisc_driver(&serial_driver); - return 0; -} - -module_init(probe_serial_gsc); - -MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/8250_parisc.c b/drivers/tty/serial/8250/8250_parisc.c new file mode 100644 index 000000000000..948d0a1c6ae8 --- /dev/null +++ b/drivers/tty/serial/8250/8250_parisc.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Serial Device Initialisation for Lasi/Asp/Wax/Dino + * + * (c) Copyright Matthew Wilcox 2001-2002 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "8250.h" + +static int __init serial_init_chip(struct parisc_device *dev) +{ + struct uart_8250_port uart; + unsigned long address; + int err; + +#if defined(CONFIG_64BIT) && defined(CONFIG_IOSAPIC) + if (!dev->irq && (dev->id.sversion == 0xad)) + dev->irq = iosapic_serial_irq(dev); +#endif + + if (!dev->irq) { + /* We find some unattached serial ports by walking native + * busses. These should be silently ignored. Otherwise, + * what we have here is a missing parent device, so tell + * the user what they're missing. + */ + if (parisc_parent(dev)->id.hw_type != HPHW_IOA) + dev_info(&dev->dev, + "Serial: device 0x%llx not configured.\n" + "Enable support for Wax, Lasi, Asp or Dino.\n", + (unsigned long long)dev->hpa.start); + return -ENODEV; + } + + address = dev->hpa.start; + if (dev->id.sversion != 0x8d) + address += 0x800; + + memset(&uart, 0, sizeof(uart)); + uart.port.iotype = UPIO_MEM; + /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */ + uart.port.uartclk = (dev->id.sversion != 0xad) ? + 7272727 : 1843200; + uart.port.mapbase = address; + uart.port.membase = ioremap(address, 16); + if (!uart.port.membase) { + dev_warn(&dev->dev, "Failed to map memory\n"); + return -ENOMEM; + } + uart.port.irq = dev->irq; + uart.port.flags = UPF_BOOT_AUTOCONF; + uart.port.dev = &dev->dev; + + err = serial8250_register_8250_port(&uart); + if (err < 0) { + dev_warn(&dev->dev, + "serial8250_register_8250_port returned error %d\n", + err); + iounmap(uart.port.membase); + return err; + } + + return 0; +} + +static const struct parisc_device_id serial_tbl[] __initconst = { + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 }, + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c }, + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d }, + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x000ad }, + { 0 } +}; + +/* Hack. Some machines have SERIAL_0 attached to Lasi and SERIAL_1 + * attached to Dino. Unfortunately, Dino appears before Lasi in the device + * tree. To ensure that ttyS0 == SERIAL_0, we register two drivers; one + * which only knows about Lasi and then a second which will find all the + * other serial ports. HPUX ignores this problem. + */ +static const struct parisc_device_id lasi_tbl[] __initconst = { + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */ + { 0 } +}; + + +MODULE_DEVICE_TABLE(parisc, serial_tbl); + +static struct parisc_driver lasi_driver __refdata = { + .name = "serial_1", + .id_table = lasi_tbl, + .probe = serial_init_chip, +}; + +static struct parisc_driver serial_driver __refdata = { + .name = "serial", + .id_table = serial_tbl, + .probe = serial_init_chip, +}; + +static int __init probe_serial_gsc(void) +{ + register_parisc_driver(&lasi_driver); + register_parisc_driver(&serial_driver); + return 0; +} + +module_init(probe_serial_gsc); + +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 7b3ffb7f50ab..b0f62345bc84 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -116,7 +116,7 @@ config SERIAL_8250_CONSOLE If unsure, say N. -config SERIAL_8250_GSC +config SERIAL_8250_PARISC tristate depends on SERIAL_8250 && PARISC default SERIAL_8250 diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index bee908f99ea0..1615bfdde2a0 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o 8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o 8250_base-$(CONFIG_SERIAL_8250_DWLIB) += 8250_dwlib.o 8250_base-$(CONFIG_SERIAL_8250_FINTEK) += 8250_fintek.o -obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o +obj-$(CONFIG_SERIAL_8250_PARISC) += 8250_parisc.o obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o obj-$(CONFIG_SERIAL_8250_EXAR) += 8250_exar.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o -- cgit v1.2.3 From 66063033f77e10b985258126a97573f84bb8d3b4 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 19 Oct 2022 09:55:41 -0600 Subject: wifi: rt2x00: use explicitly signed or unsigned types On some platforms, `char` is unsigned, but this driver, for the most part, assumed it was signed. In other places, it uses `char` to mean an unsigned number, but only in cases when the values are small. And in still other places, `char` is used as a boolean. Put an end to this confusion by declaring explicit types, depending on the context. Cc: Andrew Morton Cc: Andy Shevchenko Cc: Stanislaw Gruszka Cc: Helmut Schaa Cc: Kalle Valo Signed-off-by: Jason A. Donenfeld Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20221019155541.3410813-1-Jason@zx2c4.com --- drivers/net/wireless/ralink/rt2x00/rt2400pci.c | 8 ++-- drivers/net/wireless/ralink/rt2x00/rt2400pci.h | 2 +- drivers/net/wireless/ralink/rt2x00/rt2500pci.c | 8 ++-- drivers/net/wireless/ralink/rt2x00/rt2500pci.h | 2 +- drivers/net/wireless/ralink/rt2x00/rt2500usb.c | 8 ++-- drivers/net/wireless/ralink/rt2x00/rt2500usb.h | 2 +- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 60 +++++++++++++------------- drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 8 ++-- drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 6 +-- drivers/net/wireless/ralink/rt2x00/rt61pci.c | 4 +- drivers/net/wireless/ralink/rt2x00/rt61pci.h | 2 +- drivers/net/wireless/ralink/rt2x00/rt73usb.c | 4 +- drivers/net/wireless/ralink/rt2x00/rt73usb.h | 2 +- 13 files changed, 58 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c index 273c5eac3362..ddfc16de1b26 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c @@ -1023,9 +1023,9 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, { u32 reg, reg2; unsigned int i; - char put_to_sleep; - char bbp_state; - char rf_state; + bool put_to_sleep; + u8 bbp_state; + u8 rf_state; put_to_sleep = (state != STATE_AWAKE); @@ -1561,7 +1561,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; - char *tx_power; + u8 *tx_power; unsigned int i; /* diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.h b/drivers/net/wireless/ralink/rt2x00/rt2400pci.h index b8187b6de143..979d5fd8babf 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.h @@ -939,7 +939,7 @@ #define DEFAULT_TXPOWER 39 #define __CLAMP_TX(__txpower) \ - clamp_t(char, (__txpower), MIN_TXPOWER, MAX_TXPOWER) + clamp_t(u8, (__txpower), MIN_TXPOWER, MAX_TXPOWER) #define TXPOWER_FROM_DEV(__txpower) \ ((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c index 8faa0a80e73a..cd6371e25062 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c @@ -1176,9 +1176,9 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, { u32 reg, reg2; unsigned int i; - char put_to_sleep; - char bbp_state; - char rf_state; + bool put_to_sleep; + u8 bbp_state; + u8 rf_state; put_to_sleep = (state != STATE_AWAKE); @@ -1856,7 +1856,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; - char *tx_power; + u8 *tx_power; unsigned int i; /* diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.h b/drivers/net/wireless/ralink/rt2x00/rt2500pci.h index 7e64aee2a172..ba362675c52c 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.h @@ -1219,6 +1219,6 @@ (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) #define TXPOWER_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER) + clamp_t(u8, __txpower, MIN_TXPOWER, MAX_TXPOWER) #endif /* RT2500PCI_H */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c index bb5ed6630645..4f3b0e6c6256 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c @@ -984,9 +984,9 @@ static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev, u16 reg; u16 reg2; unsigned int i; - char put_to_sleep; - char bbp_state; - char rf_state; + bool put_to_sleep; + u8 bbp_state; + u8 rf_state; put_to_sleep = (state != STATE_AWAKE); @@ -1663,7 +1663,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; - char *tx_power; + u8 *tx_power; unsigned int i; /* diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.h b/drivers/net/wireless/ralink/rt2x00/rt2500usb.h index 0c070288a140..746f0e950b76 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.h @@ -839,6 +839,6 @@ (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) #define TXPOWER_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER) + clamp_t(u8, __txpower, MIN_TXPOWER, MAX_TXPOWER) #endif /* RT2500USB_H */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index cbbb1a4849cf..12b700c7b9c3 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -3372,10 +3372,10 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { /* r55/r59 value array of channel 1~14 */ - static const char r55_bt_rev[] = {0x83, 0x83, + static const u8 r55_bt_rev[] = {0x83, 0x83, 0x83, 0x73, 0x73, 0x63, 0x53, 0x53, 0x53, 0x43, 0x43, 0x43, 0x43, 0x43}; - static const char r59_bt_rev[] = {0x0e, 0x0e, + static const u8 r59_bt_rev[] = {0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07}; @@ -3384,7 +3384,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 59, r59_bt_rev[idx]); } else { - static const char r59_bt[] = {0x8b, 0x8b, 0x8b, + static const u8 r59_bt[] = {0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89, 0x88, 0x88, 0x86, 0x85, 0x84}; @@ -3392,10 +3392,10 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, } } else { if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { - static const char r55_nonbt_rev[] = {0x23, 0x23, + static const u8 r55_nonbt_rev[] = {0x23, 0x23, 0x23, 0x23, 0x13, 0x13, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; - static const char r59_nonbt_rev[] = {0x07, 0x07, + static const u8 r59_nonbt_rev[] = {0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x05, 0x04, 0x04}; @@ -3406,14 +3406,14 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, } else if (rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392) || rt2x00_rt(rt2x00dev, RT6352)) { - static const char r59_non_bt[] = {0x8f, 0x8f, + static const u8 r59_non_bt[] = {0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86}; rt2800_rfcsr_write(rt2x00dev, 59, r59_non_bt[idx]); } else if (rt2x00_rt(rt2x00dev, RT5350)) { - static const char r59_non_bt[] = {0x0b, 0x0b, + static const u8 r59_non_bt[] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06}; @@ -4035,23 +4035,23 @@ static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel) rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); } -static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev, +static s8 rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev, unsigned int channel, - char txpower) + s8 txpower) { if (rt2x00_rt(rt2x00dev, RT3593) || rt2x00_rt(rt2x00dev, RT3883)) txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC); if (channel <= 14) - return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); + return clamp_t(s8, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); if (rt2x00_rt(rt2x00dev, RT3593) || rt2x00_rt(rt2x00dev, RT3883)) - return clamp_t(char, txpower, MIN_A_TXPOWER_3593, + return clamp_t(s8, txpower, MIN_A_TXPOWER_3593, MAX_A_TXPOWER_3593); else - return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); + return clamp_t(s8, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); } static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev, @@ -8530,7 +8530,7 @@ static void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev) u8 bytevalue = 0; int rcalcode; u8 r_cal_code = 0; - char d1 = 0, d2 = 0; + s8 d1 = 0, d2 = 0; u8 rfvalue; u32 MAC_RF_BYPASS0, MAC_RF_CONTROL0, MAC_PWR_PIN_CFG; u32 maccfg; @@ -8591,7 +8591,7 @@ static void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev) if (bytevalue > 128) d1 = bytevalue - 256; else - d1 = (char)bytevalue; + d1 = (s8)bytevalue; rt2800_bbp_write(rt2x00dev, 22, 0x0); rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x01); @@ -8601,7 +8601,7 @@ static void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev) if (bytevalue > 128) d2 = bytevalue - 256; else - d2 = (char)bytevalue; + d2 = (s8)bytevalue; rt2800_bbp_write(rt2x00dev, 22, 0x0); rcalcode = rt2800_calcrcalibrationcode(rt2x00dev, d1, d2); @@ -8703,7 +8703,7 @@ static void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev) static u32 rt2800_do_sqrt_accumulation(u32 si) { u32 root, root_pre, bit; - char i; + s8 i; bit = 1 << 15; root = 0; @@ -9330,11 +9330,11 @@ static void rt2800_loft_search(struct rt2x00_dev *rt2x00dev, u8 ch_idx, u8 alc_idx, u8 dc_result[][RF_ALC_NUM][2]) { u32 p0 = 0, p1 = 0, pf = 0; - char idx0 = 0, idx1 = 0; + s8 idx0 = 0, idx1 = 0; u8 idxf[] = {0x00, 0x00}; u8 ibit = 0x20; u8 iorq; - char bidx; + s8 bidx; rt2800_bbp_write(rt2x00dev, 158, 0xb0); rt2800_bbp_write(rt2x00dev, 159, 0x80); @@ -9384,17 +9384,17 @@ static void rt2800_loft_search(struct rt2x00_dev *rt2x00dev, u8 ch_idx, static void rt2800_iq_search(struct rt2x00_dev *rt2x00dev, u8 ch_idx, u8 *ges, u8 *pes) { u32 p0 = 0, p1 = 0, pf = 0; - char perr = 0, gerr = 0, iq_err = 0; - char pef = 0, gef = 0; - char psta, pend; - char gsta, gend; + s8 perr = 0, gerr = 0, iq_err = 0; + s8 pef = 0, gef = 0; + s8 psta, pend; + s8 gsta, gend; u8 ibit = 0x20; u8 first_search = 0x00, touch_neg_max = 0x00; - char idx0 = 0, idx1 = 0; + s8 idx0 = 0, idx1 = 0; u8 gop; u8 bbp = 0; - char bidx; + s8 bidx; for (bidx = 5; bidx >= 1; bidx--) { for (gop = 0; gop < 2; gop++) { @@ -10043,11 +10043,11 @@ static int rt2800_rf_lp_config(struct rt2x00_dev *rt2x00dev, bool btxcal) return 0; } -static char rt2800_lp_tx_filter_bw_cal(struct rt2x00_dev *rt2x00dev) +static s8 rt2800_lp_tx_filter_bw_cal(struct rt2x00_dev *rt2x00dev) { unsigned int cnt; u8 bbp_val; - char cal_val; + s8 cal_val; rt2800_bbp_dcoc_write(rt2x00dev, 0, 0x82); @@ -10079,7 +10079,7 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev, u8 rx_filter_target_20m = 0x27, rx_filter_target_40m = 0x31; int loop = 0, is_ht40, cnt; u8 bbp_val, rf_val; - char cal_r32_init, cal_r32_val, cal_diff; + s8 cal_r32_init, cal_r32_val, cal_diff; u8 saverfb5r00, saverfb5r01, saverfb5r03, saverfb5r04, saverfb5r05; u8 saverfb5r06, saverfb5r07; u8 saverfb5r08, saverfb5r17, saverfb5r18, saverfb5r19, saverfb5r20; @@ -11550,9 +11550,9 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; - char *default_power1; - char *default_power2; - char *default_power3; + s8 *default_power1; + s8 *default_power2; + s8 *default_power3; unsigned int i, tx_chains, rx_chains; u32 reg; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h index 3cbef77b4bd3..194de676df8f 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h @@ -32,10 +32,10 @@ struct rf_reg_pair { struct rt2800_drv_data { u8 calibration_bw20; u8 calibration_bw40; - char rx_calibration_bw20; - char rx_calibration_bw40; - char tx_calibration_bw20; - char tx_calibration_bw40; + s8 rx_calibration_bw20; + s8 rx_calibration_bw40; + s8 tx_calibration_bw20; + s8 tx_calibration_bw40; u8 bbp25; u8 bbp26; u8 txmixer_gain_24g; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c index 0827bc860bf8..8fd22c69855f 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c @@ -117,12 +117,12 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, const u16 buffer_length) { int status = 0; - unsigned char *tb; + u8 *tb; u16 off, len, bsize; mutex_lock(&rt2x00dev->csr_mutex); - tb = (char *)buffer; + tb = (u8 *)buffer; off = offset; len = buffer_length; while (len && !status) { @@ -215,7 +215,7 @@ void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, rd->cr.wLength = cpu_to_le16(sizeof(u32)); usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0), - (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg), + (u8 *)(&rd->cr), &rd->reg, sizeof(rd->reg), rt2x00usb_register_read_async_cb, rd); usb_anchor_urb(urb, rt2x00dev->anchor); if (usb_submit_urb(urb, GFP_ATOMIC) < 0) { diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c index d92f9eb07dc9..81db7f57c7e4 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c @@ -1709,7 +1709,7 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { u32 reg, reg2; unsigned int i; - char put_to_sleep; + bool put_to_sleep; put_to_sleep = (state != STATE_AWAKE); @@ -2656,7 +2656,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; - char *tx_power; + u8 *tx_power; unsigned int i; /* diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.h b/drivers/net/wireless/ralink/rt2x00/rt61pci.h index 5f208ad509bd..d72d0ffd1127 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.h +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.h @@ -1484,6 +1484,6 @@ struct hw_pairwise_ta_entry { (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) #define TXPOWER_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER) + clamp_t(u8, __txpower, MIN_TXPOWER, MAX_TXPOWER) #endif /* RT61PCI_H */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c index e3269fd7c59e..861035444374 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c @@ -1378,7 +1378,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { u32 reg, reg2; unsigned int i; - char put_to_sleep; + bool put_to_sleep; put_to_sleep = (state != STATE_AWAKE); @@ -2090,7 +2090,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; - char *tx_power; + u8 *tx_power; unsigned int i; /* diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.h b/drivers/net/wireless/ralink/rt2x00/rt73usb.h index 1b56d285c34b..bb0a68516c08 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt73usb.h +++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.h @@ -1063,6 +1063,6 @@ struct hw_pairwise_ta_entry { (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) #define TXPOWER_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER) + clamp_t(u8, __txpower, MIN_TXPOWER, MAX_TXPOWER) #endif /* RT73USB_H */ -- cgit v1.2.3 From 50f19697dd768d8b072cf7f12c0c99c7d31b67d8 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 21 Oct 2022 09:15:20 +0200 Subject: parisc: Use signed char for hardware path in pdc.h Clean up the struct for hardware_path and drop the struct device_path with a proper assignment of bc[] and mod members as signed chars. This patch prepares for the kbuild change from Jason A. Donenfeld to treat char as always unsigned. Signed-off-by: Helge Deller Cc: Jason A. Donenfeld --- drivers/parisc/pdc_stable.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index d9e51036a4fa..d6af5726ddf3 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -14,7 +14,7 @@ * all) PA-RISC machines should have them. Anyway, for safety reasons, the * following code can deal with just 96 bytes of Stable Storage, and all * sizes between 96 and 192 bytes (provided they are multiple of struct - * device_path size, eg: 128, 160 and 192) to provide full information. + * pdc_module_path size, eg: 128, 160 and 192) to provide full information. * One last word: there's one path we can always count on: the primary path. * Anything above 224 bytes is used for 'osdep2' OS-dependent storage area. * @@ -88,7 +88,7 @@ struct pdcspath_entry { short ready; /* entry record is valid if != 0 */ unsigned long addr; /* entry address in stable storage */ char *name; /* entry name */ - struct device_path devpath; /* device path in parisc representation */ + struct pdc_module_path devpath; /* device path in parisc representation */ struct device *dev; /* corresponding device */ struct kobject kobj; }; @@ -138,7 +138,7 @@ struct pdcspath_attribute paths_attr_##_name = { \ static int pdcspath_fetch(struct pdcspath_entry *entry) { - struct device_path *devpath; + struct pdc_module_path *devpath; if (!entry) return -EINVAL; @@ -153,7 +153,7 @@ pdcspath_fetch(struct pdcspath_entry *entry) return -EIO; /* Find the matching device. - NOTE: hardware_path overlays with device_path, so the nice cast can + NOTE: hardware_path overlays with pdc_module_path, so the nice cast can be used */ entry->dev = hwpath_to_device((struct hardware_path *)devpath); @@ -179,7 +179,7 @@ pdcspath_fetch(struct pdcspath_entry *entry) static void pdcspath_store(struct pdcspath_entry *entry) { - struct device_path *devpath; + struct pdc_module_path *devpath; BUG_ON(!entry); @@ -221,7 +221,7 @@ static ssize_t pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf) { char *out = buf; - struct device_path *devpath; + struct pdc_module_path *devpath; short i; if (!entry || !buf) @@ -236,11 +236,11 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf) return -ENODATA; for (i = 0; i < 6; i++) { - if (devpath->bc[i] >= 128) + if (devpath->path.bc[i] < 0) continue; - out += sprintf(out, "%u/", (unsigned char)devpath->bc[i]); + out += sprintf(out, "%d/", devpath->path.bc[i]); } - out += sprintf(out, "%u\n", (unsigned char)devpath->mod); + out += sprintf(out, "%u\n", (unsigned char)devpath->path.mod); return out - buf; } @@ -296,12 +296,12 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun for (i=5; ((temp = strrchr(in, '/'))) && (temp-in > 0) && (likely(i)); i--) { hwpath.bc[i] = simple_strtoul(temp+1, NULL, 10); in[temp-in] = '\0'; - DPRINTK("%s: bc[%d]: %d\n", __func__, i, hwpath.bc[i]); + DPRINTK("%s: bc[%d]: %d\n", __func__, i, hwpath.path.bc[i]); } /* Store the final field */ hwpath.bc[i] = simple_strtoul(in, NULL, 10); - DPRINTK("%s: bc[%d]: %d\n", __func__, i, hwpath.bc[i]); + DPRINTK("%s: bc[%d]: %d\n", __func__, i, hwpath.path.bc[i]); /* Now we check that the user isn't trying to lure us */ if (!(dev = hwpath_to_device((struct hardware_path *)&hwpath))) { @@ -342,7 +342,7 @@ static ssize_t pdcspath_layer_read(struct pdcspath_entry *entry, char *buf) { char *out = buf; - struct device_path *devpath; + struct pdc_module_path *devpath; short i; if (!entry || !buf) @@ -547,7 +547,7 @@ static ssize_t pdcs_auto_read(struct kobject *kobj, pathentry = &pdcspath_entry_primary; read_lock(&pathentry->rw_lock); - out += sprintf(out, "%s\n", (pathentry->devpath.flags & knob) ? + out += sprintf(out, "%s\n", (pathentry->devpath.path.flags & knob) ? "On" : "Off"); read_unlock(&pathentry->rw_lock); @@ -594,8 +594,8 @@ static ssize_t pdcs_timer_read(struct kobject *kobj, /* print the timer value in seconds */ read_lock(&pathentry->rw_lock); - out += sprintf(out, "%u\n", (pathentry->devpath.flags & PF_TIMER) ? - (1 << (pathentry->devpath.flags & PF_TIMER)) : 0); + out += sprintf(out, "%u\n", (pathentry->devpath.path.flags & PF_TIMER) ? + (1 << (pathentry->devpath.path.flags & PF_TIMER)) : 0); read_unlock(&pathentry->rw_lock); return out - buf; @@ -764,7 +764,7 @@ static ssize_t pdcs_auto_write(struct kobject *kobj, /* Be nice to the existing flag record */ read_lock(&pathentry->rw_lock); - flags = pathentry->devpath.flags; + flags = pathentry->devpath.path.flags; read_unlock(&pathentry->rw_lock); DPRINTK("%s: flags before: 0x%X\n", __func__, flags); @@ -785,7 +785,7 @@ static ssize_t pdcs_auto_write(struct kobject *kobj, write_lock(&pathentry->rw_lock); /* Change the path entry flags first */ - pathentry->devpath.flags = flags; + pathentry->devpath.path.flags = flags; /* Now, dive in. Write back to the hardware */ pdcspath_store(pathentry); -- cgit v1.2.3 From 69188df5f6e4cecc6b76b958979ba363cd5240e8 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Fri, 14 Oct 2022 16:54:39 +0200 Subject: wifi: mac80211_hwsim: fix debugfs attribute ps with rc table support Fixes a warning that occurs when rc table support is enabled (IEEE80211_HW_SUPPORTS_RC_TABLE) in mac80211_hwsim and the PS mode is changed via the exported debugfs attribute. When the PS mode is changed, a packet is broadcasted via hwsim_send_nullfunc by creating and transmitting a plain skb with only header initialized. The ieee80211 rate array in the control buffer is zero-initialized. When ratetbl support is enabled, ieee80211_get_tx_rates is called for the skb with sta parameter set to NULL and thus no ratetbl can be used. The final rate array then looks like [-1,0; 0,0; 0,0; 0,0] which causes the warning in ieee80211_get_tx_rate. The issue is fixed by setting the count of the first rate with idx '0' to 1 and hence ieee80211_get_tx_rates won't overwrite it with idx '-1'. Signed-off-by: Jonas Jelonek Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index a40636c90ec3..0d81098c7b45 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -910,6 +910,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, struct hwsim_vif_priv *vp = (void *)vif->drv_priv; struct sk_buff *skb; struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *cb; if (!vp->assoc) return; @@ -931,6 +932,10 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, memcpy(hdr->addr2, mac, ETH_ALEN); memcpy(hdr->addr3, vp->bssid, ETH_ALEN); + cb = IEEE80211_SKB_CB(skb); + cb->control.rates[0].count = 1; + cb->control.rates[1].idx = -1; + rcu_read_lock(); mac80211_hwsim_tx_frame(data->hw, skb, rcu_dereference(vif->bss_conf.chanctx_conf)->def.chan); -- cgit v1.2.3 From cb8e30ddb7e345867f6f2da8a08291d7d9e037db Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 17 Oct 2022 12:18:51 -0700 Subject: drm/bridge: ps8640: Add back the 50 ms mystery delay after HPD Back in commit 826cff3f7ebb ("drm/bridge: parade-ps8640: Enable runtime power management") we removed a mysterious 50 ms delay because "Parade's support [couldn't] explain what the delay [was] for". While I'm always a fan of removing mysterious delays, I suspect that we need this mysterious delay to avoid some problems. Specifically, what I found recently is that on sc7180-trogdor-homestar sometimes the AUX backlight wasn't initializing properly. Some debugging showed that the drm_dp_dpcd_read() function that the AUX backlight driver was calling was returning bogus data about 1% of the time when I booted up. This confused drm_panel_dp_aux_backlight(). From continued debugging: - If I retried the read then the read worked just fine. - If I added a loop to perform the same read that drm_panel_dp_aux_backlight() was doing 30 times at bootup I could see that some percentage of the time the first read would give bogus data but all 29 additional reads would always be fine. - If I added a large delay _after_ powering on the panel but before powering on PS8640 I could still reproduce the problem. - If I added a delay after PS8640 powered on then I couldn't reproduce the problem. - I couldn't reproduce the problem on a board with the same panel but the ti-sn65dsi86 bridge chip. To me, the above indicated that there was a problem with PS8640 and not the panel. I don't really have any insight into what's going on in the MCU, but my best guess is that when the MCU itself sees the HPD go high that it does some AUX transfers itself and this is confusing things. Let's go back and add back in the mysterious 50 ms delay. We only want to do this the first time we see HPD go high after booting the MCU, not every time we double-check HPD. With this, the backlight initializes reliably on homestar. Fixes: 826cff3f7ebb ("drm/bridge: parade-ps8640: Enable runtime power management") Reviewed-by: Stephen Boyd Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20221017121813.1.I59700c745fbc31559a5d5c8e2a960279c751dbd5@changeid --- drivers/gpu/drm/bridge/parade-ps8640.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index d7483c13c569..083337a27966 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -105,6 +105,7 @@ struct ps8640 { struct gpio_desc *gpio_powerdown; struct device_link *link; bool pre_enabled; + bool need_post_hpd_delay; }; static const struct regmap_config ps8640_regmap_config[] = { @@ -173,14 +174,31 @@ static int _ps8640_wait_hpd_asserted(struct ps8640 *ps_bridge, unsigned long wai { struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; int status; + int ret; /* * Apparently something about the firmware in the chip signals that * HPD goes high by reporting GPIO9 as high (even though HPD isn't * actually connected to GPIO9). */ - return regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, - status & PS_GPIO9, wait_us / 10, wait_us); + ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, + status & PS_GPIO9, wait_us / 10, wait_us); + + /* + * The first time we see HPD go high after a reset we delay an extra + * 50 ms. The best guess is that the MCU is doing "stuff" during this + * time (maybe talking to the panel) and we don't want to interrupt it. + * + * No locking is done around "need_post_hpd_delay". If we're here we + * know we're holding a PM Runtime reference and the only other place + * that touches this is PM Runtime resume. + */ + if (!ret && ps_bridge->need_post_hpd_delay) { + ps_bridge->need_post_hpd_delay = false; + msleep(50); + } + + return ret; } static int ps8640_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us) @@ -381,6 +399,9 @@ static int __maybe_unused ps8640_resume(struct device *dev) msleep(50); gpiod_set_value(ps_bridge->gpio_reset, 0); + /* We just reset things, so we need a delay after the first HPD */ + ps_bridge->need_post_hpd_delay = true; + /* * Mystery 200 ms delay for the "MCU to be ready". It's unclear if * this is truly necessary since the MCU will already signal that -- cgit v1.2.3 From 8a7a5b5f23377a1eb79b8cc47ba79d805767da47 Mon Sep 17 00:00:00 2001 From: Chengming Gui Date: Tue, 18 Oct 2022 17:31:38 +0800 Subject: drm/amdgpu: fix pstate setting issue [WHY] 0, original pstate X 1, ctx_A_create -> ctx_A->stable_pstate = X 2, ctx_A_set_pstate (Y) -> current pstate is Y (PEAK or STANDARD) 3, ctx_B_create -> ctx_B->stable_pstate = Y 4, ctx_A_destroy -> restore pstate to X 5, ctx_B_destroy -> restore pstate to Y Above sequence will cause final pstate is wrong (Y), should be original X. [HOW] When ctx_B create, if ctx_A touched pstate setting (not auto, stable_pstate_ctx != NULL), set ctx_B->stable_pstate the same value as ctx_A saved, if stable_pstate_ctx == NULL, fetch current pstate to fill ctx_B->stable_pstate. Signed-off-by: Chengming Gui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index f6d9d5da53cd..d2139ac12159 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -326,7 +326,10 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority, if (r) return r; - ctx->stable_pstate = current_stable_pstate; + if (mgr->adev->pm.stable_pstate_ctx) + ctx->stable_pstate = mgr->adev->pm.stable_pstate_ctx->stable_pstate; + else + ctx->stable_pstate = current_stable_pstate; return 0; } -- cgit v1.2.3 From 7e5632cdf68b2d2d53ab9d39daf6a545c2ac2045 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Wed, 19 Oct 2022 11:24:05 +0800 Subject: drm/amd/pm: update driver-if header for smu_v13_0_10 update driver-if header for smu_v13_0_10 and merge with smu_v13_0_0 Signed-off-by: Kenneth Feng Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- .../pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h | 111 +++++++++++++++------ drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 6 +- 3 files changed, 84 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h index 063f4a737605..b76f0f7e4299 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h @@ -25,7 +25,7 @@ #define SMU13_DRIVER_IF_V13_0_0_H //Increment this version if SkuTable_t or BoardTable_t change -#define PPTABLE_VERSION 0x24 +#define PPTABLE_VERSION 0x26 #define NUM_GFXCLK_DPM_LEVELS 16 #define NUM_SOCCLK_DPM_LEVELS 8 @@ -109,6 +109,22 @@ #define FEATURE_SPARE_63_BIT 63 #define NUM_FEATURES 64 +#define ALLOWED_FEATURE_CTRL_DEFAULT 0xFFFFFFFFFFFFFFFFULL +#define ALLOWED_FEATURE_CTRL_SCPM ((1 << FEATURE_DPM_GFXCLK_BIT) | \ + (1 << FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT) | \ + (1 << FEATURE_DPM_UCLK_BIT) | \ + (1 << FEATURE_DPM_FCLK_BIT) | \ + (1 << FEATURE_DPM_SOCCLK_BIT) | \ + (1 << FEATURE_DPM_MP0CLK_BIT) | \ + (1 << FEATURE_DPM_LINK_BIT) | \ + (1 << FEATURE_DPM_DCN_BIT) | \ + (1 << FEATURE_DS_GFXCLK_BIT) | \ + (1 << FEATURE_DS_SOCCLK_BIT) | \ + (1 << FEATURE_DS_FCLK_BIT) | \ + (1 << FEATURE_DS_LCLK_BIT) | \ + (1 << FEATURE_DS_DCFCLK_BIT) | \ + (1 << FEATURE_DS_UCLK_BIT)) + //For use with feature control messages typedef enum { FEATURE_PWR_ALL, @@ -133,6 +149,7 @@ typedef enum { #define DEBUG_OVERRIDE_DISABLE_DFLL 0x00000200 #define DEBUG_OVERRIDE_ENABLE_RLC_VF_BRINGUP_MODE 0x00000400 #define DEBUG_OVERRIDE_DFLL_MASTER_MODE 0x00000800 +#define DEBUG_OVERRIDE_ENABLE_PROFILING_MODE 0x00001000 // VR Mapping Bit Defines #define VR_MAPPING_VR_SELECT_MASK 0x01 @@ -262,15 +279,15 @@ typedef enum { } I2cControllerPort_e; typedef enum { - I2C_CONTROLLER_NAME_VR_GFX = 0, - I2C_CONTROLLER_NAME_VR_SOC, - I2C_CONTROLLER_NAME_VR_VMEMP, - I2C_CONTROLLER_NAME_VR_VDDIO, - I2C_CONTROLLER_NAME_LIQUID0, - I2C_CONTROLLER_NAME_LIQUID1, - I2C_CONTROLLER_NAME_PLX, - I2C_CONTROLLER_NAME_OTHER, - I2C_CONTROLLER_NAME_COUNT, + I2C_CONTROLLER_NAME_VR_GFX = 0, + I2C_CONTROLLER_NAME_VR_SOC, + I2C_CONTROLLER_NAME_VR_VMEMP, + I2C_CONTROLLER_NAME_VR_VDDIO, + I2C_CONTROLLER_NAME_LIQUID0, + I2C_CONTROLLER_NAME_LIQUID1, + I2C_CONTROLLER_NAME_PLX, + I2C_CONTROLLER_NAME_FAN_INTAKE, + I2C_CONTROLLER_NAME_COUNT, } I2cControllerName_e; typedef enum { @@ -282,16 +299,17 @@ typedef enum { I2C_CONTROLLER_THROTTLER_LIQUID0, I2C_CONTROLLER_THROTTLER_LIQUID1, I2C_CONTROLLER_THROTTLER_PLX, + I2C_CONTROLLER_THROTTLER_FAN_INTAKE, I2C_CONTROLLER_THROTTLER_INA3221, I2C_CONTROLLER_THROTTLER_COUNT, } I2cControllerThrottler_e; typedef enum { - I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, - I2C_CONTROLLER_PROTOCOL_VR_IR35217, - I2C_CONTROLLER_PROTOCOL_TMP_TMP102A, - I2C_CONTROLLER_PROTOCOL_INA3221, - I2C_CONTROLLER_PROTOCOL_COUNT, + I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, + I2C_CONTROLLER_PROTOCOL_VR_IR35217, + I2C_CONTROLLER_PROTOCOL_TMP_MAX31875, + I2C_CONTROLLER_PROTOCOL_INA3221, + I2C_CONTROLLER_PROTOCOL_COUNT, } I2cControllerProtocol_e; typedef struct { @@ -658,13 +676,20 @@ typedef struct { #define PP_NUM_OD_VF_CURVE_POINTS PP_NUM_RTAVFS_PWL_ZONES + 1 +typedef enum { + FAN_MODE_AUTO = 0, + FAN_MODE_MANUAL_LINEAR, +} FanMode_e; typedef struct { uint32_t FeatureCtrlMask; //Voltage control int16_t VoltageOffsetPerZoneBoundary[PP_NUM_OD_VF_CURVE_POINTS]; - uint16_t reserved[2]; + uint16_t VddGfxVmax; // in mV + + uint8_t IdlePwrSavingFeaturesCtrl; + uint8_t RuntimePwrSavingFeaturesCtrl; //Frequency changes int16_t GfxclkFmin; // MHz @@ -674,7 +699,7 @@ typedef struct { //PPT int16_t Ppt; // % - int16_t reserved1; + int16_t Tdc; //Fan control uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS]; @@ -701,16 +726,19 @@ typedef struct { uint32_t FeatureCtrlMask; int16_t VoltageOffsetPerZoneBoundary; - uint16_t reserved[2]; + uint16_t VddGfxVmax; // in mV + + uint8_t IdlePwrSavingFeaturesCtrl; + uint8_t RuntimePwrSavingFeaturesCtrl; - uint16_t GfxclkFmin; // MHz - uint16_t GfxclkFmax; // MHz + int16_t GfxclkFmin; // MHz + int16_t GfxclkFmax; // MHz uint16_t UclkFmin; // MHz uint16_t UclkFmax; // MHz //PPT int16_t Ppt; // % - int16_t reserved1; + int16_t Tdc; uint8_t FanLinearPwmPoints; uint8_t FanLinearTempPoints; @@ -857,7 +885,8 @@ typedef struct { uint16_t FanStartTempMin; uint16_t FanStartTempMax; - uint32_t Spare[12]; + uint16_t PowerMinPpt0[POWER_SOURCE_COUNT]; + uint32_t Spare[11]; } MsgLimits_t; @@ -1041,7 +1070,17 @@ typedef struct { uint32_t GfxoffSpare[15]; // GFX GPO - uint32_t GfxGpoSpare[16]; + uint32_t DfllBtcMasterScalerM; + int32_t DfllBtcMasterScalerB; + uint32_t DfllBtcSlaveScalerM; + int32_t DfllBtcSlaveScalerB; + + uint32_t DfllPccAsWaitCtrl; //GDFLL_AS_WAIT_CTRL_PCC register value to be passed to RLC msg + uint32_t DfllPccAsStepCtrl; //GDFLL_AS_STEP_CTRL_PCC register value to be passed to RLC msg + + uint32_t DfllL2FrequencyBoostM; //Unitless (float) + uint32_t DfllL2FrequencyBoostB; //In MHz (integer) + uint32_t GfxGpoSpare[8]; // GFX DCS @@ -1114,12 +1153,14 @@ typedef struct { uint16_t IntakeTempHighIntakeAcousticLimit; uint16_t IntakeTempAcouticLimitReleaseRate; - uint16_t FanStalledTempLimitOffset; + int16_t FanAbnormalTempLimitOffset; uint16_t FanStalledTriggerRpm; - uint16_t FanAbnormalTriggerRpm; - uint16_t FanPadding; + uint16_t FanAbnormalTriggerRpmCoeff; + uint16_t FanAbnormalDetectionEnable; - uint32_t FanSpare[14]; + uint8_t FanIntakeSensorSupport; + uint8_t FanIntakePadding[3]; + uint32_t FanSpare[13]; // SECTION: VDD_GFX AVFS @@ -1198,8 +1239,13 @@ typedef struct { int16_t TotalBoardPowerM; int16_t TotalBoardPowerB; + //PMFW-11158 + QuadraticInt_t qFeffCoeffGameClock[POWER_SOURCE_COUNT]; + QuadraticInt_t qFeffCoeffBaseClock[POWER_SOURCE_COUNT]; + QuadraticInt_t qFeffCoeffBoostClock[POWER_SOURCE_COUNT]; + // SECTION: Sku Reserved - uint32_t Spare[61]; + uint32_t Spare[43]; // Padding for MMHUB - do not modify this uint32_t MmHubPadding[8]; @@ -1288,8 +1334,11 @@ typedef struct { uint32_t PostVoltageSetBacoDelay; // in microseconds. Amount of time FW will wait after power good is established or PSI0 command is issued uint32_t BacoEntryDelay; // in milliseconds. Amount of time FW will wait to trigger BACO entry after receiving entry notification from OS + uint8_t FuseWritePowerMuxPresent; + uint8_t FuseWritePadding[3]; + // SECTION: Board Reserved - uint32_t BoardSpare[64]; + uint32_t BoardSpare[63]; // SECTION: Structure Padding @@ -1381,7 +1430,7 @@ typedef struct { uint16_t AverageTotalBoardPower; uint16_t AvgTemperature[TEMP_COUNT]; - uint16_t TempPadding; + uint16_t AvgTemperatureFanIntake; uint8_t PcieRate ; uint8_t PcieWidth ; @@ -1550,5 +1599,7 @@ typedef struct { #define IH_INTERRUPT_CONTEXT_ID_AUDIO_D0 0x5 #define IH_INTERRUPT_CONTEXT_ID_AUDIO_D3 0x6 #define IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING 0x7 +#define IH_INTERRUPT_CONTEXT_ID_FAN_ABNORMAL 0x8 +#define IH_INTERRUPT_CONTEXT_ID_FAN_RECOVERY 0x9 #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 8f72202aea8e..80fb583b18d9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -30,7 +30,7 @@ #define SMU13_DRIVER_IF_VERSION_ALDE 0x08 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x07 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04 -#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x30 +#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x2C #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_10 0x1D diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index c4552ade8d44..feb4d68f3fd9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -289,7 +289,8 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_ALDE; break; case IP_VERSION(13, 0, 0): - smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0; + case IP_VERSION(13, 0, 10): + smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10; break; case IP_VERSION(13, 0, 7): smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_7; @@ -305,9 +306,6 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) case IP_VERSION(13, 0, 5): smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_5; break; - case IP_VERSION(13, 0, 10): - smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_10; - break; default: dev_err(adev->dev, "smu unsupported IP version: 0x%x.\n", adev->ip_versions[MP1_HWIP][0]); -- cgit v1.2.3 From bb3c846ad26e1c8551f68078278cbd437a20fb64 Mon Sep 17 00:00:00 2001 From: Yiqing Yao Date: Tue, 18 Oct 2022 15:17:59 +0800 Subject: drm/amdgpu: Adjust MES polling timeout for sriov [why] MES response time in sriov may be longer than default value due to reset or init in other VF. A timeout value specific to sriov is needed. [how] When in sriov, adjust the timeout value to calculated worst case scenario. Signed-off-by: Yiqing Yao Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index fef7d020bc5f..f141fadd2d86 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -98,7 +98,14 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, struct amdgpu_device *adev = mes->adev; struct amdgpu_ring *ring = &mes->ring; unsigned long flags; + signed long timeout = adev->usec_timeout; + if (amdgpu_emu_mode) { + timeout *= 100; + } else if (amdgpu_sriov_vf(adev)) { + /* Worst case in sriov where all other 15 VF timeout, each VF needs about 600ms */ + timeout = 15 * 600 * 1000; + } BUG_ON(size % 4 != 0); spin_lock_irqsave(&mes->ring_lock, flags); @@ -118,7 +125,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, DRM_DEBUG("MES msg=%d was emitted\n", x_pkt->header.opcode); r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, - adev->usec_timeout * (amdgpu_emu_mode ? 100 : 1)); + timeout); if (r < 1) { DRM_ERROR("MES failed to response msg=%d\n", x_pkt->header.opcode); -- cgit v1.2.3 From 79610d3041338dc1ef554d6fd8b3b3e23be527f5 Mon Sep 17 00:00:00 2001 From: Chengming Gui Date: Tue, 18 Oct 2022 17:31:38 +0800 Subject: drm/amdgpu: fix pstate setting issue [WHY] 0, original pstate X 1, ctx_A_create -> ctx_A->stable_pstate = X 2, ctx_A_set_pstate (Y) -> current pstate is Y (PEAK or STANDARD) 3, ctx_B_create -> ctx_B->stable_pstate = Y 4, ctx_A_destroy -> restore pstate to X 5, ctx_B_destroy -> restore pstate to Y Above sequence will cause final pstate is wrong (Y), should be original X. [HOW] When ctx_B create, if ctx_A touched pstate setting (not auto, stable_pstate_ctx != NULL), set ctx_B->stable_pstate the same value as ctx_A saved, if stable_pstate_ctx == NULL, fetch current pstate to fill ctx_B->stable_pstate. Signed-off-by: Chengming Gui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index f6d9d5da53cd..d2139ac12159 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -326,7 +326,10 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority, if (r) return r; - ctx->stable_pstate = current_stable_pstate; + if (mgr->adev->pm.stable_pstate_ctx) + ctx->stable_pstate = mgr->adev->pm.stable_pstate_ctx->stable_pstate; + else + ctx->stable_pstate = current_stable_pstate; return 0; } -- cgit v1.2.3 From 09aef0258a327409bb2279a5ba8f82ad2ca099ca Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Wed, 19 Oct 2022 11:24:05 +0800 Subject: drm/amd/pm: update driver-if header for smu_v13_0_10 update driver-if header for smu_v13_0_10 and merge with smu_v13_0_0 Signed-off-by: Kenneth Feng Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- .../pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h | 111 +++++++++++++++------ drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 6 +- 3 files changed, 84 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h index 063f4a737605..b76f0f7e4299 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h @@ -25,7 +25,7 @@ #define SMU13_DRIVER_IF_V13_0_0_H //Increment this version if SkuTable_t or BoardTable_t change -#define PPTABLE_VERSION 0x24 +#define PPTABLE_VERSION 0x26 #define NUM_GFXCLK_DPM_LEVELS 16 #define NUM_SOCCLK_DPM_LEVELS 8 @@ -109,6 +109,22 @@ #define FEATURE_SPARE_63_BIT 63 #define NUM_FEATURES 64 +#define ALLOWED_FEATURE_CTRL_DEFAULT 0xFFFFFFFFFFFFFFFFULL +#define ALLOWED_FEATURE_CTRL_SCPM ((1 << FEATURE_DPM_GFXCLK_BIT) | \ + (1 << FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT) | \ + (1 << FEATURE_DPM_UCLK_BIT) | \ + (1 << FEATURE_DPM_FCLK_BIT) | \ + (1 << FEATURE_DPM_SOCCLK_BIT) | \ + (1 << FEATURE_DPM_MP0CLK_BIT) | \ + (1 << FEATURE_DPM_LINK_BIT) | \ + (1 << FEATURE_DPM_DCN_BIT) | \ + (1 << FEATURE_DS_GFXCLK_BIT) | \ + (1 << FEATURE_DS_SOCCLK_BIT) | \ + (1 << FEATURE_DS_FCLK_BIT) | \ + (1 << FEATURE_DS_LCLK_BIT) | \ + (1 << FEATURE_DS_DCFCLK_BIT) | \ + (1 << FEATURE_DS_UCLK_BIT)) + //For use with feature control messages typedef enum { FEATURE_PWR_ALL, @@ -133,6 +149,7 @@ typedef enum { #define DEBUG_OVERRIDE_DISABLE_DFLL 0x00000200 #define DEBUG_OVERRIDE_ENABLE_RLC_VF_BRINGUP_MODE 0x00000400 #define DEBUG_OVERRIDE_DFLL_MASTER_MODE 0x00000800 +#define DEBUG_OVERRIDE_ENABLE_PROFILING_MODE 0x00001000 // VR Mapping Bit Defines #define VR_MAPPING_VR_SELECT_MASK 0x01 @@ -262,15 +279,15 @@ typedef enum { } I2cControllerPort_e; typedef enum { - I2C_CONTROLLER_NAME_VR_GFX = 0, - I2C_CONTROLLER_NAME_VR_SOC, - I2C_CONTROLLER_NAME_VR_VMEMP, - I2C_CONTROLLER_NAME_VR_VDDIO, - I2C_CONTROLLER_NAME_LIQUID0, - I2C_CONTROLLER_NAME_LIQUID1, - I2C_CONTROLLER_NAME_PLX, - I2C_CONTROLLER_NAME_OTHER, - I2C_CONTROLLER_NAME_COUNT, + I2C_CONTROLLER_NAME_VR_GFX = 0, + I2C_CONTROLLER_NAME_VR_SOC, + I2C_CONTROLLER_NAME_VR_VMEMP, + I2C_CONTROLLER_NAME_VR_VDDIO, + I2C_CONTROLLER_NAME_LIQUID0, + I2C_CONTROLLER_NAME_LIQUID1, + I2C_CONTROLLER_NAME_PLX, + I2C_CONTROLLER_NAME_FAN_INTAKE, + I2C_CONTROLLER_NAME_COUNT, } I2cControllerName_e; typedef enum { @@ -282,16 +299,17 @@ typedef enum { I2C_CONTROLLER_THROTTLER_LIQUID0, I2C_CONTROLLER_THROTTLER_LIQUID1, I2C_CONTROLLER_THROTTLER_PLX, + I2C_CONTROLLER_THROTTLER_FAN_INTAKE, I2C_CONTROLLER_THROTTLER_INA3221, I2C_CONTROLLER_THROTTLER_COUNT, } I2cControllerThrottler_e; typedef enum { - I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, - I2C_CONTROLLER_PROTOCOL_VR_IR35217, - I2C_CONTROLLER_PROTOCOL_TMP_TMP102A, - I2C_CONTROLLER_PROTOCOL_INA3221, - I2C_CONTROLLER_PROTOCOL_COUNT, + I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, + I2C_CONTROLLER_PROTOCOL_VR_IR35217, + I2C_CONTROLLER_PROTOCOL_TMP_MAX31875, + I2C_CONTROLLER_PROTOCOL_INA3221, + I2C_CONTROLLER_PROTOCOL_COUNT, } I2cControllerProtocol_e; typedef struct { @@ -658,13 +676,20 @@ typedef struct { #define PP_NUM_OD_VF_CURVE_POINTS PP_NUM_RTAVFS_PWL_ZONES + 1 +typedef enum { + FAN_MODE_AUTO = 0, + FAN_MODE_MANUAL_LINEAR, +} FanMode_e; typedef struct { uint32_t FeatureCtrlMask; //Voltage control int16_t VoltageOffsetPerZoneBoundary[PP_NUM_OD_VF_CURVE_POINTS]; - uint16_t reserved[2]; + uint16_t VddGfxVmax; // in mV + + uint8_t IdlePwrSavingFeaturesCtrl; + uint8_t RuntimePwrSavingFeaturesCtrl; //Frequency changes int16_t GfxclkFmin; // MHz @@ -674,7 +699,7 @@ typedef struct { //PPT int16_t Ppt; // % - int16_t reserved1; + int16_t Tdc; //Fan control uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS]; @@ -701,16 +726,19 @@ typedef struct { uint32_t FeatureCtrlMask; int16_t VoltageOffsetPerZoneBoundary; - uint16_t reserved[2]; + uint16_t VddGfxVmax; // in mV + + uint8_t IdlePwrSavingFeaturesCtrl; + uint8_t RuntimePwrSavingFeaturesCtrl; - uint16_t GfxclkFmin; // MHz - uint16_t GfxclkFmax; // MHz + int16_t GfxclkFmin; // MHz + int16_t GfxclkFmax; // MHz uint16_t UclkFmin; // MHz uint16_t UclkFmax; // MHz //PPT int16_t Ppt; // % - int16_t reserved1; + int16_t Tdc; uint8_t FanLinearPwmPoints; uint8_t FanLinearTempPoints; @@ -857,7 +885,8 @@ typedef struct { uint16_t FanStartTempMin; uint16_t FanStartTempMax; - uint32_t Spare[12]; + uint16_t PowerMinPpt0[POWER_SOURCE_COUNT]; + uint32_t Spare[11]; } MsgLimits_t; @@ -1041,7 +1070,17 @@ typedef struct { uint32_t GfxoffSpare[15]; // GFX GPO - uint32_t GfxGpoSpare[16]; + uint32_t DfllBtcMasterScalerM; + int32_t DfllBtcMasterScalerB; + uint32_t DfllBtcSlaveScalerM; + int32_t DfllBtcSlaveScalerB; + + uint32_t DfllPccAsWaitCtrl; //GDFLL_AS_WAIT_CTRL_PCC register value to be passed to RLC msg + uint32_t DfllPccAsStepCtrl; //GDFLL_AS_STEP_CTRL_PCC register value to be passed to RLC msg + + uint32_t DfllL2FrequencyBoostM; //Unitless (float) + uint32_t DfllL2FrequencyBoostB; //In MHz (integer) + uint32_t GfxGpoSpare[8]; // GFX DCS @@ -1114,12 +1153,14 @@ typedef struct { uint16_t IntakeTempHighIntakeAcousticLimit; uint16_t IntakeTempAcouticLimitReleaseRate; - uint16_t FanStalledTempLimitOffset; + int16_t FanAbnormalTempLimitOffset; uint16_t FanStalledTriggerRpm; - uint16_t FanAbnormalTriggerRpm; - uint16_t FanPadding; + uint16_t FanAbnormalTriggerRpmCoeff; + uint16_t FanAbnormalDetectionEnable; - uint32_t FanSpare[14]; + uint8_t FanIntakeSensorSupport; + uint8_t FanIntakePadding[3]; + uint32_t FanSpare[13]; // SECTION: VDD_GFX AVFS @@ -1198,8 +1239,13 @@ typedef struct { int16_t TotalBoardPowerM; int16_t TotalBoardPowerB; + //PMFW-11158 + QuadraticInt_t qFeffCoeffGameClock[POWER_SOURCE_COUNT]; + QuadraticInt_t qFeffCoeffBaseClock[POWER_SOURCE_COUNT]; + QuadraticInt_t qFeffCoeffBoostClock[POWER_SOURCE_COUNT]; + // SECTION: Sku Reserved - uint32_t Spare[61]; + uint32_t Spare[43]; // Padding for MMHUB - do not modify this uint32_t MmHubPadding[8]; @@ -1288,8 +1334,11 @@ typedef struct { uint32_t PostVoltageSetBacoDelay; // in microseconds. Amount of time FW will wait after power good is established or PSI0 command is issued uint32_t BacoEntryDelay; // in milliseconds. Amount of time FW will wait to trigger BACO entry after receiving entry notification from OS + uint8_t FuseWritePowerMuxPresent; + uint8_t FuseWritePadding[3]; + // SECTION: Board Reserved - uint32_t BoardSpare[64]; + uint32_t BoardSpare[63]; // SECTION: Structure Padding @@ -1381,7 +1430,7 @@ typedef struct { uint16_t AverageTotalBoardPower; uint16_t AvgTemperature[TEMP_COUNT]; - uint16_t TempPadding; + uint16_t AvgTemperatureFanIntake; uint8_t PcieRate ; uint8_t PcieWidth ; @@ -1550,5 +1599,7 @@ typedef struct { #define IH_INTERRUPT_CONTEXT_ID_AUDIO_D0 0x5 #define IH_INTERRUPT_CONTEXT_ID_AUDIO_D3 0x6 #define IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING 0x7 +#define IH_INTERRUPT_CONTEXT_ID_FAN_ABNORMAL 0x8 +#define IH_INTERRUPT_CONTEXT_ID_FAN_RECOVERY 0x9 #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 8f72202aea8e..80fb583b18d9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -30,7 +30,7 @@ #define SMU13_DRIVER_IF_VERSION_ALDE 0x08 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x07 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04 -#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x30 +#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x2C #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_10 0x1D diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index c4552ade8d44..feb4d68f3fd9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -289,7 +289,8 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_ALDE; break; case IP_VERSION(13, 0, 0): - smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0; + case IP_VERSION(13, 0, 10): + smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10; break; case IP_VERSION(13, 0, 7): smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_7; @@ -305,9 +306,6 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) case IP_VERSION(13, 0, 5): smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_5; break; - case IP_VERSION(13, 0, 10): - smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_10; - break; default: dev_err(adev->dev, "smu unsupported IP version: 0x%x.\n", adev->ip_versions[MP1_HWIP][0]); -- cgit v1.2.3 From 226dcfad349f23f7744d02b24f8ec3bc4f6198ac Mon Sep 17 00:00:00 2001 From: Yiqing Yao Date: Tue, 18 Oct 2022 15:17:59 +0800 Subject: drm/amdgpu: Adjust MES polling timeout for sriov [why] MES response time in sriov may be longer than default value due to reset or init in other VF. A timeout value specific to sriov is needed. [how] When in sriov, adjust the timeout value to calculated worst case scenario. Signed-off-by: Yiqing Yao Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index fef7d020bc5f..f141fadd2d86 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -98,7 +98,14 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, struct amdgpu_device *adev = mes->adev; struct amdgpu_ring *ring = &mes->ring; unsigned long flags; + signed long timeout = adev->usec_timeout; + if (amdgpu_emu_mode) { + timeout *= 100; + } else if (amdgpu_sriov_vf(adev)) { + /* Worst case in sriov where all other 15 VF timeout, each VF needs about 600ms */ + timeout = 15 * 600 * 1000; + } BUG_ON(size % 4 != 0); spin_lock_irqsave(&mes->ring_lock, flags); @@ -118,7 +125,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, DRM_DEBUG("MES msg=%d was emitted\n", x_pkt->header.opcode); r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, - adev->usec_timeout * (amdgpu_emu_mode ? 100 : 1)); + timeout); if (r < 1) { DRM_ERROR("MES failed to response msg=%d\n", x_pkt->header.opcode); -- cgit v1.2.3 From 24f0692bfd41fd207d99c993a5785c3426762046 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 20 Oct 2022 16:54:55 -0700 Subject: ACPI: NUMA: Add CXL CFMWS 'nodes' to the possible nodes set The ACPI CEDT.CFMWS indicates a range of possible address where new CXL regions can appear. Each range is associated with a QTG id (QoS Throttling Group id). For each range + QTG pair that is not covered by a proximity domain in the SRAT, Linux creates a new NUMA node. However, the commit that added the new ranges missed updating the node_possible mask which causes memory_group_register() to fail. Add the new nodes to the nodes_possible mask. Cc: Fixes: fd49f99c1809 ("ACPI: NUMA: Add a node and memblk for each CFMWS not in SRAT") Cc: Alison Schofield Cc: Rafael J. Wysocki Reported-by: Vishal Verma Tested-by: Vishal Verma Acked-by: Rafael J. Wysocki Reviewed-by: Vishal Verma Link: https://lore.kernel.org/r/166631003537.1167078.9373680312035292395.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams --- drivers/acpi/numa/srat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index 3b818ab186be..1f4fc5f8a819 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -327,6 +327,7 @@ static int __init acpi_parse_cfmws(union acpi_subtable_headers *header, pr_warn("ACPI NUMA: Failed to add memblk for CFMWS node %d [mem %#llx-%#llx]\n", node, start, end); } + node_set(node, numa_nodes_parsed); /* Set the next available fake_pxm value */ (*fake_pxm)++; -- cgit v1.2.3 From 48ee7952808183201b0601d85b89d2d8ccca95ff Mon Sep 17 00:00:00 2001 From: Dukhyun Kwon Date: Tue, 18 Oct 2022 16:30:03 +0900 Subject: scsi: ufs: core: Fix the error log in ufshcd_query_flag_retry() In ufshcd_query_flag_retry() failed log is incorrectly output as "ufs attibute". Signed-off-by: Dukhyun Kwon Link: https://lore.kernel.org/r/1891546521.01666080182092.JavaMail.epsvc@epcpadp4 Reviewed-by: Bean Huo Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 7256e6c43ca6..54ba80cc71bc 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -3098,7 +3098,7 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba, if (ret) dev_err(hba->dev, - "%s: query attribute, opcode %d, idn %d, failed with error %d after %d retries\n", + "%s: query flag, opcode %d, idn %d, failed with error %d after %d retries\n", __func__, opcode, idn, ret, retries); return ret; } -- cgit v1.2.3 From 181dfce9b63b80adbb861b219550ec9b27fe63d5 Mon Sep 17 00:00:00 2001 From: Igor Pylypiv Date: Fri, 7 Oct 2022 16:06:51 -0700 Subject: scsi: pm80xx: Display proc_name in sysfs The proc_name entry in sysfs for pm80xx is "(null)" because it is not initialized in scsi_host_template: Before: host:~# cat /sys/class/scsi_host/host6/proc_name (null) After: host:~# cat /sys/class/scsi_host/host6/proc_name pm80xx Signed-off-by: Igor Pylypiv Link: https://lore.kernel.org/r/20221007230651.308969-1-ipylypiv@google.com Reviewed-by: Jolly Shah Acked-by: Jack Wang Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 2ff2fac1e403..7a7d63aa90e2 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -99,6 +99,7 @@ static void pm8001_map_queues(struct Scsi_Host *shost) static struct scsi_host_template pm8001_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .proc_name = DRV_NAME, .queuecommand = sas_queuecommand, .dma_need_drain = ata_scsi_dma_need_drain, .target_alloc = sas_target_alloc, -- cgit v1.2.3 From 4652b58fe3bb177a9b208bb7a8b7a3fb64184a00 Mon Sep 17 00:00:00 2001 From: Keoseong Park Date: Mon, 17 Oct 2022 18:58:15 +0900 Subject: scsi: ufs: core: Fix typo for register name in comments Change "UTRMLCLR" to "UTMRLCLR". The meaning is "UTP Task Management Request List CLear Register" Signed-off-by: Keoseong Park Link: https://lore.kernel.org/r/20221017095815epcms2p110e3421b99bb9a937620b4d065d0ed12@epcms2p1 Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 54ba80cc71bc..b1f59a5fe632 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -772,7 +772,7 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 mask) } /** - * ufshcd_utmrl_clear - Clear a bit in UTRMLCLR register + * ufshcd_utmrl_clear - Clear a bit in UTMRLCLR register * @hba: per adapter instance * @pos: position of the bit to be cleared */ -- cgit v1.2.3 From 65244389b1b347447a7eed866d9d458963e851e8 Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Mon, 17 Oct 2022 16:55:17 +0200 Subject: scsi: mpi3mr: Select CONFIG_SCSI_SAS_ATTRS Starting with commit 42fc9fee116f ("scsi: mpi3mr: Add helper functions to manage device's port"), kernel configured with CONFIG_SCSI_MPI3MR=m and CONFIG_SCSI_SAS_ATTRS=n fails to build because modpost cannot find symbols used in mpi3mr_transport.c: ERROR: modpost: "sas_port_alloc_num" [drivers/scsi/mpi3mr/mpi3mr.ko] undefined! ERROR: modpost: "sas_remove_host" [drivers/scsi/mpi3mr/mpi3mr.ko] undefined! ERROR: modpost: "sas_phy_alloc" [drivers/scsi/mpi3mr/mpi3mr.ko] undefined! ERROR: modpost: "sas_phy_free" [drivers/scsi/mpi3mr/mpi3mr.ko] undefined! ... Select CONFIG_SCSI_SAS_ATTRS when CONFIG_SCSI_MPI3MR is enabled to prevent inconsistent configs. Link: https://lore.kernel.org/r/20221017145517.93BCB6043B@lion.mk-sys.cz Fixes: 42fc9fee116f ("scsi: mpi3mr: Add helper functions to manage device's port") Acked-by: Sathya Prakash Veerichetty Signed-off-by: Michal Kubecek Signed-off-by: Martin K. Petersen --- drivers/scsi/mpi3mr/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/mpi3mr/Kconfig b/drivers/scsi/mpi3mr/Kconfig index 8997531940c2..f48740cd5b95 100644 --- a/drivers/scsi/mpi3mr/Kconfig +++ b/drivers/scsi/mpi3mr/Kconfig @@ -4,5 +4,6 @@ config SCSI_MPI3MR tristate "Broadcom MPI3 Storage Controller Device Driver" depends on PCI && SCSI select BLK_DEV_BSGLIB + select SCSI_SAS_ATTRS help MPI3 based Storage & RAID Controllers Driver. -- cgit v1.2.3 From 307539eed46395d27e0ecc0ae4d9d6e99eb15fcd Mon Sep 17 00:00:00 2001 From: Keoseong Park Date: Wed, 19 Oct 2022 12:45:30 +0900 Subject: scsi: ufs: core: Fix typo in comment Change "drity" to "dirty". Signed-off-by: Keoseong Park Link: https://lore.kernel.org/r/20221019034530epcms2p2b10e072bb66b3fd6cdbe0e2423c11735@epcms2p2 Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshpb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ufs/core/ufshpb.c b/drivers/ufs/core/ufshpb.c index 7d56c9b4f7a8..b7f412d0f301 100644 --- a/drivers/ufs/core/ufshpb.c +++ b/drivers/ufs/core/ufshpb.c @@ -383,7 +383,7 @@ int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) rgn = hpb->rgn_tbl + rgn_idx; srgn = rgn->srgn_tbl + srgn_idx; - /* If command type is WRITE or DISCARD, set bitmap as drity */ + /* If command type is WRITE or DISCARD, set bitmap as dirty */ if (ufshpb_is_write_or_discard(cmd)) { ufshpb_iterate_rgn(hpb, rgn_idx, srgn_idx, srgn_offset, transfer_len, true); -- cgit v1.2.3 From f97fc7ef414603189d5ba6f529407c5341c03c2a Mon Sep 17 00:00:00 2001 From: Raju Rangoju Date: Thu, 20 Oct 2022 12:12:11 +0530 Subject: amd-xgbe: Yellow carp devices do not need rrc Link stability issues are noticed on Yellow carp platforms when Receiver Reset Cycle is issued. Since the CDR workaround is disabled on these platforms, the Receiver Reset Cycle is not needed. So, avoid issuing rrc on Yellow carp platforms. Fixes: dbb6c58b5a61 ("net: amd-xgbe: Add Support for Yellow Carp Ethernet device") Signed-off-by: Raju Rangoju Acked-by: Tom Lendacky Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 5 +++++ drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c index 2af3da4b2d05..f409d7bd1f1e 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c @@ -285,6 +285,9 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Yellow Carp devices do not need cdr workaround */ pdata->vdata->an_cdr_workaround = 0; + + /* Yellow Carp devices do not need rrc */ + pdata->vdata->enable_rrc = 0; } else { pdata->xpcs_window_def_reg = PCS_V2_WINDOW_DEF; pdata->xpcs_window_sel_reg = PCS_V2_WINDOW_SELECT; @@ -483,6 +486,7 @@ static struct xgbe_version_data xgbe_v2a = { .tx_desc_prefetch = 5, .rx_desc_prefetch = 5, .an_cdr_workaround = 1, + .enable_rrc = 1, }; static struct xgbe_version_data xgbe_v2b = { @@ -498,6 +502,7 @@ static struct xgbe_version_data xgbe_v2b = { .tx_desc_prefetch = 5, .rx_desc_prefetch = 5, .an_cdr_workaround = 1, + .enable_rrc = 1, }; static const struct pci_device_id xgbe_pci_table[] = { diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 2156600641b6..19b943eba560 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -2640,7 +2640,7 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) } /* No link, attempt a receiver reset cycle */ - if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) { + if (pdata->vdata->enable_rrc && phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) { phy_data->rrc_count = 0; xgbe_phy_rrc(pdata); } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index b875c430222e..49d23abce73d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -1013,6 +1013,7 @@ struct xgbe_version_data { unsigned int tx_desc_prefetch; unsigned int rx_desc_prefetch; unsigned int an_cdr_workaround; + unsigned int enable_rrc; }; struct xgbe_prv_data { -- cgit v1.2.3 From 1246d0862349f36b65db1043d27c466af930047d Mon Sep 17 00:00:00 2001 From: Raju Rangoju Date: Thu, 20 Oct 2022 12:12:12 +0530 Subject: amd-xgbe: use enums for mailbox cmd and sub_cmds Instead of using hardcoded values, use enumerations for mailbox command and sub commands. Signed-off-by: Raju Rangoju Acked-by: Tom Lendacky Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 29 ++++++++++++++++------------- drivers/net/ethernet/amd/xgbe/xgbe.h | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 19b943eba560..8cf5d81fca36 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -1989,7 +1989,7 @@ static void xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable) } static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, - unsigned int cmd, unsigned int sub_cmd) + enum xgbe_mb_cmd cmd, enum xgbe_mb_subcmd sub_cmd) { unsigned int s0 = 0; unsigned int wait; @@ -2036,7 +2036,7 @@ reenable_pll: static void xgbe_phy_rrc(struct xgbe_prv_data *pdata) { /* Receiver Reset Cycle */ - xgbe_phy_perform_ratechange(pdata, 5, 0); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_RRC, XGBE_MB_SUBCMD_NONE); netif_dbg(pdata, link, pdata->netdev, "receiver reset complete\n"); } @@ -2046,7 +2046,7 @@ static void xgbe_phy_power_off(struct xgbe_prv_data *pdata) struct xgbe_phy_data *phy_data = pdata->phy_data; /* Power off */ - xgbe_phy_perform_ratechange(pdata, 0, 0); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_POWER_OFF, XGBE_MB_SUBCMD_NONE); phy_data->cur_mode = XGBE_MODE_UNKNOWN; @@ -2061,14 +2061,17 @@ static void xgbe_phy_sfi_mode(struct xgbe_prv_data *pdata) /* 10G/SFI */ if (phy_data->sfp_cable != XGBE_SFP_CABLE_PASSIVE) { - xgbe_phy_perform_ratechange(pdata, 3, 0); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_10G_SFI, XGBE_MB_SUBCMD_ACTIVE); } else { if (phy_data->sfp_cable_len <= 1) - xgbe_phy_perform_ratechange(pdata, 3, 1); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_10G_SFI, + XGBE_MB_SUBCMD_PASSIVE_1M); else if (phy_data->sfp_cable_len <= 3) - xgbe_phy_perform_ratechange(pdata, 3, 2); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_10G_SFI, + XGBE_MB_SUBCMD_PASSIVE_3M); else - xgbe_phy_perform_ratechange(pdata, 3, 3); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_10G_SFI, + XGBE_MB_SUBCMD_PASSIVE_OTHER); } phy_data->cur_mode = XGBE_MODE_SFI; @@ -2083,7 +2086,7 @@ static void xgbe_phy_x_mode(struct xgbe_prv_data *pdata) xgbe_phy_set_redrv_mode(pdata); /* 1G/X */ - xgbe_phy_perform_ratechange(pdata, 1, 3); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_1G, XGBE_MB_SUBCMD_1G_KX); phy_data->cur_mode = XGBE_MODE_X; @@ -2097,7 +2100,7 @@ static void xgbe_phy_sgmii_1000_mode(struct xgbe_prv_data *pdata) xgbe_phy_set_redrv_mode(pdata); /* 1G/SGMII */ - xgbe_phy_perform_ratechange(pdata, 1, 2); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_1G, XGBE_MB_SUBCMD_1G_SGMII); phy_data->cur_mode = XGBE_MODE_SGMII_1000; @@ -2111,7 +2114,7 @@ static void xgbe_phy_sgmii_100_mode(struct xgbe_prv_data *pdata) xgbe_phy_set_redrv_mode(pdata); /* 100M/SGMII */ - xgbe_phy_perform_ratechange(pdata, 1, 1); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_1G, XGBE_MB_SUBCMD_100MBITS); phy_data->cur_mode = XGBE_MODE_SGMII_100; @@ -2125,7 +2128,7 @@ static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata) xgbe_phy_set_redrv_mode(pdata); /* 10G/KR */ - xgbe_phy_perform_ratechange(pdata, 4, 0); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_10G_KR, XGBE_MB_SUBCMD_NONE); phy_data->cur_mode = XGBE_MODE_KR; @@ -2139,7 +2142,7 @@ static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata) xgbe_phy_set_redrv_mode(pdata); /* 2.5G/KX */ - xgbe_phy_perform_ratechange(pdata, 2, 0); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_2_5G, XGBE_MB_SUBCMD_NONE); phy_data->cur_mode = XGBE_MODE_KX_2500; @@ -2153,7 +2156,7 @@ static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata) xgbe_phy_set_redrv_mode(pdata); /* 1G/KX */ - xgbe_phy_perform_ratechange(pdata, 1, 3); + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_1G, XGBE_MB_SUBCMD_1G_KX); phy_data->cur_mode = XGBE_MODE_KX_1000; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 49d23abce73d..71f24cb47935 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -611,6 +611,31 @@ enum xgbe_mdio_mode { XGBE_MDIO_MODE_CL45, }; +enum xgbe_mb_cmd { + XGBE_MB_CMD_POWER_OFF = 0, + XGBE_MB_CMD_SET_1G, + XGBE_MB_CMD_SET_2_5G, + XGBE_MB_CMD_SET_10G_SFI, + XGBE_MB_CMD_SET_10G_KR, + XGBE_MB_CMD_RRC +}; + +enum xgbe_mb_subcmd { + XGBE_MB_SUBCMD_NONE = 0, + + /* 10GbE SFP subcommands */ + XGBE_MB_SUBCMD_ACTIVE = 0, + XGBE_MB_SUBCMD_PASSIVE_1M, + XGBE_MB_SUBCMD_PASSIVE_3M, + XGBE_MB_SUBCMD_PASSIVE_OTHER, + + /* 1GbE Mode subcommands */ + XGBE_MB_SUBCMD_10MBITS = 0, + XGBE_MB_SUBCMD_100MBITS, + XGBE_MB_SUBCMD_1G_SGMII, + XGBE_MB_SUBCMD_1G_KX +}; + struct xgbe_phy { struct ethtool_link_ksettings lks; -- cgit v1.2.3 From fc75c032aee63e60170d80f44c8567ea45fc59da Mon Sep 17 00:00:00 2001 From: Raju Rangoju Date: Thu, 20 Oct 2022 12:12:13 +0530 Subject: amd-xgbe: enable PLL_CTL for fixed PHY modes only PLL control setting(RRC) is needed only in fixed PHY configuration to fix the peer-peer issues. Without the PLL control setting, the link up takes longer time in a fixed phy configuration. Driver implements SW RRC for Autoneg On configuration, hence PLL control setting (RRC) is not needed for AN On configuration, and can be skipped. Also, PLL re-initialization is not needed for PHY Power Off and RRC commands. Otherwise, they lead to mailbox errors. Added the changes accordingly. Fixes: daf182d360e5 ("net: amd-xgbe: Toggle PLL settings during rate change") Signed-off-by: Raju Rangoju Acked-by: Tom Lendacky Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 8cf5d81fca36..349ba0dc1fa2 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -1979,6 +1979,10 @@ static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata) static void xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable) { + /* PLL_CTRL feature needs to be enabled for fixed PHY modes (Non-Autoneg) only */ + if (pdata->phy.autoneg != AUTONEG_DISABLE) + return; + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0, XGBE_PMA_PLL_CTRL_MASK, enable ? XGBE_PMA_PLL_CTRL_ENABLE @@ -2029,8 +2033,10 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, xgbe_phy_rx_reset(pdata); reenable_pll: - /* Enable PLL re-initialization */ - xgbe_phy_pll_ctrl(pdata, true); + /* Enable PLL re-initialization, not needed for PHY Power Off and RRC cmds */ + if (cmd != XGBE_MB_CMD_POWER_OFF && + cmd != XGBE_MB_CMD_RRC) + xgbe_phy_pll_ctrl(pdata, true); } static void xgbe_phy_rrc(struct xgbe_prv_data *pdata) -- cgit v1.2.3 From 09c5f6bf11ac98874339e55f4f5f79a9dbc9b375 Mon Sep 17 00:00:00 2001 From: Raju Rangoju Date: Thu, 20 Oct 2022 12:12:14 +0530 Subject: amd-xgbe: fix the SFP compliance codes check for DAC cables The current XGBE code assumes that offset 6 of EEPROM SFP DAC (passive) cables is NULL. However, some cables (the 5 meter and 7 meter Molex passive cables) have non-zero data at offset 6. Fix the logic by moving the passive cable check above the active checks, so as not to be improperly identified as an active cable. This will fix the issue for any passive cable that advertises 1000Base-CX in offset 6. Fixes: abf0a1c2b26a ("amd-xgbe: Add support for SFP+ modules") Signed-off-by: Raju Rangoju Acked-by: Tom Lendacky Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 349ba0dc1fa2..8c41ac5676d6 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -1151,7 +1151,10 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) } /* Determine the type of SFP */ - if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR) + if (phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE && + xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000)) + phy_data->sfp_base = XGBE_SFP_BASE_10000_CR; + else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR) phy_data->sfp_base = XGBE_SFP_BASE_10000_SR; else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_LR) phy_data->sfp_base = XGBE_SFP_BASE_10000_LR; @@ -1167,9 +1170,6 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) phy_data->sfp_base = XGBE_SFP_BASE_1000_CX; else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_T) phy_data->sfp_base = XGBE_SFP_BASE_1000_T; - else if ((phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE) && - xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000)) - phy_data->sfp_base = XGBE_SFP_BASE_10000_CR; switch (phy_data->sfp_base) { case XGBE_SFP_BASE_1000_T: -- cgit v1.2.3 From 170a9e341a3b02c0b2ea0df16ef14a33a4f41de8 Mon Sep 17 00:00:00 2001 From: Raju Rangoju Date: Thu, 20 Oct 2022 12:12:15 +0530 Subject: amd-xgbe: add the bit rate quirk for Molex cables The offset 12 (bit-rate) of EEPROM SFP DAC (passive) cables is expected to be in the range 0x64 to 0x68. However, the 5 meter and 7 meter Molex passive cables have the rate ceiling 0x78 at offset 12. Add a quirk for Molex passive cables to extend the rate ceiling to 0x78. Fixes: abf0a1c2b26a ("amd-xgbe: Add support for SFP+ modules") Signed-off-by: Raju Rangoju Acked-by: Tom Lendacky Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 8c41ac5676d6..4064c3e3dd49 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -239,6 +239,7 @@ enum xgbe_sfp_speed { #define XGBE_SFP_BASE_BR_1GBE_MAX 0x0d #define XGBE_SFP_BASE_BR_10GBE_MIN 0x64 #define XGBE_SFP_BASE_BR_10GBE_MAX 0x68 +#define XGBE_MOLEX_SFP_BASE_BR_10GBE_MAX 0x78 #define XGBE_SFP_BASE_CU_CABLE_LEN 18 @@ -284,6 +285,8 @@ struct xgbe_sfp_eeprom { #define XGBE_BEL_FUSE_VENDOR "BEL-FUSE " #define XGBE_BEL_FUSE_PARTNO "1GBT-SFP06 " +#define XGBE_MOLEX_VENDOR "Molex Inc. " + struct xgbe_sfp_ascii { union { char vendor[XGBE_SFP_BASE_VENDOR_NAME_LEN + 1]; @@ -834,7 +837,11 @@ static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom, break; case XGBE_SFP_SPEED_10000: min = XGBE_SFP_BASE_BR_10GBE_MIN; - max = XGBE_SFP_BASE_BR_10GBE_MAX; + if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME], + XGBE_MOLEX_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN) == 0) + max = XGBE_MOLEX_SFP_BASE_BR_10GBE_MAX; + else + max = XGBE_SFP_BASE_BR_10GBE_MAX; break; default: return false; -- cgit v1.2.3 From 0bda03623e6b8b9052da5ba0145608941bcc2eb0 Mon Sep 17 00:00:00 2001 From: Yinjun Zhang Date: Thu, 20 Oct 2022 09:14:11 +0100 Subject: nfp: only clean `sp_indiff` when application firmware is unloaded Currently `sp_indiff` is cleaned when driver is removed. This will cause problem in multi-PF/multi-host case, considering one PF is removed while another is still in use. Since `sp_indiff` is the application firmware property, it should only be cleaned when the firmware is unloaded. Now let management firmware to clean it when necessary, driver only set it. Fixes: b1e4f11e426d ("nfp: refine the ABI of getting `sp_indiff` info") Signed-off-by: Yinjun Zhang Signed-off-by: Simon Horman Link: https://lore.kernel.org/r/20221020081411.80186-1-simon.horman@corigine.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/netronome/nfp/nfp_main.c | 38 +++++++++++---------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c index e66e548919d4..71301dbd8fb5 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c @@ -716,16 +716,26 @@ static u64 nfp_net_pf_get_app_cap(struct nfp_pf *pf) return val; } -static int nfp_pf_cfg_hwinfo(struct nfp_pf *pf, bool sp_indiff) +static void nfp_pf_cfg_hwinfo(struct nfp_pf *pf) { struct nfp_nsp *nsp; char hwinfo[32]; + bool sp_indiff; int err; nsp = nfp_nsp_open(pf->cpp); if (IS_ERR(nsp)) - return PTR_ERR(nsp); + return; + + if (!nfp_nsp_has_hwinfo_set(nsp)) + goto end; + sp_indiff = (nfp_net_pf_get_app_id(pf) == NFP_APP_FLOWER_NIC) || + (nfp_net_pf_get_app_cap(pf) & NFP_NET_APP_CAP_SP_INDIFF); + + /* No need to clean `sp_indiff` in driver, management firmware + * will do it when application firmware is unloaded. + */ snprintf(hwinfo, sizeof(hwinfo), "sp_indiff=%d", sp_indiff); err = nfp_nsp_hwinfo_set(nsp, hwinfo, sizeof(hwinfo)); /* Not a fatal error, no need to return error to stop driver from loading */ @@ -739,21 +749,8 @@ static int nfp_pf_cfg_hwinfo(struct nfp_pf *pf, bool sp_indiff) pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp); } +end: nfp_nsp_close(nsp); - return 0; -} - -static int nfp_pf_nsp_cfg(struct nfp_pf *pf) -{ - bool sp_indiff = (nfp_net_pf_get_app_id(pf) == NFP_APP_FLOWER_NIC) || - (nfp_net_pf_get_app_cap(pf) & NFP_NET_APP_CAP_SP_INDIFF); - - return nfp_pf_cfg_hwinfo(pf, sp_indiff); -} - -static void nfp_pf_nsp_clean(struct nfp_pf *pf) -{ - nfp_pf_cfg_hwinfo(pf, false); } static int nfp_pci_probe(struct pci_dev *pdev, @@ -856,13 +853,11 @@ static int nfp_pci_probe(struct pci_dev *pdev, goto err_fw_unload; } - err = nfp_pf_nsp_cfg(pf); - if (err) - goto err_fw_unload; + nfp_pf_cfg_hwinfo(pf); err = nfp_net_pci_probe(pf); if (err) - goto err_nsp_clean; + goto err_fw_unload; err = nfp_hwmon_register(pf); if (err) { @@ -874,8 +869,6 @@ static int nfp_pci_probe(struct pci_dev *pdev, err_net_remove: nfp_net_pci_remove(pf); -err_nsp_clean: - nfp_pf_nsp_clean(pf); err_fw_unload: kfree(pf->rtbl); nfp_mip_close(pf->mip); @@ -915,7 +908,6 @@ static void __nfp_pci_shutdown(struct pci_dev *pdev, bool unload_fw) nfp_net_pci_remove(pf); - nfp_pf_nsp_clean(pf); vfree(pf->dumpspec); kfree(pf->rtbl); nfp_mip_close(pf->mip); -- cgit v1.2.3 From d182c2e1bc92084c038b44c618f29589a4de9f66 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 18 Oct 2022 02:35:10 +0300 Subject: usb: dwc3: Don't switch OTG -> peripheral if extcon is present If the extcon device exists, get the mode from the extcon device. If the controller is DRD and the driver is unable to determine the mode, only then default the dr_mode to USB_DR_MODE_PERIPHERAL. Reported-by: Steev Klimaszewski Fixes: 7a84e7353e23 ("Revert "usb: dwc3: Don't switch OTG -> peripheral if extcon is present"") Cc: stable Reviewed-by: Thinh Nguyen Signed-off-by: Andrey Smirnov Signed-off-by: Andy Shevchenko Tested-by: Steev Klimaszewski Acked-by: Thinh Nguyen Link: https://lore.kernel.org/r/20221017233510.53336-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/core.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++- drivers/usb/dwc3/drd.c | 50 ------------------------------------------------- 2 files changed, 48 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ea51624461b5..c0e7c76dc5c8 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -85,7 +86,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) * mode. If the controller supports DRD but the dr_mode is not * specified or set to OTG, then set the mode to peripheral. */ - if (mode == USB_DR_MODE_OTG && + if (mode == USB_DR_MODE_OTG && !dwc->edev && (!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) || !device_property_read_bool(dwc->dev, "usb-role-switch")) && !DWC3_VER_IS_PRIOR(DWC3, 330A)) @@ -1690,6 +1691,46 @@ static void dwc3_check_params(struct dwc3 *dwc) } } +static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) +{ + struct device *dev = dwc->dev; + struct device_node *np_phy; + struct extcon_dev *edev = NULL; + const char *name; + + if (device_property_read_bool(dev, "extcon")) + return extcon_get_edev_by_phandle(dev, 0); + + /* + * Device tree platforms should get extcon via phandle. + * On ACPI platforms, we get the name from a device property. + * This device property is for kernel internal use only and + * is expected to be set by the glue code. + */ + if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) + return extcon_get_extcon_dev(name); + + /* + * Try to get an extcon device from the USB PHY controller's "port" + * node. Check if it has the "port" node first, to avoid printing the + * error message from underlying code, as it's a valid case: extcon + * device (and "port" node) may be missing in case of "usb-role-switch" + * or OTG mode. + */ + np_phy = of_parse_phandle(dev->of_node, "phys", 0); + if (of_graph_is_present(np_phy)) { + struct device_node *np_conn; + + np_conn = of_graph_get_remote_node(np_phy, -1, -1); + if (np_conn) + edev = extcon_find_edev_by_node(np_conn); + of_node_put(np_conn); + } + of_node_put(np_phy); + + return edev; +} + static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1840,6 +1881,12 @@ static int dwc3_probe(struct platform_device *pdev) goto err2; } + dwc->edev = dwc3_get_extcon(dwc); + if (IS_ERR(dwc->edev)) { + ret = dev_err_probe(dwc->dev, PTR_ERR(dwc->edev), "failed to get extcon\n"); + goto err3; + } + ret = dwc3_get_dr_mode(dwc); if (ret) goto err3; diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index 8cad9e7d3368..039bf241769a 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include @@ -439,51 +438,6 @@ static int dwc3_drd_notifier(struct notifier_block *nb, return NOTIFY_DONE; } -static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) -{ - struct device *dev = dwc->dev; - struct device_node *np_phy; - struct extcon_dev *edev = NULL; - const char *name; - - if (device_property_read_bool(dev, "extcon")) - return extcon_get_edev_by_phandle(dev, 0); - - /* - * Device tree platforms should get extcon via phandle. - * On ACPI platforms, we get the name from a device property. - * This device property is for kernel internal use only and - * is expected to be set by the glue code. - */ - if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) { - edev = extcon_get_extcon_dev(name); - if (!edev) - return ERR_PTR(-EPROBE_DEFER); - - return edev; - } - - /* - * Try to get an extcon device from the USB PHY controller's "port" - * node. Check if it has the "port" node first, to avoid printing the - * error message from underlying code, as it's a valid case: extcon - * device (and "port" node) may be missing in case of "usb-role-switch" - * or OTG mode. - */ - np_phy = of_parse_phandle(dev->of_node, "phys", 0); - if (of_graph_is_present(np_phy)) { - struct device_node *np_conn; - - np_conn = of_graph_get_remote_node(np_phy, -1, -1); - if (np_conn) - edev = extcon_find_edev_by_node(np_conn); - of_node_put(np_conn); - } - of_node_put(np_phy); - - return edev; -} - #if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) #define ROLE_SWITCH 1 static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, @@ -588,10 +542,6 @@ int dwc3_drd_init(struct dwc3 *dwc) device_property_read_bool(dwc->dev, "usb-role-switch")) return dwc3_setup_role_switch(dwc); - dwc->edev = dwc3_get_extcon(dwc); - if (IS_ERR(dwc->edev)) - return PTR_ERR(dwc->edev); - if (dwc->edev) { dwc->edev_nb.notifier_call = dwc3_drd_notifier; ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, -- cgit v1.2.3 From 4db0fbb601361767144e712beb96704b966339f5 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Tue, 18 Oct 2022 19:39:01 -0700 Subject: usb: dwc3: gadget: Don't delay End Transfer on delayed_status The gadget driver may wait on the request completion when it sets the USB_GADGET_DELAYED_STATUS. Make sure that the End Transfer command can go through if the dwc->delayed_status is set so that the request can complete. When the delayed_status is set, the Setup packet is already processed, and the next phase should be either Data or Status. It's unlikely that the host would cancel the control transfer and send a new Setup packet during End Transfer command. But if that's the case, we can try again when ep0state returns to EP0_SETUP_PHASE. Fixes: e1ee843488d5 ("usb: dwc3: gadget: Force sending delayed status during soft disconnect") Cc: stable@vger.kernel.org Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/3f9f59e5d74efcbaee444cf4b30ef639cc7b124e.1666146954.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 079cd333632e..dd8ecbe61bec 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1698,6 +1698,16 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); memset(¶ms, 0, sizeof(params)); ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); + /* + * If the End Transfer command was timed out while the device is + * not in SETUP phase, it's possible that an incoming Setup packet + * may prevent the command's completion. Let's retry when the + * ep0state returns to EP0_SETUP_PHASE. + */ + if (ret == -ETIMEDOUT && dep->dwc->ep0state != EP0_SETUP_PHASE) { + dep->flags |= DWC3_EP_DELAY_STOP; + return 0; + } WARN_ON_ONCE(ret); dep->resource_index = 0; @@ -3719,7 +3729,7 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, * timeout. Delay issuing the End Transfer command until the Setup TRB is * prepared. */ - if (dwc->ep0state != EP0_SETUP_PHASE) { + if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status) { dep->flags |= DWC3_EP_DELAY_STOP; return; } -- cgit v1.2.3 From 8e8e923a49967b798e7d69f1ce9eff1dd2533547 Mon Sep 17 00:00:00 2001 From: Dan Vacura Date: Tue, 18 Oct 2022 16:50:37 -0500 Subject: usb: gadget: uvc: fix dropped frame after missed isoc With the re-use of the previous completion status in 0d1c407b1a749 ("usb: dwc3: gadget: Return proper request status") it could be possible that the next frame would also get dropped if the current frame has a missed isoc error. Ensure that an interrupt is requested for the start of a new frame. Fixes: fc78941d8169 ("usb: gadget: uvc: decrease the interrupt load to a quarter") Cc: Signed-off-by: Dan Vacura Link: https://lore.kernel.org/r/20221018215044.765044-2-w36195@motorola.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/uvc_video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index bb037fcc90e6..323977716f5a 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -431,7 +431,8 @@ static void uvcg_video_pump(struct work_struct *work) /* Endpoint now owns the request */ req = NULL; - video->req_int_count++; + if (buf->state != UVC_BUF_STATE_DONE) + video->req_int_count++; } if (!req) -- cgit v1.2.3 From 0a0a2760b04814428800d48281a447a7522470ad Mon Sep 17 00:00:00 2001 From: Dan Vacura Date: Tue, 18 Oct 2022 16:50:39 -0500 Subject: usb: gadget: uvc: fix sg handling in error case If there is a transmission error the buffer will be returned too early, causing a memory fault as subsequent requests for that buffer are still queued up to be sent. Refactor the error handling to wait for the final request to come in before reporting back the buffer to userspace for all transfer types (bulk/isoc/isoc_sg). This ensures userspace knows if the frame was successfully sent. Fixes: e81e7f9a0eb9 ("usb: gadget: uvc: add scatter gather support") Cc: Signed-off-by: Dan Vacura Link: https://lore.kernel.org/r/20221018215044.765044-4-w36195@motorola.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/uvc_queue.c | 8 +++++--- drivers/usb/gadget/function/uvc_video.c | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index ec500ee499ee..0aa3d7e1f3cc 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -304,6 +304,7 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) queue->sequence = 0; queue->buf_used = 0; + queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE; } else { ret = vb2_streamoff(&queue->queue, queue->queue.type); if (ret < 0) @@ -329,10 +330,11 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) void uvcg_complete_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { - if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && - buf->length != buf->bytesused) { - buf->state = UVC_BUF_STATE_QUEUED; + if (queue->flags & UVC_QUEUE_DROP_INCOMPLETE) { + queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE; + buf->state = UVC_BUF_STATE_ERROR; vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0); + vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR); return; } diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 323977716f5a..5993e083819c 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -88,6 +88,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, struct uvc_buffer *buf) { void *mem = req->buf; + struct uvc_request *ureq = req->context; int len = video->req_size; int ret; @@ -113,13 +114,14 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; list_del(&buf->queue); - uvcg_complete_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; + ureq->last_buf = buf; video->payload_size = 0; } if (video->payload_size == video->max_payload_size || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE || buf->bytesused == video->queue.buf_used) video->payload_size = 0; } @@ -180,7 +182,8 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, req->length -= len; video->queue.buf_used += req->length - header_len; - if (buf->bytesused == video->queue.buf_used || !buf->sg) { + if (buf->bytesused == video->queue.buf_used || !buf->sg || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; buf->offset = 0; @@ -195,6 +198,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, struct uvc_buffer *buf) { void *mem = req->buf; + struct uvc_request *ureq = req->context; int len = video->req_size; int ret; @@ -209,12 +213,13 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, req->length = video->req_size - len; - if (buf->bytesused == video->queue.buf_used) { + if (buf->bytesused == video->queue.buf_used || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; list_del(&buf->queue); - uvcg_complete_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; + ureq->last_buf = buf; } } @@ -255,6 +260,11 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) case 0: break; + case -EXDEV: + uvcg_dbg(&video->uvc->func, "VS request missed xfer.\n"); + queue->flags |= UVC_QUEUE_DROP_INCOMPLETE; + break; + case -ESHUTDOWN: /* disconnect from host. */ uvcg_dbg(&video->uvc->func, "VS request cancelled.\n"); uvcg_queue_cancel(queue, 1); -- cgit v1.2.3 From b57b08e6f431348363adffa5b6643fe3ec9dc7fe Mon Sep 17 00:00:00 2001 From: Jeff Vanhoof Date: Tue, 18 Oct 2022 16:50:40 -0500 Subject: usb: gadget: uvc: fix sg handling during video encode In uvc_video_encode_isoc_sg, the uvc_request's sg list is incorrectly being populated leading to corrupt video being received by the remote end. When building the sg list the usage of buf->sg's 'dma_length' field is not correct and instead its 'length' field should be used. Fixes: e81e7f9a0eb9 ("usb: gadget: uvc: add scatter gather support") Cc: Signed-off-by: Jeff Vanhoof Signed-off-by: Dan Vacura Link: https://lore.kernel.org/r/20221018215044.765044-5-w36195@motorola.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/uvc_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 5993e083819c..dd1c6b2ca7c6 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -157,10 +157,10 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, sg = sg_next(sg); for_each_sg(sg, iter, ureq->sgt.nents - 1, i) { - if (!len || !buf->sg || !sg_dma_len(buf->sg)) + if (!len || !buf->sg || !buf->sg->length) break; - sg_left = sg_dma_len(buf->sg) - buf->offset; + sg_left = buf->sg->length - buf->offset; part = min_t(unsigned int, len, sg_left); sg_set_page(iter, sg_page(buf->sg), part, buf->offset); -- cgit v1.2.3 From 48ed32482c4100069d0c0eebdc6b198c6ae5f71f Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Mon, 17 Oct 2022 16:00:06 +1030 Subject: usb: gadget: aspeed: Fix probe regression Since commit fc274c1e9973 ("USB: gadget: Add a new bus for gadgets"), the gadget devices are proper driver core devices, which caused each device to request pinmux settings: aspeed_vhub 1e6a0000.usb-vhub: Initialized virtual hub in USB2 mode aspeed-g5-pinctrl 1e6e2080.pinctrl: pin A7 already requested by 1e6a0000.usb-vhub; cannot claim for gadget.0 aspeed-g5-pinctrl 1e6e2080.pinctrl: pin-232 (gadget.0) status -22 aspeed-g5-pinctrl 1e6e2080.pinctrl: could not request pin 232 (A7) from group USB2AD on device aspeed-g5-pinctrl g_mass_storage gadget.0: Error applying setting, reverse things back The vhub driver has already claimed the pins, so prevent the gadgets from requesting them too by setting the magic of_node_reused flag. This causes the driver core to skip the mux request. Reported-by: Zev Weiss Reported-by: Jae Hyun Yoo Fixes: fc274c1e9973 ("USB: gadget: Add a new bus for gadgets") Cc: stable@vger.kernel.org Signed-off-by: Joel Stanley Tested-by: Zev Weiss Tested-by: Jae Hyun Yoo Link: https://lore.kernel.org/r/20221017053006.358520-1-joel@jms.id.au Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/aspeed-vhub/dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index b0dfca43fbdc..4f3bc27c1c62 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -591,6 +591,7 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx) d->gadget.max_speed = USB_SPEED_HIGH; d->gadget.speed = USB_SPEED_UNKNOWN; d->gadget.dev.of_node = vhub->pdev->dev.of_node; + d->gadget.dev.of_node_reused = true; rc = usb_add_gadget_udc(d->port_dev, &d->gadget); if (rc != 0) -- cgit v1.2.3 From 99f6d43611135bd6f211dec9e88bb41e4167e304 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 7 Oct 2022 13:09:50 +0300 Subject: usb: typec: ucsi: Check the connection on resume Checking the connection status of every port on resume. This fixes an issue where the partner device is not unregistered properly after resume if it was unplugged while the system was suspended. The function ucsi_check_connection() is also modified so that it can be used also for registering the connection on top of unregistering it. Link: https://bugzilla.kernel.org/show_bug.cgi?id=210425 Fixes: a94ecde41f7e ("usb: typec: ucsi: ccg: enable runtime pm support") Cc: Signed-off-by: Heikki Krogerus Link: https://lore.kernel.org/r/20221007100951.43798-2-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 74fb5a4c6f21..a7987fc764cc 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -183,16 +183,6 @@ out: } EXPORT_SYMBOL_GPL(ucsi_send_command); -int ucsi_resume(struct ucsi *ucsi) -{ - u64 command; - - /* Restore UCSI notification enable mask after system resume */ - command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; - - return ucsi_send_command(ucsi, command, NULL, 0); -} -EXPORT_SYMBOL_GPL(ucsi_resume); /* -------------------------------------------------------------------------- */ struct ucsi_work { @@ -744,6 +734,7 @@ static void ucsi_partner_change(struct ucsi_connector *con) static int ucsi_check_connection(struct ucsi_connector *con) { + u8 prev_flags = con->status.flags; u64 command; int ret; @@ -754,10 +745,13 @@ static int ucsi_check_connection(struct ucsi_connector *con) return ret; } + if (con->status.flags == prev_flags) + return 0; + if (con->status.flags & UCSI_CONSTAT_CONNECTED) { - if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == - UCSI_CONSTAT_PWR_OPMODE_PD) - ucsi_partner_task(con, ucsi_check_altmodes, 30, 0); + ucsi_register_partner(con); + ucsi_pwr_opmode_change(con); + ucsi_partner_change(con); } else { ucsi_partner_change(con); ucsi_port_psy_changed(con); @@ -1276,6 +1270,28 @@ err: return ret; } +int ucsi_resume(struct ucsi *ucsi) +{ + struct ucsi_connector *con; + u64 command; + int ret; + + /* Restore UCSI notification enable mask after system resume */ + command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; + ret = ucsi_send_command(ucsi, command, NULL, 0); + if (ret < 0) + return ret; + + for (con = ucsi->connector; con->port; con++) { + mutex_lock(&con->lock); + ucsi_check_connection(con); + mutex_unlock(&con->lock); + } + + return 0; +} +EXPORT_SYMBOL_GPL(ucsi_resume); + static void ucsi_init_work(struct work_struct *work) { struct ucsi *ucsi = container_of(work, struct ucsi, work.work); -- cgit v1.2.3 From 4e3a50293c2b21961f02e1afa2f17d3a1a90c7c8 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 7 Oct 2022 13:09:51 +0300 Subject: usb: typec: ucsi: acpi: Implement resume callback The ACPI driver needs to resume the interface by calling ucsi_resume(). Otherwise we may fail to detect connections and disconnections that happen while the system is suspended. Link: https://bugzilla.kernel.org/show_bug.cgi?id=210425 Fixes: a94ecde41f7e ("usb: typec: ucsi: ccg: enable runtime pm support") Cc: Signed-off-by: Heikki Krogerus Link: https://lore.kernel.org/r/20221007100951.43798-3-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi_acpi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 8873c1644a29..ce0c8ef80c04 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -185,6 +185,15 @@ static int ucsi_acpi_remove(struct platform_device *pdev) return 0; } +static int ucsi_acpi_resume(struct device *dev) +{ + struct ucsi_acpi *ua = dev_get_drvdata(dev); + + return ucsi_resume(ua->ucsi); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(ucsi_acpi_pm_ops, NULL, ucsi_acpi_resume); + static const struct acpi_device_id ucsi_acpi_match[] = { { "PNP0CA0", 0 }, { }, @@ -194,6 +203,7 @@ MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match); static struct platform_driver ucsi_acpi_platform_driver = { .driver = { .name = "ucsi_acpi", + .pm = pm_ptr(&ucsi_acpi_pm_ops), .acpi_match_table = ACPI_PTR(ucsi_acpi_match), }, .probe = ucsi_acpi_probe, -- cgit v1.2.3 From fb8f60dd1b67520e0e0d7978ef17d015690acfc1 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 5 Oct 2022 12:13:55 -0700 Subject: usb: bdc: change state when port disconnected When port is connected and then disconnected, the state stays as configured. Which is incorrect as the port is no longer configured, but in a not attached state. Signed-off-by: Justin Chen Acked-by: Florian Fainelli Fixes: efed421a94e6 ("usb: gadget: Add UDC driver for Broadcom USB3.0 device controller IP BDC") Cc: stable Link: https://lore.kernel.org/r/1664997235-18198-1-git-send-email-justinpopo6@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/bdc/bdc_udc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/bdc/bdc_udc.c b/drivers/usb/gadget/udc/bdc/bdc_udc.c index 5ac0ef88334e..53ffaf4e2e37 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_udc.c +++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c @@ -151,6 +151,7 @@ static void bdc_uspc_disconnected(struct bdc *bdc, bool reinit) bdc->delayed_status = false; bdc->reinit = reinit; bdc->test_mode = false; + usb_gadget_set_state(&bdc->gadget, USB_STATE_NOTATTACHED); } /* TNotify wkaeup timer */ -- cgit v1.2.3 From d917a62af81b133f35f627e7936e193c842a7947 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Tue, 18 Oct 2022 08:10:14 -0400 Subject: counter: microchip-tcb-capture: Handle Signal1 read and Synapse The signal_read(), action_read(), and action_write() callbacks have been assuming Signal0 is requested without checking. This results in requests for Signal1 returning data for Signal0. This patch fixes these oversights by properly checking for the Signal's id in the respective callbacks and handling accordingly based on the particular Signal requested. The trig_inverted member of the mchp_tc_data is removed as superfluous. Fixes: 106b104137fd ("counter: Add microchip TCB capture counter") Cc: stable@vger.kernel.org Reviewed-by: Kamel Bouhara Link: https://lore.kernel.org/r/20221018121014.7368-1-william.gray@linaro.org/ Signed-off-by: William Breathitt Gray --- drivers/counter/microchip-tcb-capture.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c index f9dee15d9777..e2d1dc6ca668 100644 --- a/drivers/counter/microchip-tcb-capture.c +++ b/drivers/counter/microchip-tcb-capture.c @@ -28,7 +28,6 @@ struct mchp_tc_data { int qdec_mode; int num_channels; int channel[2]; - bool trig_inverted; }; static const enum counter_function mchp_tc_count_functions[] = { @@ -153,7 +152,7 @@ static int mchp_tc_count_signal_read(struct counter_device *counter, regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr); - if (priv->trig_inverted) + if (signal->id == 1) sigstatus = (sr & ATMEL_TC_MTIOB); else sigstatus = (sr & ATMEL_TC_MTIOA); @@ -171,6 +170,17 @@ static int mchp_tc_count_action_read(struct counter_device *counter, struct mchp_tc_data *const priv = counter_priv(counter); u32 cmr; + if (priv->qdec_mode) { + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; + return 0; + } + + /* Only TIOA signal is evaluated in non-QDEC mode */ + if (synapse->signal->id != 0) { + *action = COUNTER_SYNAPSE_ACTION_NONE; + return 0; + } + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr); switch (cmr & ATMEL_TC_ETRGEDG) { @@ -199,8 +209,8 @@ static int mchp_tc_count_action_write(struct counter_device *counter, struct mchp_tc_data *const priv = counter_priv(counter); u32 edge = ATMEL_TC_ETRGEDG_NONE; - /* QDEC mode is rising edge only */ - if (priv->qdec_mode) + /* QDEC mode is rising edge only; only TIOA handled in non-QDEC mode */ + if (priv->qdec_mode || synapse->signal->id != 0) return -EINVAL; switch (action) { -- cgit v1.2.3 From d501d37841d3b7f18402d71a9ef057eb9dde127e Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Thu, 20 Oct 2022 10:11:21 -0400 Subject: counter: 104-quad-8: Fix race getting function mode and direction The quad8_action_read() function checks the Count function mode and Count direction without first acquiring a lock. This is a race condition because the function mode could change by the time the direction is checked. Because the quad8_function_read() already acquires a lock internally, the quad8_function_read() is refactored to spin out the no-lock code to a new quad8_function_get() function. To resolve the race condition in quad8_action_read(), a lock is acquired before calling quad8_function_get() and quad8_direction_read() in order to get both function mode and direction atomically. Fixes: f1d8a071d45b ("counter: 104-quad-8: Add Generic Counter interface support") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221020141121.15434-1-william.gray@linaro.org/ Signed-off-by: William Breathitt Gray --- drivers/counter/104-quad-8.c | 64 +++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index 77a863b7eefe..deed4afadb29 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -232,34 +232,45 @@ static const enum counter_function quad8_count_functions_list[] = { COUNTER_FUNCTION_QUADRATURE_X4, }; +static int quad8_function_get(const struct quad8 *const priv, const size_t id, + enum counter_function *const function) +{ + if (!priv->quadrature_mode[id]) { + *function = COUNTER_FUNCTION_PULSE_DIRECTION; + return 0; + } + + switch (priv->quadrature_scale[id]) { + case 0: + *function = COUNTER_FUNCTION_QUADRATURE_X1_A; + return 0; + case 1: + *function = COUNTER_FUNCTION_QUADRATURE_X2_A; + return 0; + case 2: + *function = COUNTER_FUNCTION_QUADRATURE_X4; + return 0; + default: + /* should never reach this path */ + return -EINVAL; + } +} + static int quad8_function_read(struct counter_device *counter, struct counter_count *count, enum counter_function *function) { struct quad8 *const priv = counter_priv(counter); - const int id = count->id; unsigned long irqflags; + int retval; spin_lock_irqsave(&priv->lock, irqflags); - if (priv->quadrature_mode[id]) - switch (priv->quadrature_scale[id]) { - case 0: - *function = COUNTER_FUNCTION_QUADRATURE_X1_A; - break; - case 1: - *function = COUNTER_FUNCTION_QUADRATURE_X2_A; - break; - case 2: - *function = COUNTER_FUNCTION_QUADRATURE_X4; - break; - } - else - *function = COUNTER_FUNCTION_PULSE_DIRECTION; + retval = quad8_function_get(priv, count->id, function); spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return retval; } static int quad8_function_write(struct counter_device *counter, @@ -359,6 +370,7 @@ static int quad8_action_read(struct counter_device *counter, enum counter_synapse_action *action) { struct quad8 *const priv = counter_priv(counter); + unsigned long irqflags; int err; enum counter_function function; const size_t signal_a_id = count->synapses[0].signal->id; @@ -374,9 +386,21 @@ static int quad8_action_read(struct counter_device *counter, return 0; } - err = quad8_function_read(counter, count, &function); - if (err) + spin_lock_irqsave(&priv->lock, irqflags); + + /* Get Count function and direction atomically */ + err = quad8_function_get(priv, count->id, &function); + if (err) { + spin_unlock_irqrestore(&priv->lock, irqflags); + return err; + } + err = quad8_direction_read(counter, count, &direction); + if (err) { + spin_unlock_irqrestore(&priv->lock, irqflags); return err; + } + + spin_unlock_irqrestore(&priv->lock, irqflags); /* Default action mode */ *action = COUNTER_SYNAPSE_ACTION_NONE; @@ -389,10 +413,6 @@ static int quad8_action_read(struct counter_device *counter, return 0; case COUNTER_FUNCTION_QUADRATURE_X1_A: if (synapse->signal->id == signal_a_id) { - err = quad8_direction_read(counter, count, &direction); - if (err) - return err; - if (direction == COUNTER_COUNT_DIRECTION_FORWARD) *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; else -- cgit v1.2.3 From f4cd18c5b2000df0c382f6530eeca9141ea41faf Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Sat, 22 Oct 2022 08:23:52 -0700 Subject: efi/tpm: Pass correct address to memblock_reserve memblock_reserve() expects a physical address, but the address being passed for the TPM final events log is what was returned from early_memremap(). This results in something like the following: [ 0.000000] memblock_reserve: [0xffffffffff2c0000-0xffffffffff2c00e4] efi_tpm_eventlog_init+0x324/0x370 Pass the address from efi like what is done for the TPM events log. Fixes: c46f3405692d ("tpm: Reserve the TPM final events table") Cc: Matthew Garrett Cc: Jarkko Sakkinen Cc: Bartosz Szczepanek Cc: Ard Biesheuvel Signed-off-by: Jerry Snitselaar Acked-by: Jarkko Sakkinen Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/tpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c index 8f665678e9e3..e8d69bd548f3 100644 --- a/drivers/firmware/efi/tpm.c +++ b/drivers/firmware/efi/tpm.c @@ -97,7 +97,7 @@ int __init efi_tpm_eventlog_init(void) goto out_calc; } - memblock_reserve((unsigned long)final_tbl, + memblock_reserve(efi.tpm_final_log, tbl_size + sizeof(*final_tbl)); efi_tpm_final_log_size = tbl_size; -- cgit v1.2.3 From d76308f03ee1574b0deffde45604252a51c77f6d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 24 Oct 2022 08:32:39 +0200 Subject: Revert "coresight: cti: Fix hang in cti_disable_hw()" This reverts commit 665c157e0204176023860b51a46528ba0ba62c33. It causes reported build warnings: drivers/hwtracing/coresight/coresight-cti-core.c: In functio n 'cti_enable_hw': drivers/hwtracing/coresight/coresight-cti-core.c:93:24: warning: unused variable 'dev' [-Wunused-variable] 93 | struct device *dev = &drvdata->csdev->dev; | ^~~ drivers/hwtracing/coresight/coresight-cti-core.c: In function 'cti_disable_hw': drivers/hwtracing/coresight/coresight-cti-core.c:154:24: warning: unused variable 'dev' [-Wunused-variable] 154 | struct device *dev = &drvdata->csdev->dev; | ^~~ Reported-by: Stephen Rothwell Cc: Aishwarya TCV Cc: Cristian Marussi Cc: Suzuki Poulose Cc: James Clark Cc: Mike Leach Cc: Mike Leach Cc: Suzuki K Poulose Fixes: 665c157e0204 ("coresight: cti: Fix hang in cti_disable_hw()") Link: https://lore.kernel.org/r/20221024135752.2b83af97@canb.auug.org.au Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-cti-core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index 4a02ae23d3a0..1be92342b5b9 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -94,6 +94,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) unsigned long flags; int rc = 0; + pm_runtime_get_sync(dev->parent); spin_lock_irqsave(&drvdata->spinlock, flags); /* no need to do anything if enabled or unpowered*/ @@ -118,6 +119,7 @@ cti_state_unchanged: /* cannot enable due to error */ cti_err_not_enabled: spin_unlock_irqrestore(&drvdata->spinlock, flags); + pm_runtime_put(dev->parent); return rc; } @@ -173,6 +175,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); spin_unlock(&drvdata->spinlock); + pm_runtime_put(dev->parent); return 0; /* not disabled this call */ -- cgit v1.2.3 From 161a438d730dade2ba2b1bf8785f0759aba4ca5f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 20 Oct 2022 10:39:08 +0200 Subject: efi: random: reduce seed size to 32 bytes We no longer need at least 64 bytes of random seed to permit the early crng init to complete. The RNG is now based on Blake2s, so reduce the EFI seed size to the Blake2s hash size, which is sufficient for our purposes. While at it, drop the READ_ONCE(), which was supposed to prevent size from being evaluated after seed was unmapped. However, this cannot actually happen, so READ_ONCE() is unnecessary here. Cc: # v4.14+ Signed-off-by: Ard Biesheuvel Reviewed-by: Jason A. Donenfeld Acked-by: Ilias Apalodimas --- drivers/firmware/efi/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 3ecdc43a3f2b..a46df5d1d094 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -611,7 +611,7 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, seed = early_memremap(efi_rng_seed, sizeof(*seed)); if (seed != NULL) { - size = READ_ONCE(seed->size); + size = min(seed->size, EFI_RANDOM_SEED_SIZE); early_memunmap(seed, sizeof(*seed)); } else { pr_err("Could not map UEFI random seed!\n"); -- cgit v1.2.3 From 7d866e38c7e9ece8a096d0d098fa9d92b9d4f97e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 20 Oct 2022 10:39:09 +0200 Subject: efi: random: Use 'ACPI reclaim' memory for random seed EFI runtime services data is guaranteed to be preserved by the OS, making it a suitable candidate for the EFI random seed table, which may be passed to kexec kernels as well (after refreshing the seed), and so we need to ensure that the memory is preserved without support from the OS itself. However, runtime services data is intended for allocations that are relevant to the implementations of the runtime services themselves, and so they are unmapped from the kernel linear map, and mapped into the EFI page tables that are active while runtime service invocations are in progress. None of this is needed for the RNG seed. So let's switch to EFI 'ACPI reclaim' memory: in spite of the name, there is nothing exclusively ACPI about it, it is simply a type of allocation that carries firmware provided data which may or may not be relevant to the OS, and it is left up to the OS to decide whether to reclaim it after having consumed its contents. Given that in Linux, we never reclaim these allocations, it is a good choice for the EFI RNG seed, as the allocation is guaranteed to survive kexec reboots. One additional reason for changing this now is to align it with the upcoming recommendation for EFI bootloader provided RNG seeds, which must not use EFI runtime services code/data allocations. Cc: # v4.14+ Signed-off-by: Ard Biesheuvel Reviewed-by: Ilias Apalodimas --- drivers/firmware/efi/libstub/random.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c index 24aa37535372..33ab56769595 100644 --- a/drivers/firmware/efi/libstub/random.c +++ b/drivers/firmware/efi/libstub/random.c @@ -75,7 +75,12 @@ efi_status_t efi_random_get_seed(void) if (status != EFI_SUCCESS) return status; - status = efi_bs_call(allocate_pool, EFI_RUNTIME_SERVICES_DATA, + /* + * Use EFI_ACPI_RECLAIM_MEMORY here so that it is guaranteed that the + * allocation will survive a kexec reboot (although we refresh the seed + * beforehand) + */ + status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, sizeof(*seed) + EFI_RANDOM_SEED_SIZE, (void **)&seed); if (status != EFI_SUCCESS) -- cgit v1.2.3 From 1a3abd12a394f5c66943fee75cef533069e831fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Mon, 17 Oct 2022 06:24:32 -0700 Subject: drm/i915: Extend Wa_1607297627 to Alderlake-P MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Workaround 1607297627 was missed for Alderlake-P, so here extending it to it and adding the fixes tag so this WA is backported to all stable kernels. v2: - fixed subject - added Fixes tag BSpec: 54369 Cc: # v5.17+ Fixes: dfb924e33927 ("drm/i915/adlp: Remove require_force_probe protection") Reviewed-by: Lucas De Marchi Cc: Tvrtko Ursulin Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20221017132432.112850-1-jose.souza@intel.com (cherry picked from commit 847eec69f01a28ca44f5ac7e1d71d3a60263d680) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 6d2003d598e6..a821e3d405db 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -2293,11 +2293,11 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) } if (IS_DG1_GRAPHICS_STEP(i915, STEP_A0, STEP_B0) || - IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) { + IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915) || IS_ALDERLAKE_P(i915)) { /* * Wa_1607030317:tgl * Wa_1607186500:tgl - * Wa_1607297627:tgl,rkl,dg1[a0] + * Wa_1607297627:tgl,rkl,dg1[a0],adlp * * On TGL and RKL there are multiple entries for this WA in the * BSpec; some indicate this is an A0-only WA, others indicate -- cgit v1.2.3 From 62c52eac1ad680fc68ef6d75955127dca46e2740 Mon Sep 17 00:00:00 2001 From: Anshuman Gupta Date: Fri, 14 Oct 2022 17:02:58 +0530 Subject: drm/i915/dgfx: Keep PCI autosuspend control 'on' by default on all dGPU DGFX platforms has lmem and cpu can access the lmem objects via mmap and i915 internal i915_gem_object_pin_map() for i915 own usages. Both of these methods has pre-requisite requirement to keep GFX PCI endpoint in D0 for a supported iomem transaction over PCI link. (Refer PCIe specs 5.3.1.4.1) Both DG1/DG2 have a known hardware bug that violates the PCIe specs and support the iomem read write transaction over PCIe bus despite endpoint is D3 state. Due to above H/W bug, we had never observed any issue with i915 runtime PM versus lmem access. But this issue becomes visible when PCIe gfx endpoint's upstream bridge enters to D3, at this point any lmem read/write access will be returned as unsupported request. But again this issue is not observed on every platform because it has been observed on few host machines DG1/DG2 endpoint's upstream bridge does not bind with pcieport driver. which really disables the PCIe power savings and leaves the bridge at D0 state. We need a unique interface to read/write from lmem with runtime PM wakeref protection something similar to intel_uncore_{read, write}, keep autosuspend control to 'on' on all discrete platforms, until we have a unique interface to read/write from lmem. This just change the default autosuspend setting of i915 on dGPU, user can still change it to 'auto'. v2: - Modified the commit message and subject with more information. - Changed the Fixes tag to LMEM support commit. [Joonas] - Changed !HAS_LMEM() Cond to !IS_DGFX(). [Rodrigo] Fixes: b908be543e44 ("drm/i915: support creating LMEM objects") Suggested-by: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Signed-off-by: Anshuman Gupta Link: https://patchwork.freedesktop.org/patch/msgid/20221014113258.1284226-1-anshuman.gupta@intel.com (cherry picked from commit 66eb93e71a7a6695b7c5eb682e3ca1c980cf9d58) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_runtime_pm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 6ed5786bcd29..744cca507946 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -591,8 +591,15 @@ void intel_runtime_pm_enable(struct intel_runtime_pm *rpm) pm_runtime_use_autosuspend(kdev); } - /* Enable by default */ - pm_runtime_allow(kdev); + /* + * FIXME: Temp hammer to keep autosupend disable on lmem supported platforms. + * As per PCIe specs 5.3.1.4.1, all iomem read write request over a PCIe + * function will be unsupported in case PCIe endpoint function is in D3. + * Let's keep i915 autosuspend control 'on' till we fix all known issue + * with lmem access in D3. + */ + if (!IS_DGFX(i915)) + pm_runtime_allow(kdev); /* * The core calls the driver load handler with an RPM reference held. -- cgit v1.2.3 From 63720a561b3c98199adf0c73e152807f15cc3b7f Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 11 Oct 2022 12:04:40 +0530 Subject: drm/i915/dp: Reset frl trained flag before restarting FRL training MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For cases where DP has HDMI2.1 sink and FRL Link issues are detected, reset the flag to state FRL trained status before restarting FRL training. Fixes: 9488a030ac91 ("drm/i915: Add support for enabling link status and recovery") Cc: Swati Sharma Cc: Ankit Nautiyal Cc: Uma Shankar (v2) Cc: Jani Nikula Signed-off-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221011063447.904649-2-ankit.k.nautiyal@intel.com (cherry picked from commit 47e1a59e60c688c5f95b67277202f05b7e84c189) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/display/intel_dp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c9be61d2348e..47419d162f30 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3957,6 +3957,8 @@ intel_dp_handle_hdmi_link_status_change(struct intel_dp *intel_dp) drm_dp_pcon_hdmi_frl_link_error_count(&intel_dp->aux, &intel_dp->attached_connector->base); + intel_dp->frl.is_trained = false; + /* Restart FRL training or fall back to TMDS mode */ intel_dp_check_frl_training(intel_dp); } -- cgit v1.2.3 From 36abde8d24ad740371422a7678ca92b06cc8a3d5 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Mon, 10 Oct 2022 19:30:09 +1300 Subject: platform/x86: asus-wmi: Add support for ROG X16 tablet mode Add quirk for ASUS ROG X16 Flow 2-in-1 to enable tablet mode with lid flip (all screen rotations). Signed-off-by: Luke D. Jones Link: https://lore.kernel.org/r/20221010063009.32293-1-luke@ljones.dev Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/asus-nb-wmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 613c45c9fbe3..c685a705b73d 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -464,6 +464,15 @@ static const struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_tablet_mode, }, + { + .callback = dmi_matched, + .ident = "ASUS ROG FLOW X16", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GV601R"), + }, + .driver_data = &quirk_asus_tablet_mode, + }, {}, }; -- cgit v1.2.3 From a10d50983f7befe85acf95ea7dbf6ba9187c2d70 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Wed, 19 Oct 2022 21:47:51 +0200 Subject: platform/x86: thinkpad_acpi: Fix reporting a non present second fan on some models thinkpad_acpi was reporting 2 fans on a ThinkPad T14s gen 1, even though the laptop has only 1 fan. The second, not present fan always reads 65535 (-1 in 16 bit signed), ignore fans which report 65535 to avoid reporting the non present fan. Signed-off-by: Jelle van der Waa Link: https://lore.kernel.org/r/20221019194751.5392-1-jvanderwaa@redhat.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/thinkpad_acpi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 6a823b850a77..20e5c043a8e8 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -263,6 +263,8 @@ enum tpacpi_hkey_event_t { #define TPACPI_DBG_BRGHT 0x0020 #define TPACPI_DBG_MIXER 0x0040 +#define FAN_NOT_PRESENT 65535 + #define strlencmp(a, b) (strncmp((a), (b), strlen(b))) @@ -8876,7 +8878,7 @@ static int __init fan_init(struct ibm_init_struct *iibm) /* Try and probe the 2nd fan */ tp_features.second_fan = 1; /* needed for get_speed to work */ res = fan2_get_speed(&speed); - if (res >= 0) { + if (res >= 0 && speed != FAN_NOT_PRESENT) { /* It responded - so let's assume it's there */ tp_features.second_fan = 1; tp_features.second_fan_ctl = 1; -- cgit v1.2.3 From 6960d133f66ecddcd3af2b1cbd0c7dcd104268b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Thu, 20 Oct 2022 09:53:10 +0200 Subject: atlantic: fix deadlock at aq_nic_stop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NIC is stopped with rtnl_lock held, and during the stop it cancels the 'service_task' work and free irqs. However, if CONFIG_MACSEC is set, rtnl_lock is acquired both from aq_nic_service_task and aq_linkstate_threaded_isr. Then a deadlock happens if aq_nic_stop tries to cancel/disable them when they've already started their execution. As the deadlock is caused by rtnl_lock, it causes many other processes to stall, not only atlantic related stuff. Fix it by introducing a mutex that protects each NIC's macsec related data, and locking it instead of the rtnl_lock from the service task and the threaded IRQ. Before this patch, all macsec data was protected with rtnl_lock, but maybe not all of it needs to be protected. With this new mutex, further efforts can be made to limit the protected data only to that which requires it. However, probably it doesn't worth it because all macsec's data accesses are infrequent, and almost all are done from macsec_ops or ethtool callbacks, called holding rtnl_lock, so macsec_mutex won't never be much contended. The issue appeared repeteadly attaching and deattaching the NIC to a bond interface. Doing that after this patch I cannot reproduce the bug. Fixes: 62c1c2e606f6 ("net: atlantic: MACSec offload skeleton") Reported-by: Li Liang Suggested-by: Andrew Lunn Signed-off-by: Íñigo Huguet Reviewed-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/aq_macsec.c | 96 ++++++++++++++++------ drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 2 + 2 files changed, 74 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c index 3d0e16791e1c..a0180811305d 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c @@ -1394,26 +1394,57 @@ static void aq_check_txsa_expiration(struct aq_nic_s *nic) egress_sa_threshold_expired); } +#define AQ_LOCKED_MDO_DEF(mdo) \ +static int aq_locked_mdo_##mdo(struct macsec_context *ctx) \ +{ \ + struct aq_nic_s *nic = netdev_priv(ctx->netdev); \ + int ret; \ + mutex_lock(&nic->macsec_mutex); \ + ret = aq_mdo_##mdo(ctx); \ + mutex_unlock(&nic->macsec_mutex); \ + return ret; \ +} + +AQ_LOCKED_MDO_DEF(dev_open) +AQ_LOCKED_MDO_DEF(dev_stop) +AQ_LOCKED_MDO_DEF(add_secy) +AQ_LOCKED_MDO_DEF(upd_secy) +AQ_LOCKED_MDO_DEF(del_secy) +AQ_LOCKED_MDO_DEF(add_rxsc) +AQ_LOCKED_MDO_DEF(upd_rxsc) +AQ_LOCKED_MDO_DEF(del_rxsc) +AQ_LOCKED_MDO_DEF(add_rxsa) +AQ_LOCKED_MDO_DEF(upd_rxsa) +AQ_LOCKED_MDO_DEF(del_rxsa) +AQ_LOCKED_MDO_DEF(add_txsa) +AQ_LOCKED_MDO_DEF(upd_txsa) +AQ_LOCKED_MDO_DEF(del_txsa) +AQ_LOCKED_MDO_DEF(get_dev_stats) +AQ_LOCKED_MDO_DEF(get_tx_sc_stats) +AQ_LOCKED_MDO_DEF(get_tx_sa_stats) +AQ_LOCKED_MDO_DEF(get_rx_sc_stats) +AQ_LOCKED_MDO_DEF(get_rx_sa_stats) + const struct macsec_ops aq_macsec_ops = { - .mdo_dev_open = aq_mdo_dev_open, - .mdo_dev_stop = aq_mdo_dev_stop, - .mdo_add_secy = aq_mdo_add_secy, - .mdo_upd_secy = aq_mdo_upd_secy, - .mdo_del_secy = aq_mdo_del_secy, - .mdo_add_rxsc = aq_mdo_add_rxsc, - .mdo_upd_rxsc = aq_mdo_upd_rxsc, - .mdo_del_rxsc = aq_mdo_del_rxsc, - .mdo_add_rxsa = aq_mdo_add_rxsa, - .mdo_upd_rxsa = aq_mdo_upd_rxsa, - .mdo_del_rxsa = aq_mdo_del_rxsa, - .mdo_add_txsa = aq_mdo_add_txsa, - .mdo_upd_txsa = aq_mdo_upd_txsa, - .mdo_del_txsa = aq_mdo_del_txsa, - .mdo_get_dev_stats = aq_mdo_get_dev_stats, - .mdo_get_tx_sc_stats = aq_mdo_get_tx_sc_stats, - .mdo_get_tx_sa_stats = aq_mdo_get_tx_sa_stats, - .mdo_get_rx_sc_stats = aq_mdo_get_rx_sc_stats, - .mdo_get_rx_sa_stats = aq_mdo_get_rx_sa_stats, + .mdo_dev_open = aq_locked_mdo_dev_open, + .mdo_dev_stop = aq_locked_mdo_dev_stop, + .mdo_add_secy = aq_locked_mdo_add_secy, + .mdo_upd_secy = aq_locked_mdo_upd_secy, + .mdo_del_secy = aq_locked_mdo_del_secy, + .mdo_add_rxsc = aq_locked_mdo_add_rxsc, + .mdo_upd_rxsc = aq_locked_mdo_upd_rxsc, + .mdo_del_rxsc = aq_locked_mdo_del_rxsc, + .mdo_add_rxsa = aq_locked_mdo_add_rxsa, + .mdo_upd_rxsa = aq_locked_mdo_upd_rxsa, + .mdo_del_rxsa = aq_locked_mdo_del_rxsa, + .mdo_add_txsa = aq_locked_mdo_add_txsa, + .mdo_upd_txsa = aq_locked_mdo_upd_txsa, + .mdo_del_txsa = aq_locked_mdo_del_txsa, + .mdo_get_dev_stats = aq_locked_mdo_get_dev_stats, + .mdo_get_tx_sc_stats = aq_locked_mdo_get_tx_sc_stats, + .mdo_get_tx_sa_stats = aq_locked_mdo_get_tx_sa_stats, + .mdo_get_rx_sc_stats = aq_locked_mdo_get_rx_sc_stats, + .mdo_get_rx_sa_stats = aq_locked_mdo_get_rx_sa_stats, }; int aq_macsec_init(struct aq_nic_s *nic) @@ -1435,6 +1466,7 @@ int aq_macsec_init(struct aq_nic_s *nic) nic->ndev->features |= NETIF_F_HW_MACSEC; nic->ndev->macsec_ops = &aq_macsec_ops; + mutex_init(&nic->macsec_mutex); return 0; } @@ -1458,7 +1490,7 @@ int aq_macsec_enable(struct aq_nic_s *nic) if (!nic->macsec_cfg) return 0; - rtnl_lock(); + mutex_lock(&nic->macsec_mutex); if (nic->aq_fw_ops->send_macsec_req) { struct macsec_cfg_request cfg = { 0 }; @@ -1507,7 +1539,7 @@ int aq_macsec_enable(struct aq_nic_s *nic) ret = aq_apply_macsec_cfg(nic); unlock: - rtnl_unlock(); + mutex_unlock(&nic->macsec_mutex); return ret; } @@ -1519,9 +1551,9 @@ void aq_macsec_work(struct aq_nic_s *nic) if (!netif_carrier_ok(nic->ndev)) return; - rtnl_lock(); + mutex_lock(&nic->macsec_mutex); aq_check_txsa_expiration(nic); - rtnl_unlock(); + mutex_unlock(&nic->macsec_mutex); } int aq_macsec_rx_sa_cnt(struct aq_nic_s *nic) @@ -1532,21 +1564,30 @@ int aq_macsec_rx_sa_cnt(struct aq_nic_s *nic) if (!cfg) return 0; + mutex_lock(&nic->macsec_mutex); + for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { if (!test_bit(i, &cfg->rxsc_idx_busy)) continue; cnt += hweight_long(cfg->aq_rxsc[i].rx_sa_idx_busy); } + mutex_unlock(&nic->macsec_mutex); return cnt; } int aq_macsec_tx_sc_cnt(struct aq_nic_s *nic) { + int cnt; + if (!nic->macsec_cfg) return 0; - return hweight_long(nic->macsec_cfg->txsc_idx_busy); + mutex_lock(&nic->macsec_mutex); + cnt = hweight_long(nic->macsec_cfg->txsc_idx_busy); + mutex_unlock(&nic->macsec_mutex); + + return cnt; } int aq_macsec_tx_sa_cnt(struct aq_nic_s *nic) @@ -1557,12 +1598,15 @@ int aq_macsec_tx_sa_cnt(struct aq_nic_s *nic) if (!cfg) return 0; + mutex_lock(&nic->macsec_mutex); + for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { if (!test_bit(i, &cfg->txsc_idx_busy)) continue; cnt += hweight_long(cfg->aq_txsc[i].tx_sa_idx_busy); } + mutex_unlock(&nic->macsec_mutex); return cnt; } @@ -1634,6 +1678,8 @@ u64 *aq_macsec_get_stats(struct aq_nic_s *nic, u64 *data) if (!cfg) return data; + mutex_lock(&nic->macsec_mutex); + aq_macsec_update_stats(nic); common_stats = &cfg->stats; @@ -1716,5 +1762,7 @@ u64 *aq_macsec_get_stats(struct aq_nic_s *nic, u64 *data) data += i; + mutex_unlock(&nic->macsec_mutex); + return data; } diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 935ba889bd9a..ad33f8586532 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -157,6 +157,8 @@ struct aq_nic_s { struct mutex fwreq_mutex; #if IS_ENABLED(CONFIG_MACSEC) struct aq_macsec_cfg *macsec_cfg; + /* mutex to protect data in macsec_cfg */ + struct mutex macsec_mutex; #endif /* PTP support */ struct aq_ptp_s *aq_ptp; -- cgit v1.2.3 From 0b6e6e149c136677f1cc859d4185b5a2db50ffbf Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 20 Oct 2022 06:37:49 -0500 Subject: platform/x86/amd: pmc: Read SMU version during suspend on Cezanne systems commit b0c07116c894 ("platform/x86: amd-pmc: Avoid reading SMU version at probe time") adjusted the behavior for amd-pmc to avoid reading the SMU version at startup but rather on first use to improve boot time. However the SMU version is also used to decide whether to place a timer based wakeup in the OS_HINT message. If the idlemask hasn't been read before this message was sent then the SMU version will not have been cached. Ensure the SMU version has been read before deciding whether or not to run this codepath. Cc: stable@vger.kernel.org # 6.0 Reported-by: You-Sheng Yang Tested-by: Anson Tsao Fixes: b0c07116c894 ("platform/x86: amd-pmc: Avoid reading SMU version at probe time") Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20221020113749.6621-2-mario.limonciello@amd.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/amd/pmc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index ce859b300712..96e790e639a2 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -663,6 +663,13 @@ static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg) struct rtc_time tm; int rc; + /* we haven't yet read SMU version */ + if (!pdev->major) { + rc = amd_pmc_get_smu_version(pdev); + if (rc) + return rc; + } + if (pdev->major < 64 || (pdev->major == 64 && pdev->minor < 53)) return 0; -- cgit v1.2.3 From f8127476930b98fc9e9aa5de0bbf9eeaf45db219 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Thu, 20 Oct 2022 08:28:28 +0300 Subject: net/mlx5e: Cleanup MACsec uninitialization routine The mlx5e_macsec_cleanup() routine has NULL pointer dereferencing if mlx5 device doesn't support MACsec (priv->macsec will be NULL). While at it delete comment line, assignment and extra blank lines, so fix everything in one patch. Fixes: 1f53da676439 ("net/mlx5e: Create advanced steering operation (ASO) object for MACsec") Reported-by: Dan Carpenter Signed-off-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 41970067917b..4331235b21ee 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -1846,25 +1846,16 @@ err_hash: void mlx5e_macsec_cleanup(struct mlx5e_priv *priv) { struct mlx5e_macsec *macsec = priv->macsec; - struct mlx5_core_dev *mdev = macsec->mdev; + struct mlx5_core_dev *mdev = priv->mdev; if (!macsec) return; mlx5_notifier_unregister(mdev, &macsec->nb); - mlx5e_macsec_fs_cleanup(macsec->macsec_fs); - - /* Cleanup workqueue */ destroy_workqueue(macsec->wq); - mlx5e_macsec_aso_cleanup(&macsec->aso, mdev); - - priv->macsec = NULL; - rhashtable_destroy(&macsec->sci_hash); - mutex_destroy(&macsec->lock); - kfree(macsec); } -- cgit v1.2.3 From ee24395f91b9cddccae5f6c11c37ee4ed78ff354 Mon Sep 17 00:00:00 2001 From: Henning Schild Date: Mon, 24 Oct 2022 11:20:27 +0200 Subject: leds: simatic-ipc-leds-gpio: fix incorrect LED to GPIO mapping For apollolake the mapping between LEDs and GPIO pins was off because of a refactoring when we introduced a new device model. In addition to the reordering the indices in the lookup table need to be updated as well. Fixes: a97126265dfe ("leds: simatic-ipc-leds-gpio: add new model 227G") Signed-off-by: Henning Schild Link: https://lore.kernel.org/r/20221024092027.4529-1-henning.schild@siemens.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/leds/simple/simatic-ipc-leds-gpio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio.c b/drivers/leds/simple/simatic-ipc-leds-gpio.c index b9eeb8702df0..07f0d79d604d 100644 --- a/drivers/leds/simple/simatic-ipc-leds-gpio.c +++ b/drivers/leds/simple/simatic-ipc-leds-gpio.c @@ -20,12 +20,12 @@ static struct gpiod_lookup_table *simatic_ipc_led_gpio_table; static struct gpiod_lookup_table simatic_ipc_led_gpio_table_127e = { .dev_id = "leds-gpio", .table = { - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 52, NULL, 1, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 53, NULL, 2, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 57, NULL, 3, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 58, NULL, 4, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 60, NULL, 5, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 51, NULL, 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 52, NULL, 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 53, NULL, 1, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 57, NULL, 2, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 58, NULL, 3, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 60, NULL, 4, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 51, NULL, 5, GPIO_ACTIVE_LOW), GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 56, NULL, 6, GPIO_ACTIVE_LOW), GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 59, NULL, 7, GPIO_ACTIVE_HIGH), }, -- cgit v1.2.3 From 555a68dd681b7437a2708001d465c85f6dfa6955 Mon Sep 17 00:00:00 2001 From: Gayatri Kammela Date: Mon, 12 Sep 2022 16:33:07 -0700 Subject: platform/x86/intel: pmc/core: Add Raptor Lake support to pmc core driver Add Raptor Lake client parts (both RPL and RPL_S) support to pmc core driver. Raptor Lake client parts reuse all the Alder Lake PCH IPs. Cc: Srinivas Pandruvada Cc: Andy Shevchenko Cc: David Box Acked-by: Rajneesh Bhardwaj Signed-off-by: Gayatri Kammela Link: https://lore.kernel.org/r/20220912233307.409954-2-gayatri.kammela@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/pmc/core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index a1fe1e0dcf4a..17ec5825d13d 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -1914,6 +1914,8 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, &tgl_reg_map), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_reg_map), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, &tgl_reg_map), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, &adl_reg_map), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, &adl_reg_map), {} }; -- cgit v1.2.3 From c99f0f7e68376dda5df8db7950cd6b67e73c6d3c Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Thu, 20 Oct 2022 11:50:41 -0400 Subject: net: fman: Use physical address for userspace interfaces Before 262f2b782e25 ("net: fman: Map the base address once"), the physical address of the MAC was exposed to userspace in two places: via sysfs and via SIOCGIFMAP. While this is not best practice, it is an external ABI which is in use by userspace software. The aforementioned commit inadvertently modified these addresses and made them virtual. This constitutes and ABI break. Additionally, it leaks the kernel's memory layout to userspace. Partially revert that commit, reintroducing the resource back into struct mac_device, while keeping the intended changes (the rework of the address mapping). Fixes: 262f2b782e25 ("net: fman: Map the base address once") Reported-by: Geert Uytterhoeven Signed-off-by: Sean Anderson Acked-by: Madalin Bucur Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 4 ++-- drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c | 2 +- drivers/net/ethernet/freescale/fman/mac.c | 12 ++++++------ drivers/net/ethernet/freescale/fman/mac.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 31cfa121333d..fc68a32ce2f7 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -221,8 +221,8 @@ static int dpaa_netdev_init(struct net_device *net_dev, net_dev->netdev_ops = dpaa_ops; mac_addr = mac_dev->addr; - net_dev->mem_start = (unsigned long)mac_dev->vaddr; - net_dev->mem_end = (unsigned long)mac_dev->vaddr_end; + net_dev->mem_start = (unsigned long)priv->mac_dev->res->start; + net_dev->mem_end = (unsigned long)priv->mac_dev->res->end; net_dev->min_mtu = ETH_MIN_MTU; net_dev->max_mtu = dpaa_get_max_mtu(); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c index 258eb6c8f4c0..4fee74c024bd 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c @@ -18,7 +18,7 @@ static ssize_t dpaa_eth_show_addr(struct device *dev, if (mac_dev) return sprintf(buf, "%llx", - (unsigned long long)mac_dev->vaddr); + (unsigned long long)mac_dev->res->start); else return sprintf(buf, "none"); } diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index 7b7526fd7da3..65df308bad97 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -279,7 +279,6 @@ static int mac_probe(struct platform_device *_of_dev) struct device_node *mac_node, *dev_node; struct mac_device *mac_dev; struct platform_device *of_dev; - struct resource *res; struct mac_priv_s *priv; struct fman_mac_params params; u32 val; @@ -338,24 +337,25 @@ static int mac_probe(struct platform_device *_of_dev) of_node_put(dev_node); /* Get the address of the memory mapped registers */ - res = platform_get_mem_or_io(_of_dev, 0); - if (!res) { + mac_dev->res = platform_get_mem_or_io(_of_dev, 0); + if (!mac_dev->res) { dev_err(dev, "could not get registers\n"); return -EINVAL; } - err = devm_request_resource(dev, fman_get_mem_region(priv->fman), res); + err = devm_request_resource(dev, fman_get_mem_region(priv->fman), + mac_dev->res); if (err) { dev_err_probe(dev, err, "could not request resource\n"); return err; } - mac_dev->vaddr = devm_ioremap(dev, res->start, resource_size(res)); + mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start, + resource_size(mac_dev->res)); if (!mac_dev->vaddr) { dev_err(dev, "devm_ioremap() failed\n"); return -EIO; } - mac_dev->vaddr_end = mac_dev->vaddr + resource_size(res); if (!of_device_is_available(mac_node)) return -ENODEV; diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h index b95d384271bd..13b69ca5f00c 100644 --- a/drivers/net/ethernet/freescale/fman/mac.h +++ b/drivers/net/ethernet/freescale/fman/mac.h @@ -20,8 +20,8 @@ struct mac_priv_s; struct mac_device { void __iomem *vaddr; - void __iomem *vaddr_end; struct device *dev; + struct resource *res; u8 addr[ETH_ALEN]; struct fman_port *port[2]; u32 if_support; -- cgit v1.2.3 From b75927cff13e0b3b652a12da7eb9a012911799e8 Mon Sep 17 00:00:00 2001 From: Michael Margolin Date: Thu, 20 Oct 2022 18:19:49 +0300 Subject: RDMA/efa: Add EFA 0xefa2 PCI ID Add support for 0xefa2 devices. Reviewed-by: Firas Jahjah Reviewed-by: Yossi Leybovich Signed-off-by: Michael Margolin Link: https://lore.kernel.org/r/20221020151949.1768-1-mrgolin@amazon.com Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/efa/efa_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/efa/efa_main.c b/drivers/infiniband/hw/efa/efa_main.c index 94b94cca4870..15ee92081118 100644 --- a/drivers/infiniband/hw/efa/efa_main.c +++ b/drivers/infiniband/hw/efa/efa_main.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause /* - * Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All rights reserved. + * Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All rights reserved. */ #include @@ -14,10 +14,12 @@ #define PCI_DEV_ID_EFA0_VF 0xefa0 #define PCI_DEV_ID_EFA1_VF 0xefa1 +#define PCI_DEV_ID_EFA2_VF 0xefa2 static const struct pci_device_id efa_pci_tbl[] = { { PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA0_VF) }, { PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA1_VF) }, + { PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA2_VF) }, { } }; -- cgit v1.2.3 From 195583504be28df5d608a4677dd796117aea875f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 18 Oct 2022 20:35:13 +0200 Subject: spi: stm32: Print summary 'callbacks suppressed' message The original fix "spi: stm32: Rate-limit the 'Communication suspended' message" still leads to "stm32h7_spi_irq_thread: 1696 callbacks suppressed" spew in the kernel log. Since this 'Communication suspended' message is a debug print, add RATELIMIT_MSG_ON_RELEASE flag to inhibit the "callbacks suspended" part during normal operation and only print summary at the end. Fixes: ea8be08cc9358 ("spi: stm32: Rate-limit the 'Communication suspended' message") Signed-off-by: Marek Vasut Link: https://lore.kernel.org/r/20221018183513.206706-1-marex@denx.de Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 6fe617b445a5..3c2fa2e2f94a 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -886,6 +886,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL * 10, 1); + ratelimit_set_flags(&rs, RATELIMIT_MSG_ON_RELEASE); if (__ratelimit(&rs)) dev_dbg_ratelimited(spi->dev, "Communication suspended\n"); if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) -- cgit v1.2.3 From 9e272ed69ad6f6952fafd0599d6993575512408e Mon Sep 17 00:00:00 2001 From: Yangyang Li Date: Mon, 24 Oct 2022 16:38:13 +0800 Subject: RDMA/hns: Disable local invalidate operation When function reset and local invalidate are mixed, HNS RoCEE may hang. Before introducing the cause of the problem, two hardware internal concepts need to be introduced: 1. Execution queue: The queue of hardware execution instructions, function reset and local invalidate are queued for execution in this queue. 2.Local queue: A queue that stores local operation instructions. The instructions in the local queue will be sent to the execution queue for execution. The instructions in the local queue will not be removed until the execution is completed. The reason for the problem is as follows: 1. There is a function reset instruction in the execution queue, which is currently being executed. A necessary condition for the successful execution of function reset is: the hardware pipeline needs to empty the instructions that were not completed before; 2. A local invalidate instruction at the head of the local queue is sent to the execution queue. Now there are two instructions in the execution queue, the first is the function reset instruction, and the second is the local invalidate instruction, which will be executed in se quence; 3. The user has issued many local invalidate operations, causing the local queue to be filled up. 4. The user still has a new local operation command and is queuing to enter the local queue. But the local queue is full and cannot receive new instructions, this instruction is temporarily stored at the hardware pipeline. 5. The function reset has been waiting for the instruction before the hardware pipeline stage is drained. The hardware pipeline stage also caches a local invalidate instruction, so the function reset cannot be completed, and the instructions after it cannot be executed. These factors together cause the execution logic deadlock of the hardware, and the consequence is that RoCEE will not have any response. Considering that the local operation command may potentially cause RoCEE to hang, this feature is no longer supported. Fixes: e93df0108579 ("RDMA/hns: Support local invalidate for hip08 in kernel space") Signed-off-by: Yangyang Li Signed-off-by: Wenpeng Liang Signed-off-by: Haoyue Xu Link: https://lore.kernel.org/r/20221024083814.1089722-2-xuhaoyue1@hisilicon.com Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 11 ----------- drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 -- 2 files changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 1ead35fb031b..7f5a4769cee0 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -118,7 +118,6 @@ static const u32 hns_roce_op_code[] = { HR_OPC_MAP(ATOMIC_CMP_AND_SWP, ATOM_CMP_AND_SWAP), HR_OPC_MAP(ATOMIC_FETCH_AND_ADD, ATOM_FETCH_AND_ADD), HR_OPC_MAP(SEND_WITH_INV, SEND_WITH_INV), - HR_OPC_MAP(LOCAL_INV, LOCAL_INV), HR_OPC_MAP(MASKED_ATOMIC_CMP_AND_SWP, ATOM_MSK_CMP_AND_SWAP), HR_OPC_MAP(MASKED_ATOMIC_FETCH_AND_ADD, ATOM_MSK_FETCH_AND_ADD), HR_OPC_MAP(REG_MR, FAST_REG_PMR), @@ -559,9 +558,6 @@ static int set_rc_opcode(struct hns_roce_dev *hr_dev, else ret = -EOPNOTSUPP; break; - case IB_WR_LOCAL_INV: - hr_reg_enable(rc_sq_wqe, RC_SEND_WQE_SO); - fallthrough; case IB_WR_SEND_WITH_INV: rc_sq_wqe->inv_key = cpu_to_le32(wr->ex.invalidate_rkey); break; @@ -3222,7 +3218,6 @@ static int hns_roce_v2_write_mtpt(struct hns_roce_dev *hr_dev, hr_reg_write(mpt_entry, MPT_ST, V2_MPT_ST_VALID); hr_reg_write(mpt_entry, MPT_PD, mr->pd); - hr_reg_enable(mpt_entry, MPT_L_INV_EN); hr_reg_write_bool(mpt_entry, MPT_BIND_EN, mr->access & IB_ACCESS_MW_BIND); @@ -3313,7 +3308,6 @@ static int hns_roce_v2_frmr_write_mtpt(struct hns_roce_dev *hr_dev, hr_reg_enable(mpt_entry, MPT_RA_EN); hr_reg_enable(mpt_entry, MPT_R_INV_EN); - hr_reg_enable(mpt_entry, MPT_L_INV_EN); hr_reg_enable(mpt_entry, MPT_FRE); hr_reg_clear(mpt_entry, MPT_MR_MW); @@ -3345,7 +3339,6 @@ static int hns_roce_v2_mw_write_mtpt(void *mb_buf, struct hns_roce_mw *mw) hr_reg_write(mpt_entry, MPT_PD, mw->pdn); hr_reg_enable(mpt_entry, MPT_R_INV_EN); - hr_reg_enable(mpt_entry, MPT_L_INV_EN); hr_reg_enable(mpt_entry, MPT_LW_EN); hr_reg_enable(mpt_entry, MPT_MR_MW); @@ -3794,7 +3787,6 @@ static const u32 wc_send_op_map[] = { HR_WC_OP_MAP(RDMA_READ, RDMA_READ), HR_WC_OP_MAP(RDMA_WRITE, RDMA_WRITE), HR_WC_OP_MAP(RDMA_WRITE_WITH_IMM, RDMA_WRITE), - HR_WC_OP_MAP(LOCAL_INV, LOCAL_INV), HR_WC_OP_MAP(ATOM_CMP_AND_SWAP, COMP_SWAP), HR_WC_OP_MAP(ATOM_FETCH_AND_ADD, FETCH_ADD), HR_WC_OP_MAP(ATOM_MSK_CMP_AND_SWAP, MASKED_COMP_SWAP), @@ -3844,9 +3836,6 @@ static void fill_send_wc(struct ib_wc *wc, struct hns_roce_v2_cqe *cqe) case HNS_ROCE_V2_WQE_OP_RDMA_WRITE_WITH_IMM: wc->wc_flags |= IB_WC_WITH_IMM; break; - case HNS_ROCE_V2_WQE_OP_LOCAL_INV: - wc->wc_flags |= IB_WC_WITH_INVALIDATE; - break; case HNS_ROCE_V2_WQE_OP_ATOM_CMP_AND_SWAP: case HNS_ROCE_V2_WQE_OP_ATOM_FETCH_AND_ADD: case HNS_ROCE_V2_WQE_OP_ATOM_MSK_CMP_AND_SWAP: diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index b11579027e82..c7bf2d52c1cd 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h @@ -179,7 +179,6 @@ enum { HNS_ROCE_V2_WQE_OP_ATOM_MSK_CMP_AND_SWAP = 0x8, HNS_ROCE_V2_WQE_OP_ATOM_MSK_FETCH_AND_ADD = 0x9, HNS_ROCE_V2_WQE_OP_FAST_REG_PMR = 0xa, - HNS_ROCE_V2_WQE_OP_LOCAL_INV = 0xb, HNS_ROCE_V2_WQE_OP_BIND_MW = 0xc, HNS_ROCE_V2_WQE_OP_MASK = 0x1f, }; @@ -915,7 +914,6 @@ struct hns_roce_v2_rc_send_wqe { #define RC_SEND_WQE_OWNER RC_SEND_WQE_FIELD_LOC(7, 7) #define RC_SEND_WQE_CQE RC_SEND_WQE_FIELD_LOC(8, 8) #define RC_SEND_WQE_FENCE RC_SEND_WQE_FIELD_LOC(9, 9) -#define RC_SEND_WQE_SO RC_SEND_WQE_FIELD_LOC(10, 10) #define RC_SEND_WQE_SE RC_SEND_WQE_FIELD_LOC(11, 11) #define RC_SEND_WQE_INLINE RC_SEND_WQE_FIELD_LOC(12, 12) #define RC_SEND_WQE_WQE_INDEX RC_SEND_WQE_FIELD_LOC(30, 15) -- cgit v1.2.3 From 12bcaf87d8b66d8cd812479c8a6349dcb245375c Mon Sep 17 00:00:00 2001 From: Yixing Liu Date: Mon, 24 Oct 2022 16:38:14 +0800 Subject: RDMA/hns: Fix NULL pointer problem in free_mr_init() Lock grab occurs in a concurrent scenario, resulting in stepping on a NULL pointer. It should be init mutex_init() first before use the lock. Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 Call trace: __mutex_lock.constprop.0+0xd0/0x5c0 __mutex_lock_slowpath+0x1c/0x2c mutex_lock+0x44/0x50 free_mr_send_cmd_to_hw+0x7c/0x1c0 [hns_roce_hw_v2] hns_roce_v2_dereg_mr+0x30/0x40 [hns_roce_hw_v2] hns_roce_dereg_mr+0x4c/0x130 [hns_roce_hw_v2] ib_dereg_mr_user+0x54/0x124 uverbs_free_mr+0x24/0x30 destroy_hw_idr_uobject+0x38/0x74 uverbs_destroy_uobject+0x48/0x1c4 uobj_destroy+0x74/0xcc ib_uverbs_cmd_verbs+0x368/0xbb0 ib_uverbs_ioctl+0xec/0x1a4 __arm64_sys_ioctl+0xb4/0x100 invoke_syscall+0x50/0x120 el0_svc_common.constprop.0+0x58/0x190 do_el0_svc+0x30/0x90 el0_svc+0x2c/0xb4 el0t_64_sync_handler+0x1a4/0x1b0 el0t_64_sync+0x19c/0x1a0 Fixes: 70f92521584f ("RDMA/hns: Use the reserved loopback QPs to free MR before destroying MPT") Signed-off-by: Yixing Liu Signed-off-by: Haoyue Xu Link: https://lore.kernel.org/r/20221024083814.1089722-3-xuhaoyue1@hisilicon.com Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 7f5a4769cee0..1435fe2ea176 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -2801,8 +2801,12 @@ static int free_mr_modify_qp(struct hns_roce_dev *hr_dev) static int free_mr_init(struct hns_roce_dev *hr_dev) { + struct hns_roce_v2_priv *priv = hr_dev->priv; + struct hns_roce_v2_free_mr *free_mr = &priv->free_mr; int ret; + mutex_init(&free_mr->mutex); + ret = free_mr_alloc_res(hr_dev); if (ret) return ret; -- cgit v1.2.3 From 9c1eaa27ec599fcc25ed4970c0b73c247d147a2b Mon Sep 17 00:00:00 2001 From: Zhang Changzhong Date: Fri, 21 Oct 2022 09:32:24 +0800 Subject: net: lantiq_etop: don't free skb when returning NETDEV_TX_BUSY The ndo_start_xmit() method must not free skb when returning NETDEV_TX_BUSY, since caller is going to requeue freed skb. Fixes: 504d4721ee8e ("MIPS: Lantiq: Add ethernet driver") Signed-off-by: Zhang Changzhong Signed-off-by: David S. Miller --- drivers/net/ethernet/lantiq_etop.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 59aab4086dcc..f5961bdcc480 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -485,7 +485,6 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev) len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) { - dev_kfree_skb_any(skb); netdev_err(dev, "tx ring full\n"); netif_tx_stop_queue(txq); return NETDEV_TX_BUSY; -- cgit v1.2.3 From e9cf4d9b9a6fdb1df6401a59f5ac5d24006bfeae Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 24 Oct 2022 17:12:10 +0300 Subject: ACPI: video: Fix missing native backlight on Chromebooks Chromebooks don't have backlight in ACPI table, they suppose to use native backlight in this case. Check presence of the CrOS embedded controller ACPI device and prefer the native backlight if EC found. Suggested-by: Hans de Goede Fixes: 2600bfa3df99 ("ACPI: video: Add acpi_video_backlight_use_native() helper") Signed-off-by: Dmitry Osipenko Reviewed-by: Hans de Goede Acked-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20221024141210.67784-1-dmitry.osipenko@collabora.com Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 0d9064a9804c..9cd8797d12bb 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -668,6 +668,11 @@ static const struct dmi_system_id video_detect_dmi_table[] = { { }, }; +static bool google_cros_ec_present(void) +{ + return acpi_dev_found("GOOG0004"); +} + /* * Determine which type of backlight interface to use on this system, * First check cmdline, then dmi quirks, then do autodetect. @@ -730,6 +735,13 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) return acpi_backlight_video; } + /* + * Chromebooks that don't have backlight handle in ACPI table + * are supposed to use native backlight if it's available. + */ + if (google_cros_ec_present() && native_available) + return acpi_backlight_native; + /* No ACPI video (old hw), use vendor specific fw methods. */ return acpi_backlight_vendor; } -- cgit v1.2.3 From 028822b714bd3a159d65416c53f1549345b53d9e Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Thu, 20 Oct 2022 15:01:23 +0200 Subject: mmc: core: Fix WRITE_ZEROES CQE handling WRITE_ZEROES requests use TRIM, so mark them as needing to be issued synchronously even when a CQE is being used. Without this, mmc_blk_mq_issue_rq() triggers a WARN_ON_ONCE() and fails the request since we don't have any handling for issuing this asynchronously. Fixes: f7b6fc327327 ("mmc: core: Support zeroout using TRIM for eMMC") Reported-by: Jon Hunter Tested-by: Jon Hunter Signed-off-by: Vincent Whitchurch Reviewed-by: Avri Altman Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221020130123.4033218-1-vincent.whitchurch@axis.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/queue.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 86be55d7cf55..b396e3900717 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -48,6 +48,7 @@ static enum mmc_issue_type mmc_cqe_issue_type(struct mmc_host *host, case REQ_OP_DRV_OUT: case REQ_OP_DISCARD: case REQ_OP_SECURE_ERASE: + case REQ_OP_WRITE_ZEROES: return MMC_ISSUE_SYNC; case REQ_OP_FLUSH: return mmc_cqe_can_dcmd(host) ? MMC_ISSUE_DCMD : MMC_ISSUE_SYNC; -- cgit v1.2.3 From efa17e90e1711bdb084e3954fa44afb6647331c0 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sat, 22 Oct 2022 15:42:12 +0800 Subject: iio: trigger: sysfs: fix possible memory leak in iio_sysfs_trig_init() dev_set_name() allocates memory for name, it need be freed when device_add() fails, call put_device() to give up the reference that hold in device_initialize(), so that it can be freed in kobject_cleanup() when the refcount hit to 0. Fault injection test can trigger this: unreferenced object 0xffff8e8340a7b4c0 (size 32): comm "modprobe", pid 243, jiffies 4294678145 (age 48.845s) hex dump (first 32 bytes): 69 69 6f 5f 73 79 73 66 73 5f 74 72 69 67 67 65 iio_sysfs_trigge 72 00 a7 40 83 8e ff ff 00 86 13 c4 f6 ee ff ff r..@............ backtrace: [<0000000074999de8>] __kmem_cache_alloc_node+0x1e9/0x360 [<00000000497fd30b>] __kmalloc_node_track_caller+0x44/0x1a0 [<000000003636c520>] kstrdup+0x2d/0x60 [<0000000032f84da2>] kobject_set_name_vargs+0x1e/0x90 [<0000000092efe493>] dev_set_name+0x4e/0x70 Fixes: 1f785681a870 ("staging:iio:trigger sysfs userspace trigger rework.") Signed-off-by: Yang Yingliang Cc: Link: https://lore.kernel.org/r/20221022074212.1386424-1-yangyingliang@huawei.com Signed-off-by: Jonathan Cameron --- drivers/iio/trigger/iio-trig-sysfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c index d6c5e9644738..6b05eed41612 100644 --- a/drivers/iio/trigger/iio-trig-sysfs.c +++ b/drivers/iio/trigger/iio-trig-sysfs.c @@ -203,9 +203,13 @@ static int iio_sysfs_trigger_remove(int id) static int __init iio_sysfs_trig_init(void) { + int ret; device_initialize(&iio_sysfs_trig_dev); dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger"); - return device_add(&iio_sysfs_trig_dev); + ret = device_add(&iio_sysfs_trig_dev); + if (ret) + put_device(&iio_sysfs_trig_dev); + return ret; } module_init(iio_sysfs_trig_init); -- cgit v1.2.3 From 207777dc306a732cff76ab63bf19a7e0851410b3 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 20 Oct 2022 13:27:05 +0300 Subject: iio: adc: at91-sama5d2_adc: get rid of 5 degrees Celsius adjustment On SAMA7G5 final chip version there is no need for 5 degrees Celsius adjustment when computing junction temperature, thus, remove it. Fixes: 5ab38b81895c ("iio: adc: at91-sama5d2_adc: add support for temperature sensor") Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20221020102705.3639204-1-claudiu.beznea@microchip.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 33e251552214..870f4cb60923 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -2307,11 +2307,9 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st, clb->p6 = buf[AT91_ADC_TS_CLB_IDX_P6]; /* - * We prepare here the conversion to milli and also add constant - * factor (5 degrees Celsius) to p1 here to avoid doing it on - * hotpath. + * We prepare here the conversion to milli to avoid doing it on hotpath. */ - clb->p1 = clb->p1 * 1000 + 5000; + clb->p1 = clb->p1 * 1000; free_buf: kfree(buf); -- cgit v1.2.3 From 835bed1b83952bdbbe874f8ee41d665d52e991de Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 24 Oct 2022 18:29:01 +0200 Subject: fbdev: sisfb: use explicitly signed char With char becoming unsigned by default, and with `char` alone being ambiguous and based on architecture, signed chars need to be marked explicitly as such. This fixes warnings like: drivers/video/fbdev/sis/init301.c:3549 SiS_GetCRT2Data301() warn: 'SiS_Pr->SiS_EModeIDTable[ModeIdIndex]->ROMMODEIDX661' is unsigned Cc: Thomas Winischhofer Cc: Greg Kroah-Hartman Cc: Helge Deller Cc: linux-usb@vger.kernel.org Cc: linux-fbdev@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Jason A. Donenfeld Signed-off-by: Helge Deller --- drivers/usb/misc/sisusbvga/sisusb_struct.h | 2 +- drivers/video/fbdev/sis/vstruct.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h index 3df64d2a9d43..a86032a26d36 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_struct.h +++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h @@ -91,7 +91,7 @@ struct SiS_Ext { unsigned char VB_ExtTVYFilterIndex; unsigned char VB_ExtTVYFilterIndexROM661; unsigned char REFindex; - char ROMMODEIDX661; + signed char ROMMODEIDX661; }; struct SiS_Ext2 { diff --git a/drivers/video/fbdev/sis/vstruct.h b/drivers/video/fbdev/sis/vstruct.h index ea94d214dcff..d7a14e63ba5a 100644 --- a/drivers/video/fbdev/sis/vstruct.h +++ b/drivers/video/fbdev/sis/vstruct.h @@ -148,7 +148,7 @@ struct SiS_Ext { unsigned char VB_ExtTVYFilterIndex; unsigned char VB_ExtTVYFilterIndexROM661; unsigned char REFindex; - char ROMMODEIDX661; + signed char ROMMODEIDX661; }; struct SiS_Ext2 { -- cgit v1.2.3 From 20293269d81779a0d0c0865f5877b240c3335c97 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 30 Sep 2022 10:43:08 +0530 Subject: drm/amdgpu: Remove ATC L2 access for MMHUB 2.1.x MMHUB 2.1.x versions don't have ATCL2. Remove accesses to ATCL2 registers. Since they are non-existing registers, read access will cause a 'Completer Abort' and gets reported when AER is enabled with the below patch. Tagging with the patch so that this is backported along with it. v2: squash in uninitialized warning fix (Nathan Chancellor) Fixes: 8795e182b02d ("PCI/portdrv: Don't disable AER reporting in get_port_device_capability()") Signed-off-by: Lijo Lazar Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 4d304f22889e..998b5d17b271 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -32,8 +32,6 @@ #include "gc/gc_10_1_0_offset.h" #include "soc15_common.h" -#define mmMM_ATC_L2_MISC_CG_Sienna_Cichlid 0x064d -#define mmMM_ATC_L2_MISC_CG_Sienna_Cichlid_BASE_IDX 0 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid 0x0070 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid_BASE_IDX 0 @@ -574,7 +572,6 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): - def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid); def1 = data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid); break; default: @@ -608,8 +605,6 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): - if (def != data) - WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid, data); if (def1 != data1) WREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid, data1); break; @@ -634,8 +629,8 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): - def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid); - break; + /* There is no ATCL2 in MMHUB for 2.1.x */ + return; default: def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG); break; @@ -646,18 +641,8 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade else data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK; - if (def != data) { - switch (adev->ip_versions[MMHUB_HWIP][0]) { - case IP_VERSION(2, 1, 0): - case IP_VERSION(2, 1, 1): - case IP_VERSION(2, 1, 2): - WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid, data); - break; - default: - WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data); - break; - } - } + if (def != data) + WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data); } static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, @@ -695,7 +680,10 @@ static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags) case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): - data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid); + /* There is no ATCL2 in MMHUB for 2.1.x. Keep the status + * based on DAGB + */ + data = MM_ATC_L2_MISC_CG__ENABLE_MASK; data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid); break; default: -- cgit v1.2.3 From 7b5a4d7b9e2952a15c8d2b2391dfacd7ce841a1a Mon Sep 17 00:00:00 2001 From: Rafael Mendonca Date: Mon, 17 Oct 2022 22:27:50 -0300 Subject: drm/amdkfd: Fix memory leak in kfd_mem_dmamap_userptr() If the number of pages from the userptr BO differs from the SG BO then the allocated memory for the SG table doesn't get freed before returning -EINVAL, which may lead to a memory leak in some error paths. Fix this by checking the number of pages before allocating memory for the SG table. Fixes: 264fb4d332f5 ("drm/amdgpu: Add multi-GPU DMA mapping helpers") Signed-off-by: Rafael Mendonca Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 8ad01e1ee4c6..da9d475d7ef2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -510,13 +510,13 @@ kfd_mem_dmamap_userptr(struct kgd_mem *mem, struct ttm_tt *ttm = bo->tbo.ttm; int ret; + if (WARN_ON(ttm->num_pages != src_ttm->num_pages)) + return -EINVAL; + ttm->sg = kmalloc(sizeof(*ttm->sg), GFP_KERNEL); if (unlikely(!ttm->sg)) return -ENOMEM; - if (WARN_ON(ttm->num_pages != src_ttm->num_pages)) - return -EINVAL; - /* Same sequence as in amdgpu_ttm_tt_pin_userptr */ ret = sg_alloc_table_from_pages(ttm->sg, src_ttm->pages, ttm->num_pages, 0, -- cgit v1.2.3 From 03ce7b387e8b0f4a1dc97a878545bdf7c7f23251 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:15 -0400 Subject: drm/amd/display: Check if link state is valid The link state is set to false if there is no link and local sink. Even though the stream state may not change, it is desirable to commit the new stream when HPD goes low to high. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 997ab031f816..7b576bd24cb5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1500,6 +1500,8 @@ static bool context_changed( for (i = 0; i < dc->current_state->stream_count; i++) { if (dc->current_state->streams[i] != context->streams[i]) return true; + if (!context->streams[i]->link->link_state_valid) + return true; } return false; -- cgit v1.2.3 From 10fdb0a11c555e0d6f7698d2874581d06e99ee71 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:16 -0400 Subject: drm/amd/display: Rework context change check Context change is all about streams; for this reason, this commit renames context_changed to streams_changed. Additionally, to make this function more flexible, this commit changes the function signature to receive the stream array and the stream count as a parameter. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7b576bd24cb5..9219d1efde2a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1488,19 +1488,19 @@ static void program_timing_sync( } } -static bool context_changed( - struct dc *dc, - struct dc_state *context) +static bool streams_changed(struct dc *dc, + struct dc_stream_state *streams[], + uint8_t stream_count) { uint8_t i; - if (context->stream_count != dc->current_state->stream_count) + if (stream_count != dc->current_state->stream_count) return true; for (i = 0; i < dc->current_state->stream_count; i++) { - if (dc->current_state->streams[i] != context->streams[i]) + if (dc->current_state->streams[i] != streams[i]) return true; - if (!context->streams[i]->link->link_state_valid) + if (!streams[i]->link->link_state_valid) return true; } @@ -1895,7 +1895,7 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context) enum dc_status result = DC_ERROR_UNEXPECTED; int i; - if (!context_changed(dc, context)) + if (!streams_changed(dc, context->streams, context->stream_count)) return DC_OK; DC_LOG_DC("%s: %d streams\n", -- cgit v1.2.3 From 7b36f4d18e3e4941d12fe027ad6ad6123c257027 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:17 -0400 Subject: drm/amd/display: Enable new commit sequence only for DCN32x Change commit sequence will impact all ASICs. It is prudent to run this update in small steps to keep issues under control and avoid any potential regression. With this idea in mind, this commit is preparation work for the complete transition to the new commit sequence. To maintain this change manageable across multiple ASICs, this commit adds a new function named dc_commit_streams which is a copy of the dc_commit_state with some minor changes. Finally, inside the dc_commit_state, we check if we are using DCN32x or above and enable the new sequence only for those devices. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 46 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 13 +++------ 2 files changed, 50 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9219d1efde2a..5d9e9e8f87d3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1890,11 +1890,57 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c return result; } +enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context) +{ + enum dc_status res = DC_OK; + int i; + + if (!streams_changed(dc, context->streams, context->stream_count)) + return res; + + DC_LOG_DC("%s: %d streams\n", + __func__, context->stream_count); + + for (i = 0; i < context->stream_count; i++) { + struct dc_stream_state *stream = context->streams[i]; + + dc_stream_log(dc, stream); + } + + /* + * Previous validation was perfomred with fast_validation = true and + * the full DML state required for hardware programming was skipped. + * + * Re-validate here to calculate these parameters / watermarks. + */ + res = dc_validate_global_state(dc, context, false); + if (res != DC_OK) { + DC_LOG_ERROR("DC commit global validation failure: %s (%d)", + dc_status_to_str(res), res); + return res; + } + + res = dc_commit_state_no_check(dc, context); + + return (res == DC_OK); +} + +/* TODO: When the transition to the new commit sequence is done, remove this + * function in favor of dc_commit_streams. */ bool dc_commit_state(struct dc *dc, struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; int i; + /* TODO: Since change commit sequence can have a huge impact, + * we decided to only enable it for DCN3x. However, as soon as + * we get more confident about this change we'll need to enable + * the new sequence for all ASICs. */ + if (dc->ctx->dce_version >= DCN_VERSION_3_2) { + result = dc_commit_streams(dc, context); + return result == DC_OK; + } + if (!streams_changed(dc, context->streams, context->stream_count)) return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bfc5474c0f4c..2e71781f155b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1321,15 +1321,10 @@ void dc_resource_state_destruct(struct dc_state *context); bool dc_resource_is_dsc_encoding_supported(const struct dc *dc); -/* - * TODO update to make it about validation sets - * Set up streams and links associated to drive sinks - * The streams parameter is an absolute set of all active streams. - * - * After this call: - * Phy, Encoder, Timing Generator are programmed and enabled. - * New streams are enabled with blank stream; no memory read. - */ +enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context); + +/* TODO: When the transition to the new commit sequence is done, remove this + * function in favor of dc_commit_streams. */ bool dc_commit_state(struct dc *dc, struct dc_state *context); struct dc_state *dc_create_state(struct dc *dc); -- cgit v1.2.3 From 0e986cea0347902b2c72b09c8fe9c0f30d7decb4 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:18 -0400 Subject: drm/amd/display: Copy DC context in the commit streams DC adds an instance of DML (which contains VBA) to each context, and multiple threads might write back to the global VBA resulting in data overwriting. To keep the consistency with other parts of the DC code, this commit changes dc_commit_streams to copy the current DC state, and as a result, it also changes the function signature to expect streams instead of a context. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 41 +++++++++++++++++++++++++------- drivers/gpu/drm/amd/display/dc/dc.h | 4 +++- 2 files changed, 36 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5d9e9e8f87d3..af81c2835738 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1890,23 +1890,44 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c return result; } -enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context) +/** + * dc_commit_streams - Commit current stream state + * + * @dc: DC object with the commit state to be configured in the hardware + * @streams: Array with a list of stream state + * @stream_count: Total of streams + * + * Function responsible for commit streams change to the hardware. + * + * Return: + * Return DC_OK if everything work as expected, otherwise, return a dc_status + * code. + */ +enum dc_status dc_commit_streams(struct dc *dc, + struct dc_stream_state *streams[], + uint8_t stream_count) { - enum dc_status res = DC_OK; int i; + struct dc_state *context; + enum dc_status res = DC_OK; - if (!streams_changed(dc, context->streams, context->stream_count)) + if (!streams_changed(dc, streams, stream_count)) return res; - DC_LOG_DC("%s: %d streams\n", - __func__, context->stream_count); + DC_LOG_DC("%s: %d streams\n", __func__, stream_count); - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + for (i = 0; i < stream_count; i++) { + struct dc_stream_state *stream = streams[i]; dc_stream_log(dc, stream); } + context = dc_create_state(dc); + if (!context) + goto context_alloc_fail; + + dc_resource_state_copy_construct_current(dc, context); + /* * Previous validation was perfomred with fast_validation = true and * the full DML state required for hardware programming was skipped. @@ -1922,6 +1943,10 @@ enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context) res = dc_commit_state_no_check(dc, context); +context_alloc_fail: + + DC_LOG_DC("%s Finished.\n", __func__); + return (res == DC_OK); } @@ -1937,7 +1962,7 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context) * we get more confident about this change we'll need to enable * the new sequence for all ASICs. */ if (dc->ctx->dce_version >= DCN_VERSION_3_2) { - result = dc_commit_streams(dc, context); + result = dc_commit_streams(dc, context->streams, context->stream_count); return result == DC_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2e71781f155b..6adecb62e534 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1321,7 +1321,9 @@ void dc_resource_state_destruct(struct dc_state *context); bool dc_resource_is_dsc_encoding_supported(const struct dc *dc); -enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context); +enum dc_status dc_commit_streams(struct dc *dc, + struct dc_stream_state *streams[], + uint8_t stream_count); /* TODO: When the transition to the new commit sequence is done, remove this * function in favor of dc_commit_streams. */ -- cgit v1.2.3 From f6ae69f49fcf697b6ffa93d58eb3746897f61cf8 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:19 -0400 Subject: drm/amd/display: Include surface of unaffected streams The commit stream function does not include surfaces of unaffected streams, which may lead to some blank screens during mode change in some edge cases. This commit adds surfaces of unaffected streams followed by kernel-doc for documenting some of the fields that participate in this change. v2: squash in kerneldoc warning fix (Alex) Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 15 +++++++++++++-- drivers/gpu/drm/amd/display/dc/dc_stream.h | 4 ++++ 3 files changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index af81c2835738..b904b03cf94e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1907,9 +1907,10 @@ enum dc_status dc_commit_streams(struct dc *dc, struct dc_stream_state *streams[], uint8_t stream_count) { - int i; + int i, j; struct dc_state *context; enum dc_status res = DC_OK; + struct dc_validation_set set[MAX_STREAMS] = {0}; if (!streams_changed(dc, streams, stream_count)) return res; @@ -1918,8 +1919,17 @@ enum dc_status dc_commit_streams(struct dc *dc, for (i = 0; i < stream_count; i++) { struct dc_stream_state *stream = streams[i]; + struct dc_stream_status *status = dc_stream_get_status(stream); dc_stream_log(dc, stream); + + set[i].stream = stream; + + if (status) { + set[i].plane_count = status->plane_count; + for (j = 0; j < status->plane_count; j++) + set[i].plane_states[j] = status->plane_states[j]; + } } context = dc_create_state(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6adecb62e534..836cdf5d4114 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1269,12 +1269,23 @@ void dc_post_update_surfaces_to_stream( #include "dc_stream.h" -/* - * Structure to store surface/stream associations for validation +/** + * struct dc_validation_set - Struct to store surface/stream associations for validation */ struct dc_validation_set { + /** + * @stream: Stream state properties + */ struct dc_stream_state *stream; + + /** + * @plane_state: Surface state + */ struct dc_plane_state *plane_states[MAX_SURFACES]; + + /** + * @plane_count: Total of active planes + */ uint8_t plane_count; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 9e6025c98db9..73dccd485895 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -41,6 +41,10 @@ struct timing_sync_info { struct dc_stream_status { int primary_otg_inst; int stream_enc_inst; + + /** + * @plane_count: Total of planes attached to a single stream + */ int plane_count; int audio_inst; struct timing_sync_info timing_sync_info; -- cgit v1.2.3 From 987b96eb860036ab79051fb271f7fbdc01c9daf5 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:20 -0400 Subject: drm/amd/display: Handle virtual hardware detect If virtual hardware is detected, there is no reason to run the full dc_commit_streams process, and DC can return true immediately. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b904b03cf94e..61b574b9e736 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1912,6 +1912,9 @@ enum dc_status dc_commit_streams(struct dc *dc, enum dc_status res = DC_OK; struct dc_validation_set set[MAX_STREAMS] = {0}; + if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW) + return res; + if (!streams_changed(dc, streams, stream_count)) return res; -- cgit v1.2.3 From a5e39ae27c3a305c6aafc0e423b0cb2c677facde Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:21 -0400 Subject: drm/amd/display: Add function for validate and update new stream DC stream can be seen as a representation of the DCN backend or the data struct that represents the center of the display pipeline. The front end (i.e., planes) is connected to the DC stream, and in its turn, streams are connected to the DC link. Due to this dynamic, DC must handle the following scenarios: 1. A stream is removed; 2. A new stream is created; 3. An unchanged stream had some updates on its planes. These combinations require that the new stream data struct become updated and has a valid global state. For handling multiple corner cases associated with stream operations, this commit introduces a function dedicated to manipulating stream changes and invokes the state validation function after that. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 219 +++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 6 + 3 files changed, 227 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 61b574b9e736..d568387c4bda 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1941,21 +1941,17 @@ enum dc_status dc_commit_streams(struct dc *dc, dc_resource_state_copy_construct_current(dc, context); - /* - * Previous validation was perfomred with fast_validation = true and - * the full DML state required for hardware programming was skipped. - * - * Re-validate here to calculate these parameters / watermarks. - */ - res = dc_validate_global_state(dc, context, false); + res = dc_validate_with_context(dc, set, stream_count, context, false); if (res != DC_OK) { - DC_LOG_ERROR("DC commit global validation failure: %s (%d)", - dc_status_to_str(res), res); - return res; + BREAK_TO_DEBUGGER(); + goto fail; } res = dc_commit_state_no_check(dc, context); +fail: + dc_release_state(context); + context_alloc_fail: DC_LOG_DC("%s Finished.\n", __func__); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fd8db482e56f..e001b138b2ac 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2593,15 +2593,226 @@ bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) return dc->res_pool->res_cap->num_dsc > 0; } +static bool planes_changed_for_existing_stream(struct dc_state *context, + struct dc_stream_state *stream, + const struct dc_validation_set set[], + int set_count) +{ + int i, j; + struct dc_stream_status *stream_status = NULL; + + for (i = 0; i < context->stream_count; i++) { + if (context->streams[i] == stream) { + stream_status = &context->stream_status[i]; + break; + } + } + + if (!stream_status) + ASSERT(0); + + for (i = 0; i < set_count; i++) + if (set[i].stream == stream) + break; + + if (i == set_count) + ASSERT(0); + + if (set[i].plane_count != stream_status->plane_count) + return true; + + for (j = 0; j < set[i].plane_count; j++) + if (set[i].plane_states[j] != stream_status->plane_states[j]) + return true; + + return false; +} + +/** + * dc_validate_with_context - Validate and update the potential new stream in the context object + * + * @dc: Used to get the current state status + * @set: An array of dc_validation_set with all the current streams reference + * @set_count: Total of streams + * @context: New context + * @fast_validate: Enable or disable fast validation + * + * This function updates the potential new stream in the context object. It + * creates multiple lists for the add, remove, and unchanged streams. In + * particular, if the unchanged streams have a plane that changed, it is + * necessary to remove all planes from the unchanged streams. In summary, this + * function is responsible for validating the new context. + * + * Return: + * In case of success, return DC_OK (1), otherwise, return a DC error. + */ +enum dc_status dc_validate_with_context(struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct dc_state *context, + bool fast_validate) +{ + struct dc_stream_state *unchanged_streams[MAX_PIPES] = { 0 }; + struct dc_stream_state *del_streams[MAX_PIPES] = { 0 }; + struct dc_stream_state *add_streams[MAX_PIPES] = { 0 }; + int old_stream_count = context->stream_count; + enum dc_status res = DC_ERROR_UNEXPECTED; + int unchanged_streams_count = 0; + int del_streams_count = 0; + int add_streams_count = 0; + bool found = false; + int i, j, k; + + DC_LOGGER_INIT(dc->ctx->logger); + + /* First build a list of streams to be remove from current context */ + for (i = 0; i < old_stream_count; i++) { + struct dc_stream_state *stream = context->streams[i]; + + for (j = 0; j < set_count; j++) { + if (stream == set[j].stream) { + found = true; + break; + } + } + + if (!found) + del_streams[del_streams_count++] = stream; + + found = false; + } + + /* Second, build a list of new streams */ + for (i = 0; i < set_count; i++) { + struct dc_stream_state *stream = set[i].stream; + + for (j = 0; j < old_stream_count; j++) { + if (stream == context->streams[j]) { + found = true; + break; + } + } + + if (!found) + add_streams[add_streams_count++] = stream; + + found = false; + } + + /* Build a list of unchanged streams which is necessary for handling + * planes change such as added, removed, and updated. + */ + for (i = 0; i < set_count; i++) { + /* Check if stream is part of the delete list */ + for (j = 0; j < del_streams_count; j++) { + if (set[i].stream == del_streams[j]) { + found = true; + break; + } + } + + if (!found) { + /* Check if stream is part of the add list */ + for (j = 0; j < add_streams_count; j++) { + if (set[i].stream == add_streams[j]) { + found = true; + break; + } + } + } + + if (!found) + unchanged_streams[unchanged_streams_count++] = set[i].stream; + + found = false; + } + + /* Remove all planes for unchanged streams if planes changed */ + for (i = 0; i < unchanged_streams_count; i++) { + if (planes_changed_for_existing_stream(context, + unchanged_streams[i], + set, + set_count)) { + if (!dc_rem_all_planes_for_stream(dc, + unchanged_streams[i], + context)) { + res = DC_FAIL_DETACH_SURFACES; + goto fail; + } + } + } + + /* Remove all planes for removed streams and then remove the streams */ + for (i = 0; i < del_streams_count; i++) { + /* Need to cpy the dwb data from the old stream in order to efc to work */ + if (del_streams[i]->num_wb_info > 0) { + for (j = 0; j < add_streams_count; j++) { + if (del_streams[i]->sink == add_streams[j]->sink) { + add_streams[j]->num_wb_info = del_streams[i]->num_wb_info; + for (k = 0; k < del_streams[i]->num_wb_info; k++) + add_streams[j]->writeback_info[k] = del_streams[i]->writeback_info[k]; + } + } + } + + if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) { + res = DC_FAIL_DETACH_SURFACES; + goto fail; + } + + res = dc_remove_stream_from_ctx(dc, context, del_streams[i]); + if (res != DC_OK) + goto fail; + } + + /* Add new streams and then add all planes for the new stream */ + for (i = 0; i < add_streams_count; i++) { + calculate_phy_pix_clks(add_streams[i]); + res = dc_add_stream_to_ctx(dc, context, add_streams[i]); + if (res != DC_OK) + goto fail; + + if (!add_all_planes_for_stream(dc, add_streams[i], set, set_count, context)) { + res = DC_FAIL_ATTACH_SURFACES; + goto fail; + } + } + + /* Add all planes for unchanged streams if planes changed */ + for (i = 0; i < unchanged_streams_count; i++) { + if (planes_changed_for_existing_stream(context, + unchanged_streams[i], + set, + set_count)) { + if (!add_all_planes_for_stream(dc, unchanged_streams[i], set, set_count, context)) { + res = DC_FAIL_ATTACH_SURFACES; + goto fail; + } + } + } + + res = dc_validate_global_state(dc, context, fast_validate); + +fail: + if (res != DC_OK) + DC_LOG_WARNING("%s:resource validation failed, dc_status:%d\n", + __func__, + res); + + return res; +} /** - * dc_validate_global_state() - Determine if HW can support a given state - * Checks HW resource availability and bandwidth requirement. + * dc_validate_global_state() - Determine if hardware can support a given state + * * @dc: dc struct for this driver * @new_ctx: state to be validated * @fast_validate: set to true if only yes/no to support matters * - * Return: DC_OK if the result can be programmed. Otherwise, an error code. + * Checks hardware resource availability and bandwidth requirement. + * + * Return: + * DC_OK if the result can be programmed. Otherwise, an error code. */ enum dc_status dc_validate_global_state( struct dc *dc, @@ -3734,4 +3945,4 @@ bool dc_resource_acquire_secondary_pipe_for_mpc_odm( } return true; -} \ No newline at end of file +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 836cdf5d4114..bf938cda379a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1297,6 +1297,12 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info); +enum dc_status dc_validate_with_context(struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct dc_state *context, + bool fast_validate); + bool dc_set_generic_gpio_for_stereo(bool enable, struct gpio_service *gpio_service); -- cgit v1.2.3 From 170390e587a69b2a24abac39eb3ae6ec28a4d7f2 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:22 -0400 Subject: drm/amd/display: Handle seamless boot stream A seamless boot stream has hardware resources assigned to it, and adding a new stream means rebuilding the current assignment. It is desirable to avoid this situation since it may cause light-up issues on the VGA monitor on USB-C. This commit swaps the seamless boot stream to pipe 0 (if necessary) to ensure that the pipe context matches. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e001b138b2ac..ba2d4347f722 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2765,6 +2765,21 @@ enum dc_status dc_validate_with_context(struct dc *dc, goto fail; } + /* Swap seamless boot stream to pipe 0 (if needed) to ensure pipe_ctx + * matches. This may change in the future if seamless_boot_stream can be + * multiple. + */ + for (i = 0; i < add_streams_count; i++) { + mark_seamless_boot_stream(dc, add_streams[i]); + if (add_streams[i]->apply_seamless_boot_optimization && i != 0) { + struct dc_stream_state *temp = add_streams[0]; + + add_streams[0] = add_streams[i]; + add_streams[i] = temp; + break; + } + } + /* Add new streams and then add all planes for the new stream */ for (i = 0; i < add_streams_count; i++) { calculate_phy_pix_clks(add_streams[i]); -- cgit v1.2.3 From eef019eabc3cd0fddcffefbf67806a4d8cca29bb Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:23 -0400 Subject: drm/amd/display: Update OTG instance in the commit stream OTG instance is not updated in dc_commit_state_no_check for newly committed streams because mode_change is not set. Notice that OTG update is part of the software state, and after hardware programming, it must be updated; for this reason, this commit updates the OTG offset right after hardware programming. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d568387c4bda..b7afada35b24 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1949,6 +1949,12 @@ enum dc_status dc_commit_streams(struct dc *dc, res = dc_commit_state_no_check(dc, context); + for (i = 0; i < stream_count; i++) { + for (j = 0; j < context->stream_count; j++) + if (streams[i]->stream_id == context->streams[j]->stream_id) + streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst; + } + fail: dc_release_state(context); -- cgit v1.2.3 From 7fffb03b4045c862f904a88b852dc509c4e46406 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:24 -0400 Subject: drm/amd/display: Avoid ABM when ODM combine is enabled for eDP ODM to combine on the eDP panel with ABM causes the color difference to the panel since the ABM module only sets one pipe. Hence, this commit blocks ABM in case of ODM combined on eDP. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b7afada35b24..375439c51cd3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1950,9 +1950,19 @@ enum dc_status dc_commit_streams(struct dc *dc, res = dc_commit_state_no_check(dc, context); for (i = 0; i < stream_count; i++) { - for (j = 0; j < context->stream_count; j++) + for (j = 0; j < context->stream_count; j++) { if (streams[i]->stream_id == context->streams[j]->stream_id) streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst; + + if (dc_is_embedded_signal(streams[i]->signal)) { + struct dc_stream_status *status = dc_stream_get_status_from_state(context, streams[i]); + + if (dc->hwss.is_abm_supported) + status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, streams[i]); + else + status->is_abm_supported = true; + } + } } fail: -- cgit v1.2.3 From dddde627807c22d6f15f4417eb395b13a1ca88f9 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 08:28:25 -0400 Subject: drm/amd/display: Use update plane and stream routine for DCN32x Sub-viewport (Subvp) feature is used for changing MCLK without causing any display artifact, requiring special treatment from the plane and stream perspective since DC needs to read data from the cache when using subvp. However, the function dc_commit_updates_for_stream does not provide all the support needed by this feature which will make this function legacy at some point. For this reason, this commit enables dc_update_planes_and_stream for ASICs that support this feature but preserves the old behavior for other ASICs. However, dc_update_planes_and_stream should replace dc_commit_updates_for_stream for all ASICs since it does most of the tasks executed by dc_commit_updates_for_stream with other extra operations, but we need to run tests before making this change. Reviewed-by: Harry Wentland Signed-off-by: Rodrigo Siqueira Co-developed-by: Aurabindo Pillai Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 375439c51cd3..56629197a6a1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3904,6 +3904,18 @@ void dc_commit_updates_for_stream(struct dc *dc, struct dc_context *dc_ctx = dc->ctx; int i, j; + /* TODO: Since change commit sequence can have a huge impact, + * we decided to only enable it for DCN3x. However, as soon as + * we get more confident about this change we'll need to enable + * the new sequence for all ASICs. + */ + if (dc->ctx->dce_version >= DCN_VERSION_3_2) { + dc_update_planes_and_stream(dc, srf_updates, + surface_count, stream, + stream_update); + return; + } + stream_status = dc_stream_get_status(stream); context = dc->current_state; -- cgit v1.2.3 From fa16dec20440156fda208c3d289dfa15af3953dc Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 20 Oct 2022 15:25:25 +0800 Subject: drm/amd/pm: allow gfxoff on gc_11_0_3 allow gfxoff on gc_11_0_3 Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index e3842dc100d6..5eefba2948a5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -5051,6 +5051,7 @@ static int gfx_v11_0_set_powergating_state(void *handle, switch (adev->ip_versions[GC_HWIP][0]) { case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 2): + case IP_VERSION(11, 0, 3): amdgpu_gfx_off_ctrl(adev, enable); break; case IP_VERSION(11, 0, 1): diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index feb4d68f3fd9..43fb102a65f5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -840,6 +840,7 @@ int smu_v13_0_gfx_off_control(struct smu_context *smu, bool enable) case IP_VERSION(13, 0, 5): case IP_VERSION(13, 0, 7): case IP_VERSION(13, 0, 8): + case IP_VERSION(13, 0, 10): if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) -- cgit v1.2.3 From 345b16961afe0deae8633ce10dbff46c7e64e35f Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 6 Oct 2022 17:26:48 -0400 Subject: drm/amd/display: Remove wrong pipe control lock When using a device based on DCN32/321, we have an issue where a second 4k@60Hz display does not light up, and the system becomes unresponsive for a few minutes. In the debug process, it was possible to see a hang in the function dcn20_post_unlock_program_front_end in this part: for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000 && hubp->funcs->hubp_is_flip_pending(hubp); j++) mdelay(1); } The hubp_is_flip_pending always returns positive for waiting pending flips which is a symptom of pipe hang. Additionally, the dmesg log shows this message after a few minutes: BUG: soft lockup - CPU#4 stuck for 26s! ... [ +0.000003] dcn20_post_unlock_program_front_end+0x112/0x340 [amdgpu] [ +0.000171] dc_commit_state_no_check+0x63d/0xbf0 [amdgpu] [ +0.000155] ? dc_validate_global_state+0x358/0x3d0 [amdgpu] [ +0.000154] dc_commit_state+0xe2/0xf0 [amdgpu] This confirmed the hypothesis that we had a pipe hanging somewhere. Next, after checking the ftrace entries, we have the below weird sequence: [..] 2) | dcn10_lock_all_pipes [amdgpu]() { 2) 0.120 us | optc1_is_tg_enabled [amdgpu](); 2) | dcn20_pipe_control_lock [amdgpu]() { 2) | dc_dmub_srv_clear_inbox0_ack [amdgpu]() { 2) 0.121 us | amdgpu_dm_dmub_reg_write [amdgpu](); 2) 0.551 us | } 2) | dc_dmub_srv_send_inbox0_cmd [amdgpu]() { 2) 0.110 us | amdgpu_dm_dmub_reg_write [amdgpu](); 2) 0.511 us | } 2) | dc_dmub_srv_wait_for_inbox0_ack [amdgpu]() { 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); [..] We are not expected to read from dmub register so many times and for so long. From the trace log, it was possible to identify that the function dcn20_pipe_control_lock was triggering the dmub operation when it was unnecessary and causing the hang issue. This commit drops the unnecessary dmub code and, consequently, fixes the second display not lighting up the issue. Tested-by: Daniel Wheeler Acked-by: Qingqing Zhuo Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index d732b6f031a1..a7e0001a8f46 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1270,16 +1270,6 @@ void dcn20_pipe_control_lock( lock, &hw_locks, &inst_flags); - } else if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN) { - union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 }; - hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK; - hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER; - hw_lock_cmd.bits.lock_pipe = 1; - hw_lock_cmd.bits.otg_inst = pipe->stream_res.tg->inst; - hw_lock_cmd.bits.lock = lock; - if (!lock) - hw_lock_cmd.bits.should_release = 1; - dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd); } else if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) { if (lock) pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); @@ -1856,7 +1846,7 @@ void dcn20_post_unlock_program_front_end( for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000 && hubp->funcs->hubp_is_flip_pending(hubp); j++) - mdelay(1); + udelay(1); } } -- cgit v1.2.3 From 27fcf77830d0e8af53cd562909ff37aa3ec345dd Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 6 Oct 2022 17:26:49 -0400 Subject: drm/amd/display: Don't return false if no stream pipe_ctx[i] exists even if the pipe is not in use. If the pipe is not in use it will always have a null stream, so don't return false in this case. Tested-by: Daniel Wheeler Reviewed-by: Rodrigo Siqueira Acked-by: Qingqing Zhuo Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index d51d0c40ae5b..b03a7814e96d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -200,7 +200,7 @@ bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc, struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; if (!pipe->stream) - return false; + continue; if (!pipe->plane_state) return false; -- cgit v1.2.3 From 6c16afdcec20b01879ad17440f42c9944786dc7d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Oct 2022 16:57:42 -0400 Subject: drm/amdgpu: fix sdma doorbell init ordering on APUs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 8795e182b02d ("PCI/portdrv: Don't disable AER reporting in get_port_device_capability()") uncovered a bug in amdgpu that required a reordering of the driver init sequence to avoid accessing a special register on the GPU before it was properly set up leading to an PCI AER error. This reordering uncovered a different hw programming ordering dependency in some APUs where the SDMA doorbells need to be programmed before the GFX doorbells. To fix this, move the SDMA doorbell programming back into the soc15 common code, but use the actual doorbell range values directly rather than the values stored in the ring structure since those will not be initialized at this point. This is a partial revert, but with the doorbell assignment fixed so the proper doorbell index is set before it's used. Fixes: e3163bc8ffdfdb ("drm/amdgpu: move nbio sdma_doorbell_range() into sdma code for vega") Acked-by: Christian König Signed-off-by: Alex Deucher Cc: skhan@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 5 ----- drivers/gpu/drm/amd/amdgpu/soc15.c | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 298fa11702e7..1122bd4eae98 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -1417,11 +1417,6 @@ static int sdma_v4_0_start(struct amdgpu_device *adev) WREG32_SDMA(i, mmSDMA0_CNTL, temp); if (!amdgpu_sriov_vf(adev)) { - ring = &adev->sdma.instance[i].ring; - adev->nbio.funcs->sdma_doorbell_range(adev, i, - ring->use_doorbell, ring->doorbell_index, - adev->doorbell_index.sdma_doorbell_range); - /* unhalt engine */ temp = RREG32_SDMA(i, mmSDMA0_F32_CNTL); temp = REG_SET_FIELD(temp, SDMA0_F32_CNTL, HALT, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 183024d7c184..e3b2b6b4f1a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1211,6 +1211,20 @@ static int soc15_common_sw_fini(void *handle) return 0; } +static void soc15_sdma_doorbell_range_init(struct amdgpu_device *adev) +{ + int i; + + /* sdma doorbell range is programed by hypervisor */ + if (!amdgpu_sriov_vf(adev)) { + for (i = 0; i < adev->sdma.num_instances; i++) { + adev->nbio.funcs->sdma_doorbell_range(adev, i, + true, adev->doorbell_index.sdma_engine[i] << 1, + adev->doorbell_index.sdma_doorbell_range); + } + } +} + static int soc15_common_hw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1230,6 +1244,13 @@ static int soc15_common_hw_init(void *handle) /* enable the doorbell aperture */ soc15_enable_doorbell_aperture(adev, true); + /* HW doorbell routing policy: doorbell writing not + * in SDMA/IH/MM/ACV range will be routed to CP. So + * we need to init SDMA doorbell range prior + * to CP ip block init and ring test. IH already + * happens before CP. + */ + soc15_sdma_doorbell_range_init(adev); return 0; } -- cgit v1.2.3 From 9feece0d96124096e7268007bd2d3905a29d92ac Mon Sep 17 00:00:00 2001 From: ruanjinjie Date: Wed, 19 Oct 2022 15:45:02 +0800 Subject: drm/amd/display: Make some symbols static These symbols qp_table_422_10bpc_min, qp_table_444_8bpc_max, qp_table_420_12bpc_max, qp_table_444_10bpc_min, qp_table_420_8bpc_max, qp_table_444_8bpc_min, qp_table_444_12bpc_min, qp_table_420_12bpc_min, qp_table_422_12bpc_min, qp_table_422_12bpc_max, qp_table_444_12bpc_max, qp_table_420_8bpc_min, qp_table_422_8bpc_min, qp_table_422_10bpc_max, qp_table_420_10bpc_max, qp_table_420_10bpc_min, qp_table_444_10bpc_max, qp_table_422_8bpc_max are not used outside of the file, so mark them static. ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:28:18: warning: symbol 'qp_table_422_10bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:61:18: warning: symbol 'qp_table_444_8bpc_max' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:102:18: warning: symbol 'qp_table_420_12bpc_max' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:135:18: warning: symbol 'qp_table_444_10bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:188:18: warning: symbol 'qp_table_420_8bpc_max' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:209:18: warning: symbol 'qp_table_444_8bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:250:18: warning: symbol 'qp_table_444_12bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:315:18: warning: symbol 'qp_table_420_12bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:348:18: warning: symbol 'qp_table_422_12bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:389:18: warning: symbol 'qp_table_422_12bpc_max' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:430:18: warning: symbol 'qp_table_444_12bpc_max' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:495:18: warning: symbol 'qp_table_420_8bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:516:18: warning: symbol 'qp_table_422_8bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:541:18: warning: symbol 'qp_table_422_10bpc_max' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:574:16: warning: symbol 'qp_table_420_10bpc_max' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:601:18: warning: symbol 'qp_table_420_10bpc_min' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:628:18: warning: symbol 'qp_table_444_10bpc_max' was not declared. Should it be static? ./drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/qp_tables.h:681:18: warning: symbol 'qp_table_422_8bpc_max' was not declared. Should it be static? Signed-off-by: ruanjinjie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h b/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h index e5fac9f4181d..dcff0dd2b6a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h @@ -25,7 +25,7 @@ */ -const qp_table qp_table_422_10bpc_min = { +static const qp_table qp_table_422_10bpc_min = { { 6, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} }, { 6.5, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} }, { 7, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 7, 9, 9, 9, 11, 15} }, @@ -58,7 +58,7 @@ const qp_table qp_table_422_10bpc_min = { }; -const qp_table qp_table_444_8bpc_max = { +static const qp_table qp_table_444_8bpc_max = { { 6, { 4, 6, 8, 8, 9, 9, 9, 10, 11, 12, 12, 12, 12, 13, 15} }, { 6.5, { 4, 6, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 12, 13, 15} }, { 7, { 4, 5, 7, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 13, 14} }, @@ -99,7 +99,7 @@ const qp_table qp_table_444_8bpc_max = { }; -const qp_table qp_table_420_12bpc_max = { +static const qp_table qp_table_420_12bpc_max = { { 4, {11, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 21, 22} }, { 4.5, {10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, { 5, { 9, 11, 12, 13, 14, 15, 15, 16, 17, 17, 18, 18, 19, 20, 21} }, @@ -132,7 +132,7 @@ const qp_table qp_table_420_12bpc_max = { }; -const qp_table qp_table_444_10bpc_min = { +static const qp_table qp_table_444_10bpc_min = { { 6, { 0, 4, 7, 7, 9, 9, 9, 9, 9, 10, 10, 10, 10, 12, 18} }, { 6.5, { 0, 4, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 12, 18} }, { 7, { 0, 4, 6, 6, 8, 8, 8, 8, 8, 9, 9, 10, 10, 12, 17} }, @@ -185,7 +185,7 @@ const qp_table qp_table_444_10bpc_min = { }; -const qp_table qp_table_420_8bpc_max = { +static const qp_table qp_table_420_8bpc_max = { { 4, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 13, 14} }, { 4.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, { 5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 12, 13} }, @@ -206,7 +206,7 @@ const qp_table qp_table_420_8bpc_max = { }; -const qp_table qp_table_444_8bpc_min = { +static const qp_table qp_table_444_8bpc_min = { { 6, { 0, 1, 3, 3, 5, 5, 5, 5, 5, 6, 6, 6, 6, 9, 14} }, { 6.5, { 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 9, 14} }, { 7, { 0, 0, 2, 2, 4, 4, 4, 4, 4, 5, 5, 6, 6, 9, 13} }, @@ -247,7 +247,7 @@ const qp_table qp_table_444_8bpc_min = { }; -const qp_table qp_table_444_12bpc_min = { +static const qp_table qp_table_444_12bpc_min = { { 6, { 0, 5, 11, 11, 13, 13, 13, 13, 13, 14, 14, 14, 14, 17, 22} }, { 6.5, { 0, 5, 10, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 17, 22} }, { 7, { 0, 5, 10, 10, 12, 12, 12, 12, 12, 13, 13, 14, 14, 17, 21} }, @@ -312,7 +312,7 @@ const qp_table qp_table_444_12bpc_min = { }; -const qp_table qp_table_420_12bpc_min = { +static const qp_table qp_table_420_12bpc_min = { { 4, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21} }, { 4.5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, { 5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, @@ -345,7 +345,7 @@ const qp_table qp_table_420_12bpc_min = { }; -const qp_table qp_table_422_12bpc_min = { +static const qp_table qp_table_422_12bpc_min = { { 6, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} }, { 6.5, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} }, { 7, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, @@ -386,7 +386,7 @@ const qp_table qp_table_422_12bpc_min = { }; -const qp_table qp_table_422_12bpc_max = { +static const qp_table qp_table_422_12bpc_max = { { 6, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, { 6.5, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, { 7, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20} }, @@ -427,7 +427,7 @@ const qp_table qp_table_422_12bpc_max = { }; -const qp_table qp_table_444_12bpc_max = { +static const qp_table qp_table_444_12bpc_max = { { 6, {12, 14, 16, 16, 17, 17, 17, 18, 19, 20, 20, 20, 20, 21, 23} }, { 6.5, {12, 14, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 20, 21, 23} }, { 7, {12, 13, 15, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 21, 22} }, @@ -492,7 +492,7 @@ const qp_table qp_table_444_12bpc_max = { }; -const qp_table qp_table_420_8bpc_min = { +static const qp_table qp_table_420_8bpc_min = { { 4, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 13} }, { 4.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, { 5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, @@ -513,7 +513,7 @@ const qp_table qp_table_420_8bpc_min = { }; -const qp_table qp_table_422_8bpc_min = { +static const qp_table qp_table_422_8bpc_min = { { 6, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, { 6.5, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, { 7, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, @@ -538,7 +538,7 @@ const qp_table qp_table_422_8bpc_min = { }; -const qp_table qp_table_422_10bpc_max = { +static const qp_table qp_table_422_10bpc_max = { { 6, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, { 6.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, { 7, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, @@ -571,7 +571,7 @@ const qp_table qp_table_422_10bpc_max = { }; -const qp_table qp_table_420_10bpc_max = { +static const qp_table qp_table_420_10bpc_max = { { 4, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 17, 18} }, { 4.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, { 5, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 16, 17} }, @@ -598,7 +598,7 @@ const qp_table qp_table_420_10bpc_max = { }; -const qp_table qp_table_420_10bpc_min = { +static const qp_table qp_table_420_10bpc_min = { { 4, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 17} }, { 4.5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, { 5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, @@ -625,7 +625,7 @@ const qp_table qp_table_420_10bpc_min = { }; -const qp_table qp_table_444_10bpc_max = { +static const qp_table qp_table_444_10bpc_max = { { 6, { 8, 10, 12, 12, 13, 13, 13, 14, 15, 16, 16, 16, 16, 17, 19} }, { 6.5, { 8, 10, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 16, 17, 19} }, { 7, { 8, 9, 11, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 17, 18} }, @@ -678,7 +678,7 @@ const qp_table qp_table_444_10bpc_max = { }; -const qp_table qp_table_422_8bpc_max = { +static const qp_table qp_table_422_8bpc_max = { { 6, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, { 6.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, { 7, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, -- cgit v1.2.3 From 72c9abd5399d9f5c20a5b93737e67edba3189079 Mon Sep 17 00:00:00 2001 From: ruanjinjie Date: Wed, 19 Oct 2022 14:31:15 +0800 Subject: drm/amd/display: make dcn32_mmhubbub_funcs static The symbol is not used outside of the file, so mark it static. Fixes the following warning: drivers/gpu/drm/amd/amdgpu/../display/dc/dcn32/dcn32_mmhubbub.c:214:28: warning: symbol 'dcn32_mmhubbub_funcs' was not declared. Should it be static? Reviewed-by: Harry Wentland Signed-off-by: ruanjinjie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c index 41b0baf8e183..c3b089ba511a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c @@ -211,7 +211,7 @@ static void mmhubbub32_config_mcif_arb(struct mcif_wb *mcif_wb, REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, params->arbitration_slice); } -const struct mcif_wb_funcs dcn32_mmhubbub_funcs = { +static const struct mcif_wb_funcs dcn32_mmhubbub_funcs = { .warmup_mcif = mmhubbub32_warmup_mcif, .enable_mcif = mmhubbub2_enable_mcif, .disable_mcif = mmhubbub2_disable_mcif, -- cgit v1.2.3 From 178919f8ff2d4cd1ad32680eb767e6761e9d00ea Mon Sep 17 00:00:00 2001 From: ruanjinjie Date: Wed, 19 Oct 2022 14:23:47 +0800 Subject: drm/amd/display: make dcn32_mpc_funcs static The symbol is not used outside of the file, so mark it static. Fixes the following warning: drivers/gpu/drm/amd/amdgpu/../display/dc/dcn32/dcn32_mpc.c:985:24: warning: symbol 'dcn32_mpc_funcs' was not declared. Should it be static? Reviewed-by: Harry Wentland Signed-off-by: ruanjinjie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c index 4edd0655965b..206a5ddbaf6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c @@ -982,7 +982,7 @@ static bool mpc32_program_3dlut( return true; } -const struct mpc_funcs dcn32_mpc_funcs = { +static const struct mpc_funcs dcn32_mpc_funcs = { .read_mpcc_state = mpc1_read_mpcc_state, .insert_plane = mpc1_insert_plane, .remove_mpcc = mpc1_remove_mpcc, -- cgit v1.2.3 From 3a3e841d050d9d919317ad2b65d80fc9c8c799dc Mon Sep 17 00:00:00 2001 From: Deming Wang Date: Thu, 6 Oct 2022 22:26:51 -0400 Subject: drm/amdkfd: use vma_lookup() instead of find_vma() Using vma_lookup() verifies the start address is contained in the found vma. This results in easier to read the code. Signed-off-by: Deming Wang Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 8 ++++---- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 17 ++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 2797029bd500..d4e6de2a6bf6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -529,8 +529,8 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, for (addr = start; addr < end;) { unsigned long next; - vma = find_vma(mm, addr); - if (!vma || addr < vma->vm_start) + vma = vma_lookup(mm, addr); + if (!vma) break; next = min(vma->vm_end, end); @@ -798,8 +798,8 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm, for (addr = start; addr < end;) { unsigned long next; - vma = find_vma(mm, addr); - if (!vma || addr < vma->vm_start) { + vma = vma_lookup(mm, addr); + if (!vma) { pr_debug("failed to find vma for prange %p\n", prange); r = -EFAULT; break; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 64fdf63093a0..0100812478b2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1586,8 +1586,8 @@ static int svm_range_validate_and_map(struct mm_struct *mm, unsigned long npages; bool readonly; - vma = find_vma(mm, addr); - if (!vma || addr < vma->vm_start) { + vma = vma_lookup(mm, addr); + if (!vma) { r = -EFAULT; goto unreserve_out; } @@ -2542,8 +2542,8 @@ svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr, struct interval_tree_node *node; unsigned long start_limit, end_limit; - vma = find_vma(p->mm, addr << PAGE_SHIFT); - if (!vma || (addr << PAGE_SHIFT) < vma->vm_start) { + vma = vma_lookup(p->mm, addr << PAGE_SHIFT); + if (!vma) { pr_debug("VMA does not exist in address [0x%llx]\n", addr); return -EFAULT; } @@ -2871,8 +2871,8 @@ retry_write_locked: /* __do_munmap removed VMA, return success as we are handling stale * retry fault. */ - vma = find_vma(mm, addr << PAGE_SHIFT); - if (!vma || (addr << PAGE_SHIFT) < vma->vm_start) { + vma = vma_lookup(mm, addr << PAGE_SHIFT); + if (!vma) { pr_debug("address 0x%llx VMA is removed\n", addr); r = 0; goto out_unlock_range; @@ -3152,9 +3152,8 @@ svm_range_is_valid(struct kfd_process *p, uint64_t start, uint64_t size) start <<= PAGE_SHIFT; end = start + (size << PAGE_SHIFT); do { - vma = find_vma(p->mm, start); - if (!vma || start < vma->vm_start || - (vma->vm_flags & device_vma)) + vma = vma_lookup(p->mm, start); + if (!vma || (vma->vm_flags & device_vma)) return -EFAULT; start = min(end, vma->vm_end); } while (start < end); -- cgit v1.2.3 From b72362962a66693cd095389cbe41dd005bfcfb44 Mon Sep 17 00:00:00 2001 From: David Francis Date: Fri, 16 Sep 2022 11:15:01 -0400 Subject: drm/amd: Add IMU fw version to fw version queries IMU is a new firmware for GFX11. There are four means by which firmware version can be queried from the driver: device attributes, vf2pf, debugfs, and the AMDGPU_INFO_FW_VERSION option in the amdgpu info ioctl. Add IMU as an option for those four methods. V2: Added debugfs Reviewed-by: Likun Gao Reviewed-by: Alex Deucher Signed-off-by: David Francis Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 13 +++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 4 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index fe23e09eec98..bf1ff8f0e712 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -344,6 +344,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, fw_info->ver = adev->mes.ucode_fw_version[1]; fw_info->feature = 0; break; + case AMDGPU_INFO_FW_IMU: + fw_info->ver = adev->gfx.imu_fw_version; + fw_info->feature = 0; + break; default: return -EINVAL; } @@ -1520,6 +1524,15 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused) fw_info.feature, fw_info.ver); } + /* IMU */ + query_fw.fw_type = AMDGPU_INFO_FW_IMU; + query_fw.index = 0; + ret = amdgpu_firmware_info(&fw_info, &query_fw, adev); + if (ret) + return ret; + seq_printf(m, "IMU feature version: %u, firmware version: 0x%08x\n", + fw_info.feature, fw_info.ver); + /* PSP SOS */ query_fw.fw_type = AMDGPU_INFO_FW_SOS; ret = amdgpu_firmware_info(&fw_info, &query_fw, adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index dd0bc649a57d..5cb62e6249c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -698,6 +698,7 @@ FW_VERSION_ATTR(rlc_srlg_fw_version, 0444, gfx.rlc_srlg_fw_version); FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version); FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version); FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version); +FW_VERSION_ATTR(imu_fw_version, 0444, gfx.imu_fw_version); FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version); FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_context.bin_desc.fw_version); FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.fw_version); @@ -719,7 +720,8 @@ static struct attribute *fw_attrs[] = { &dev_attr_ta_ras_fw_version.attr, &dev_attr_ta_xgmi_fw_version.attr, &dev_attr_smc_fw_version.attr, &dev_attr_sdma_fw_version.attr, &dev_attr_sdma2_fw_version.attr, &dev_attr_vcn_fw_version.attr, - &dev_attr_dmcu_fw_version.attr, NULL + &dev_attr_dmcu_fw_version.attr, &dev_attr_imu_fw_version.attr, + NULL }; static const struct attribute_group fw_attr_group = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 9c765b04aae3..c73abe54d974 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -547,6 +547,7 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev) POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_IMU, adev->gfx.imu_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd_context.bin_desc.fw_version); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h index e78e4c27b62a..6c97148ca0ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -70,6 +70,7 @@ enum amd_sriov_ucode_engine_id { AMD_SRIOV_UCODE_ID_RLC_SRLS, AMD_SRIOV_UCODE_ID_MEC, AMD_SRIOV_UCODE_ID_MEC2, + AMD_SRIOV_UCODE_ID_IMU, AMD_SRIOV_UCODE_ID_SOS, AMD_SRIOV_UCODE_ID_ASD, AMD_SRIOV_UCODE_ID_TA_RAS, -- cgit v1.2.3 From a9232b068e3698b8aa4a29fb7292bfdeb0c8f4ff Mon Sep 17 00:00:00 2001 From: Prike Liang Date: Thu, 20 Oct 2022 14:44:26 +0800 Subject: drm/amdkfd: update gfx1037 Lx cache setting Update the gfx1037 L1/L2 cache setting. Signed-off-by: Prike Liang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 53 ++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index cd5f8b219bf9..d6fa787ff490 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -795,6 +795,54 @@ static struct kfd_gpu_cache_info yellow_carp_cache_info[] = { }, }; +static struct kfd_gpu_cache_info gfx1037_cache_info[] = { + { + /* TCP L1 Cache per CU */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 1, + }, + { + /* Scalar L1 Instruction Cache per SQC */ + .cache_size = 32, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_INST_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* Scalar L1 Data Cache per SQC */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* GL1 Data Cache per SA */ + .cache_size = 128, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* L2 Data Cache per GPU (Total Tex Cache) */ + .cache_size = 256, + .cache_level = 2, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, +}; + static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev, struct crat_subtype_computeunit *cu) { @@ -1515,10 +1563,13 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, break; case IP_VERSION(10, 3, 3): case IP_VERSION(10, 3, 6): /* TODO: Double check these on production silicon */ - case IP_VERSION(10, 3, 7): /* TODO: Double check these on production silicon */ pcache_info = yellow_carp_cache_info; num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info); break; + case IP_VERSION(10, 3, 7): + pcache_info = gfx1037_cache_info; + num_of_cache_types = ARRAY_SIZE(gfx1037_cache_info); + break; case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 2): -- cgit v1.2.3 From d62eaddbc9ae27e1d98389b74778b29d4c1388d4 Mon Sep 17 00:00:00 2001 From: Jesse Zhang Date: Tue, 11 Oct 2022 05:23:10 +0000 Subject: drm/amdkfd: correct the cache info for gfx1036 correct the cache information for gfx1036 Acked-by: Alex Deucher Reviewed-by: Yifan Zhang Signed-off-by: Yifan Zhang Signed-off-by: Jesse Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 53 ++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index d6fa787ff490..8bfdfd062ff6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -843,6 +843,54 @@ static struct kfd_gpu_cache_info gfx1037_cache_info[] = { }, }; +static struct kfd_gpu_cache_info gc_10_3_6_cache_info[] = { + { + /* TCP L1 Cache per CU */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 1, + }, + { + /* Scalar L1 Instruction Cache per SQC */ + .cache_size = 32, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_INST_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* Scalar L1 Data Cache per SQC */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* GL1 Data Cache per SA */ + .cache_size = 128, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* L2 Data Cache per GPU (Total Tex Cache) */ + .cache_size = 256, + .cache_level = 2, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, +}; + static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev, struct crat_subtype_computeunit *cu) { @@ -1562,10 +1610,13 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, num_of_cache_types = ARRAY_SIZE(beige_goby_cache_info); break; case IP_VERSION(10, 3, 3): - case IP_VERSION(10, 3, 6): /* TODO: Double check these on production silicon */ pcache_info = yellow_carp_cache_info; num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info); break; + case IP_VERSION(10, 3, 6): + pcache_info = gc_10_3_6_cache_info; + num_of_cache_types = ARRAY_SIZE(gc_10_3_6_cache_info); + break; case IP_VERSION(10, 3, 7): pcache_info = gfx1037_cache_info; num_of_cache_types = ARRAY_SIZE(gfx1037_cache_info); -- cgit v1.2.3 From fd72e2cb2f9dd2734e8013b3e185a21f0d605d3e Mon Sep 17 00:00:00 2001 From: Prike Liang Date: Fri, 21 Oct 2022 16:38:48 -0400 Subject: drm/amdkfd: introduce dummy cache info for property asic This dummy cache info will enable kfd base function support. Signed-off-by: Prike Liang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 53 ++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 8bfdfd062ff6..5e0bad7e0b77 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -891,6 +891,54 @@ static struct kfd_gpu_cache_info gc_10_3_6_cache_info[] = { }, }; +static struct kfd_gpu_cache_info dummy_cache_info[] = { + { + /* TCP L1 Cache per CU */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 1, + }, + { + /* Scalar L1 Instruction Cache per SQC */ + .cache_size = 32, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_INST_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* Scalar L1 Data Cache per SQC */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* GL1 Data Cache per SA */ + .cache_size = 128, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 6, + }, + { + /* L2 Data Cache per GPU (Total Tex Cache) */ + .cache_size = 2048, + .cache_level = 2, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 6, + }, +}; + static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev, struct crat_subtype_computeunit *cu) { @@ -1630,7 +1678,10 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, kfd_fill_gpu_cache_info_from_gfx_config(kdev, pcache_info); break; default: - return -EINVAL; + pcache_info = dummy_cache_info; + num_of_cache_types = ARRAY_SIZE(dummy_cache_info); + pr_warn("dummy cache info is used temporarily and real cache info need update later.\n"); + break; } } -- cgit v1.2.3 From 693073a04de491c82cd0e1d6bf979192375373c1 Mon Sep 17 00:00:00 2001 From: YuBiao Wang Date: Wed, 19 Oct 2022 11:36:32 +0800 Subject: drm/amdgpu: skip mes self test for gc 11.0.3 in recover Temporary disable mes self teset for gc 11.0.3 during gpu_recovery. Signed-off-by: YuBiao Wang Acked-by: Luben Tuikov Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index e0445e8cc342..5b8362727226 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -5381,7 +5381,7 @@ skip_hw_reset: drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res); } - if (adev->enable_mes) + if (adev->enable_mes && adev->ip_versions[GC_HWIP][0] != IP_VERSION(11, 0, 3)) amdgpu_mes_self_test(tmp_adev); if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) { -- cgit v1.2.3 From f543d28687480fad06b708bc6e0b0b6ec953b078 Mon Sep 17 00:00:00 2001 From: Prike Liang Date: Fri, 21 Oct 2022 10:04:40 +0800 Subject: drm/amdgpu: disallow gfxoff until GC IP blocks complete s2idle resume In the S2idle suspend/resume phase the gfxoff is keeping functional so some IP blocks will be likely to reinitialize at gfxoff entry and that will result in failing to program GC registers.Therefore, let disallow gfxoff until AMDGPU IPs reinitialized completely. Signed-off-by: Prike Liang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5b8362727226..ddaecb2610c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3210,6 +3210,15 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev) return r; } adev->ip_blocks[i].status.hw = true; + + if (adev->in_s0ix && adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) { + /* disable gfxoff for IP resume. The gfxoff will be re-enabled in + * amdgpu_device_resume() after IP resume. + */ + amdgpu_gfx_off_ctrl(adev, false); + DRM_DEBUG("will disable gfxoff for re-initializing other blocks\n"); + } + } return 0; @@ -4185,6 +4194,13 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) /* Make sure IB tests flushed */ flush_delayed_work(&adev->delayed_init_work); + if (adev->in_s0ix) { + /* re-enable gfxoff after IP resume. This re-enables gfxoff after + * it was disabled for IP resume in amdgpu_device_ip_resume_phase2(). + */ + amdgpu_gfx_off_ctrl(adev, true); + DRM_DEBUG("will enable gfxoff for the mission mode\n"); + } if (fbcon) drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false); -- cgit v1.2.3 From b66fca42c4e5739fa7ce17edd1c4d451b0d3c78d Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Thu, 20 Oct 2022 11:46:30 -0400 Subject: drm/amd/display: Add UHBR135 and UHBR20 into debugfs Add support to manually force link rate to UHBR135 (0x546) and UHBR20 (0x7d0). Tested-by: Mark Broadworth Reviewed-by: Roman Li Acked-by: Rodrigo Siqueira Signed-off-by: Fangzhi Zuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index ee242d9d8b06..0c717d7b12e5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -299,6 +299,8 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, case LINK_RATE_HIGH2: case LINK_RATE_HIGH3: case LINK_RATE_UHBR10: + case LINK_RATE_UHBR13_5: + case LINK_RATE_UHBR20: break; default: valid_input = false; -- cgit v1.2.3 From bbfbf09d193ac831c40db50ef4b31d11548a9eef Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 20 Oct 2022 11:46:31 -0400 Subject: drm/amd/display: Remove FPU guards from the DML folder As part of the programming expectation for using DML functions, DC requires that any DML function invoked outside DML uses: DC_FP_START(); ... dml function ... DC_FP_END(); Additionally, all the DML functions that can be invoked outside the DML folder call the function dc_assert_fp_enabled(), which is responsible for triggering a warning in the case that the DML function was not guarded by the DC_FP_START/END. For this reason, call DC_FP_START/END inside DML is wrong, and this commit removes all of those references. Tested-by: Mark Broadworth Reviewed-by: Nevenko Stupar Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c | 2 -- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 17 +---------------- 2 files changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c index e1e92daba668..d4c0f9cdac8e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c @@ -520,9 +520,7 @@ void dcn30_fpu_calculate_wm_and_dlg( pipe_idx++; } - DC_FP_START(); dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); - DC_FP_END(); if (!pstate_en) /* Restore full p-state latency */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 819de0f11012..d8e68f13c288 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -1191,9 +1191,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, } } else { // Most populate phantom DLG params before programming hardware / timing for phantom pipe - DC_FP_START(); dcn32_helper_populate_phantom_dlg_params(dc, context, pipes, *pipe_cnt); - DC_FP_END(); /* Call validate_apply_pipe_split flags after calling DML getters for * phantom dlg params, or some of the VBA params indicating pipe split @@ -1494,11 +1492,8 @@ bool dcn32_internal_validate_bw(struct dc *dc, dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); - if (!fast_validate) { - DC_FP_START(); + if (!fast_validate) dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt); - DC_FP_END(); - } if (fast_validate || (dc->debug.dml_disallow_alternate_prefetch_modes && @@ -2145,9 +2140,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params, entry.fabricclk_mhz = 0; entry.dram_speed_mts = 0; - DC_FP_START(); insert_entry_into_table_sorted(table, num_entries, &entry); - DC_FP_END(); } // Insert the max DCFCLK @@ -2155,9 +2148,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params, entry.fabricclk_mhz = 0; entry.dram_speed_mts = 0; - DC_FP_START(); insert_entry_into_table_sorted(table, num_entries, &entry); - DC_FP_END(); // Insert the UCLK DPMS for (i = 0; i < num_uclk_dpms; i++) { @@ -2165,9 +2156,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params, entry.fabricclk_mhz = 0; entry.dram_speed_mts = bw_params->clk_table.entries[i].memclk_mhz * 16; - DC_FP_START(); insert_entry_into_table_sorted(table, num_entries, &entry); - DC_FP_END(); } // If FCLK is coarse grained, insert individual DPMs. @@ -2177,9 +2166,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params, entry.fabricclk_mhz = bw_params->clk_table.entries[i].fclk_mhz; entry.dram_speed_mts = 0; - DC_FP_START(); insert_entry_into_table_sorted(table, num_entries, &entry); - DC_FP_END(); } } // If FCLK fine grained, only insert max @@ -2188,9 +2175,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params, entry.fabricclk_mhz = max_fclk_mhz; entry.dram_speed_mts = 0; - DC_FP_START(); insert_entry_into_table_sorted(table, num_entries, &entry); - DC_FP_END(); } // At this point, the table contains all "points of interest" based on -- cgit v1.2.3 From 14e2739c3695734bb4f5a0deca6fff4e10e5ef5d Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 20 Oct 2022 11:46:32 -0400 Subject: drm/amd/display: refactor enable/disable audio stream hw sequence [why] 1. As recommended by hardware team, don't enable APG when stream is not enabled. 2. Move audio stream encoder programming into link_hwss. [how] 1. Merge dp_audio_enable into enable audio stream hw sequence. 2. Move stream encoder programming into link hwss level to unify stream encoder programming interface. Tested-by: Mark Broadworth Reviewed-by: Charlene Liu Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +-- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 14 +----- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 50 ++++------------------ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 8 ---- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c | 2 - drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 2 + .../gpu/drm/amd/display/dc/link/link_hwss_dio.c | 35 +++++++++++++++ .../gpu/drm/amd/display/dc/link/link_hwss_dio.h | 2 + .../gpu/drm/amd/display/dc/link/link_hwss_dpia.c | 2 + .../gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c | 15 +++++++ 10 files changed, 68 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d7b1ace6328a..24ed057414e1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -4229,6 +4229,7 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings); + dc->hwss.enable_audio_stream(pipe_ctx); } void core_link_enable_stream( @@ -4308,10 +4309,7 @@ void core_link_enable_stream( /* Still enable stream features & audio on seamless boot for DP external displays */ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) { enable_stream_features(pipe_ctx); - if (pipe_ctx->stream_res.audio != NULL) { - pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); - dc->hwss.enable_audio_stream(pipe_ctx); - } + dc->hwss.enable_audio_stream(pipe_ctx); } #if defined(CONFIG_DRM_AMD_DC_HDCP) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 1254d38f1778..bd4cbe02d353 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -7339,19 +7339,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, link->dc->hwss.unblank_stream(&pipes[i], link_setting); - if (pipes[i].stream_res.audio) { - /* notify audio driver for - * audio modes of monitor */ - pipes[i].stream_res.audio->funcs->az_enable( - pipes[i].stream_res.audio); - - /* un-mute audio */ - /* TODO: audio should be per stream rather than - * per link */ - pipes[i].stream_res.stream_enc->funcs-> - audio_mute_control( - pipes[i].stream_res.stream_enc, false); - } + link->dc->hwss.enable_audio_stream(&pipes[i]); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d260eaa1509e..a34bc631be00 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -688,16 +688,6 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) early_control = lane_count; tg->funcs->set_early_control(tg, early_control); - - /* enable audio only within mode set */ - if (pipe_ctx->stream_res.audio != NULL) { - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); - } - - - - } static enum bp_result link_transmitter_control( @@ -1081,12 +1071,14 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) struct dc *dc; struct clk_mgr *clk_mgr; unsigned int i, num_audio = 1; + const struct link_hwss *link_hwss; if (!pipe_ctx->stream) return; dc = pipe_ctx->stream->ctx->dc; clk_mgr = dc->clk_mgr; + link_hwss = get_link_hwss(pipe_ctx->stream->link, &pipe_ctx->link_res); if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true) return; @@ -1103,56 +1095,35 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa) /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ clk_mgr->funcs->enable_pme_wa(clk_mgr); - /* un-mute audio */ - /* TODO: audio should be per stream rather than per link */ - if (is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_res.hpo_dp_stream_enc, false); - else - pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_res.stream_enc, false); + + link_hwss->enable_audio_packet(pipe_ctx); + if (pipe_ctx->stream_res.audio) pipe_ctx->stream_res.audio->enabled = true; } - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM); } void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) { struct dc *dc; struct clk_mgr *clk_mgr; + const struct link_hwss *link_hwss; if (!pipe_ctx || !pipe_ctx->stream) return; dc = pipe_ctx->stream->ctx->dc; clk_mgr = dc->clk_mgr; + link_hwss = get_link_hwss(pipe_ctx->stream->link, &pipe_ctx->link_res); if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false) return; - if (is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_res.hpo_dp_stream_enc, true); - else - pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_res.stream_enc, true); + link_hwss->disable_audio_packet(pipe_ctx); + if (pipe_ctx->stream_res.audio) { pipe_ctx->stream_res.audio->enabled = false; - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - if (is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable( - pipe_ctx->stream_res.hpo_dp_stream_enc); - else - pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( - pipe_ctx->stream_res.stream_enc); - else - pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( - pipe_ctx->stream_res.stream_enc); - if (clk_mgr->funcs->enable_pme_wa) /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ clk_mgr->funcs->enable_pme_wa(clk_mgr); @@ -1163,9 +1134,6 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) * stream->stream_engine_id); */ } - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM); } void dce110_disable_stream(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index a7e0001a8f46..1ac0ed5be605 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2601,14 +2601,6 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) if (dc->hwseq->funcs.set_pixels_per_cycle) dc->hwseq->funcs.set_pixels_per_cycle(pipe_ctx); - - /* enable audio only within mode set */ - if (pipe_ctx->stream_res.audio != NULL) { - if (is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.hpo_dp_stream_enc); - else if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); - } } void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c index de5e18c2a3ac..2cec7131a96f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c @@ -134,8 +134,6 @@ static void apg31_se_audio_setup( /* Disable forced mem power off */ REG_UPDATE(APG_MEM_PWR, APG_MEM_PWR_FORCE, 0); - - apg31_enable(apg); } static void apg31_audio_mute_control( diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 89964c980b87..7a2c8bc280d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -79,6 +79,8 @@ struct link_hwss { void (*disable_link_output)(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); + void (*enable_audio_packet)(struct pipe_ctx *pipe_ctx); + void (*disable_audio_packet)(struct pipe_ctx *pipe_ctx); }; #endif /* __DC_LINK_HWSS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c index 4227adbc646a..fcc3ce2b8fbf 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c @@ -170,11 +170,46 @@ static void update_dio_stream_allocation_table(struct dc_link *link, link_enc->funcs->update_mst_stream_allocation_table(link_enc, table); } +void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx) +{ + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable( + pipe_ctx->stream_res.stream_enc); + + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, false); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, + DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM); +} + +void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx) +{ + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, true); + + if (pipe_ctx->stream_res.audio) { + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( + pipe_ctx->stream_res.stream_enc); + else + pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( + pipe_ctx->stream_res.stream_enc); + } + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, + DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM); +} + static const struct link_hwss dio_link_hwss = { .setup_stream_encoder = setup_dio_stream_encoder, .reset_stream_encoder = reset_dio_stream_encoder, .setup_stream_attribute = setup_dio_stream_attribute, .disable_link_output = disable_dio_link_output, + .enable_audio_packet = enable_dio_audio_packet, + .disable_audio_packet = disable_dio_audio_packet, .ext = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, .enable_dp_link_output = enable_dio_dp_link_output, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h index 126d37f847a1..006830376e7d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h @@ -50,5 +50,7 @@ void set_dio_dp_lane_settings(struct dc_link *link, const struct link_resource *link_res, const struct dc_link_settings *link_settings, const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); +void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx); +void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx); #endif /* __LINK_HWSS_DIO_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c index 64f7ea6a9aa3..f81949221e0d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c @@ -57,6 +57,8 @@ static const struct link_hwss dpia_link_hwss = { .reset_stream_encoder = reset_dio_stream_encoder, .setup_stream_attribute = setup_dio_stream_attribute, .disable_link_output = disable_dio_link_output, + .enable_audio_packet = enable_dio_audio_packet, + .disable_audio_packet = disable_dio_audio_packet, .ext = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, .enable_dp_link_output = enable_dio_dp_link_output, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c index 153a88381f2c..668a66832579 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c @@ -262,11 +262,26 @@ static void update_hpo_dp_stream_allocation_table(struct dc_link *link, table); } +static void enable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx) +{ + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable( + pipe_ctx->stream_res.hpo_dp_stream_enc); +} + +static void disable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx->stream_res.audio) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable( + pipe_ctx->stream_res.hpo_dp_stream_enc); +} + static const struct link_hwss hpo_dp_link_hwss = { .setup_stream_encoder = setup_hpo_dp_stream_encoder, .reset_stream_encoder = reset_hpo_dp_stream_encoder, .setup_stream_attribute = setup_hpo_dp_stream_attribute, .disable_link_output = disable_hpo_dp_link_output, + .enable_audio_packet = enable_hpo_dp_audio_packet, + .disable_audio_packet = disable_hpo_dp_audio_packet, .ext = { .set_throttled_vcp_size = set_hpo_dp_throttled_vcp_size, .set_hblank_min_symbol_width = set_hpo_dp_hblank_min_symbol_width, -- cgit v1.2.3 From c859181cfeacf87336fc385c5665444f0e59eafe Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 20 Oct 2022 11:46:33 -0400 Subject: drm/amd/display: move stream encoder audio setup to link_hwss Unify stream encoder audio setup interface. Tested-by: Mark Broadworth Reviewed-by: Charlene Liu Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 22 +++++----------------- drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 3 +++ .../gpu/drm/amd/display/dc/link/link_hwss_dio.c | 17 +++++++++++++++++ .../gpu/drm/amd/display/dc/link/link_hwss_dio.h | 2 ++ .../gpu/drm/amd/display/dc/link/link_hwss_dpia.c | 1 + .../gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c | 10 ++++++++++ 6 files changed, 38 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a34bc631be00..c5380ce70653 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1455,6 +1455,9 @@ static enum dc_status apply_single_controller_ctx_to_hw( unsigned int event_triggers = 0; struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; struct dce_hwseq *hws = dc->hwseq; + const struct link_hwss *link_hwss = get_link_hwss( + link, &pipe_ctx->link_res); + if (hws->funcs.disable_stream_gating) { hws->funcs.disable_stream_gating(dc, pipe_ctx); @@ -1465,23 +1468,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( build_audio_output(context, pipe_ctx, &audio_output); - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - if (is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup( - pipe_ctx->stream_res.hpo_dp_stream_enc, - pipe_ctx->stream_res.audio->inst, - &pipe_ctx->stream->audio_info); - else - pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( - pipe_ctx->stream_res.stream_enc, - pipe_ctx->stream_res.audio->inst, - &pipe_ctx->stream->audio_info); - else - pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( - pipe_ctx->stream_res.stream_enc, - pipe_ctx->stream_res.audio->inst, - &pipe_ctx->stream->audio_info, - &audio_output.crtc_info); + link_hwss->setup_audio_output(pipe_ctx, &audio_output, + pipe_ctx->stream_res.audio->inst); pipe_ctx->stream_res.audio->funcs->az_configure( pipe_ctx->stream_res.audio, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 7a2c8bc280d5..0f69946cce9f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -38,6 +38,7 @@ struct link_resource; struct pipe_ctx; struct encoder_set_dp_phy_pattern_param; struct link_mst_stream_allocation_table; +struct audio_output; struct link_hwss_ext { /* function pointers below may require to check for NULL if caller @@ -79,6 +80,8 @@ struct link_hwss { void (*disable_link_output)(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); + void (*setup_audio_output)(struct pipe_ctx *pipe_ctx, + struct audio_output *audio_output, uint32_t audio_inst); void (*enable_audio_packet)(struct pipe_ctx *pipe_ctx); void (*disable_audio_packet)(struct pipe_ctx *pipe_ctx); }; diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c index fcc3ce2b8fbf..33148b753c03 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c @@ -170,6 +170,22 @@ static void update_dio_stream_allocation_table(struct dc_link *link, link_enc->funcs->update_mst_stream_allocation_table(link_enc, table); } +void setup_dio_audio_output(struct pipe_ctx *pipe_ctx, + struct audio_output *audio_output, uint32_t audio_inst) +{ + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_res.stream_enc, + audio_inst, + &pipe_ctx->stream->audio_info); + else + pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_res.stream_enc, + audio_inst, + &pipe_ctx->stream->audio_info, + &audio_output->crtc_info); +} + void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) @@ -208,6 +224,7 @@ static const struct link_hwss dio_link_hwss = { .reset_stream_encoder = reset_dio_stream_encoder, .setup_stream_attribute = setup_dio_stream_attribute, .disable_link_output = disable_dio_link_output, + .setup_audio_output = setup_dio_audio_output, .enable_audio_packet = enable_dio_audio_packet, .disable_audio_packet = disable_dio_audio_packet, .ext = { diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h index 006830376e7d..9a108c3d7831 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h @@ -50,6 +50,8 @@ void set_dio_dp_lane_settings(struct dc_link *link, const struct link_resource *link_res, const struct dc_link_settings *link_settings, const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); +void setup_dio_audio_output(struct pipe_ctx *pipe_ctx, + struct audio_output *audio_output, uint32_t audio_inst); void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx); void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c index f81949221e0d..861f3cd5b356 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c @@ -57,6 +57,7 @@ static const struct link_hwss dpia_link_hwss = { .reset_stream_encoder = reset_dio_stream_encoder, .setup_stream_attribute = setup_dio_stream_attribute, .disable_link_output = disable_dio_link_output, + .setup_audio_output = setup_dio_audio_output, .enable_audio_packet = enable_dio_audio_packet, .disable_audio_packet = disable_dio_audio_packet, .ext = { diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c index 668a66832579..2f46e1ac4ce0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c @@ -262,6 +262,15 @@ static void update_hpo_dp_stream_allocation_table(struct dc_link *link, table); } +static void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx, + struct audio_output *audio_output, uint32_t audio_inst) +{ + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_res.hpo_dp_stream_enc, + audio_inst, + &pipe_ctx->stream->audio_info); +} + static void enable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx) { pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable( @@ -280,6 +289,7 @@ static const struct link_hwss hpo_dp_link_hwss = { .reset_stream_encoder = reset_hpo_dp_stream_encoder, .setup_stream_attribute = setup_hpo_dp_stream_attribute, .disable_link_output = disable_hpo_dp_link_output, + .setup_audio_output = setup_hpo_dp_audio_output, .enable_audio_packet = enable_hpo_dp_audio_packet, .disable_audio_packet = disable_hpo_dp_audio_packet, .ext = { -- cgit v1.2.3 From 0094f042f2f88f6e0fea01f0753773a95cc975bd Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 20 Oct 2022 11:46:34 -0400 Subject: drm/amd/display: remove audio mute control in hpo dp VPG doesn't have the ability to mute audio output by sending all 0s in audio SDP. The existing implemention is disabling audio SDP instead. This is same as what dp_audio_enable does. Since it is no longer referenced by any callers, we decided to remove this interface for simplicity. Tested-by: Mark Broadworth Reviewed-by: Charlene Liu Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c | 11 ----------- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h | 4 ---- .../drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c | 9 --------- drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 3 --- 4 files changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c index 2cec7131a96f..24e9ff65434d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c @@ -136,19 +136,8 @@ static void apg31_se_audio_setup( REG_UPDATE(APG_MEM_PWR, APG_MEM_PWR_FORCE, 0); } -static void apg31_audio_mute_control( - struct apg *apg, - bool mute) -{ - if (mute) - apg31_disable(apg); - else - apg31_enable(apg); -} - static struct apg_funcs dcn31_apg_funcs = { .se_audio_setup = apg31_se_audio_setup, - .audio_mute_control = apg31_audio_mute_control, .enable_apg = apg31_enable, .disable_apg = apg31_disable, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h index 24f568e120d8..1b81f6773c53 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h @@ -84,10 +84,6 @@ struct apg_funcs { unsigned int az_inst, struct audio_info *audio_info); - void (*audio_mute_control)( - struct apg *apg, - bool mute); - void (*enable_apg)( struct apg *apg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c index 814f401db3b3..16639bd03adf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -600,14 +600,6 @@ static void dcn31_hpo_dp_stream_enc_map_stream_to_link( } } -static void dcn31_hpo_dp_stream_enc_mute_control( - struct hpo_dp_stream_encoder *enc, - bool mute) -{ - ASSERT(enc->apg); - enc->apg->funcs->audio_mute_control(enc->apg, mute); -} - static void dcn31_hpo_dp_stream_enc_audio_setup( struct hpo_dp_stream_encoder *enc, unsigned int az_inst, @@ -726,7 +718,6 @@ static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = { .stop_dp_info_packets = dcn31_hpo_dp_stream_enc_stop_dp_info_packets, .dp_set_dsc_pps_info_packet = dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet, .map_stream_to_link = dcn31_hpo_dp_stream_enc_map_stream_to_link, - .audio_mute_control = dcn31_hpo_dp_stream_enc_mute_control, .dp_audio_setup = dcn31_hpo_dp_stream_enc_audio_setup, .dp_audio_enable = dcn31_hpo_dp_stream_enc_audio_enable, .dp_audio_disable = dcn31_hpo_dp_stream_enc_audio_disable, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 42afa1952890..6b3e6de374bd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -317,9 +317,6 @@ struct hpo_dp_stream_encoder_funcs { uint32_t stream_enc_inst, uint32_t link_enc_inst); - void (*audio_mute_control)( - struct hpo_dp_stream_encoder *enc, bool mute); - void (*dp_audio_setup)( struct hpo_dp_stream_encoder *enc, unsigned int az_inst, -- cgit v1.2.3 From 174fc82410a8c75d3937320658fca5a240ca8176 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 20 Oct 2022 11:46:35 -0400 Subject: drm/amd/display: correctly populate dcn315 clock table Fix incorrect pstate read order as well as min and max state logic. Tested-by: Mark Broadworth Reviewed-by: Charlene Liu Acked-by: Rodrigo Siqueira Signed-off-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 71 +++++++--------------- 1 file changed, 23 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 893991a0eb97..07edd9777edf 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -458,19 +458,6 @@ static void dcn315_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, dcn315_smu_transfer_dpm_table_smu_2_dram(clk_mgr); } -static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks) -{ - uint32_t max = 0; - int i; - - for (i = 0; i < num_clocks; ++i) { - if (clocks[i] > max) - max = clocks[i]; - } - - return max; -} - static void dcn315_clk_mgr_helper_populate_bw_params( struct clk_mgr_internal *clk_mgr, struct integrated_info *bios_info, @@ -478,29 +465,21 @@ static void dcn315_clk_mgr_helper_populate_bw_params( { int i; struct clk_bw_params *bw_params = clk_mgr->base.bw_params; - uint32_t max_pstate = 0, max_fclk = 0, min_pstate = 0; + uint32_t max_pstate = clock_table->NumDfPstatesEnabled - 1; struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1]; - /* Find highest fclk pstate */ - for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) { - if (clock_table->DfPstateTable[i].FClk > max_fclk) { - max_fclk = clock_table->DfPstateTable[i].FClk; - max_pstate = i; - } - } - /* For 315 we want to base clock table on dcfclk, need at least one entry regardless of pmfw table */ for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) { int j; - uint32_t min_fclk = clock_table->DfPstateTable[0].FClk; - for (j = 1; j < clock_table->NumDfPstatesEnabled; j++) { - if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i] - && clock_table->DfPstateTable[j].FClk < min_fclk) { - min_fclk = clock_table->DfPstateTable[j].FClk; - min_pstate = j; - } + /* DF table is sorted with clocks decreasing */ + for (j = clock_table->NumDfPstatesEnabled - 2; j >= 0; j--) { + if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i]) + max_pstate = j; } + /* Max DCFCLK should match up with max pstate */ + if (i == clock_table->NumDcfClkLevelsEnabled - 1) + max_pstate = 0; /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */ for (j = bw_params->clk_table.num_entries - 1; j > 0; j--) @@ -511,9 +490,9 @@ static void dcn315_clk_mgr_helper_populate_bw_params( bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz; /* Now update clocks we do read */ - bw_params->clk_table.entries[i].fclk_mhz = min_fclk; - bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[min_pstate].MemClk; - bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[min_pstate].Voltage; + bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[max_pstate].FClk; + bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk; + bw_params->clk_table.entries[i].voltage = clock_table->SocVoltage[i]; bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i]; bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i]; bw_params->clk_table.entries[i].dispclk_mhz = clock_table->DispClocks[i]; @@ -521,25 +500,16 @@ static void dcn315_clk_mgr_helper_populate_bw_params( bw_params->clk_table.entries[i].wck_ratio = 1; } - /* Make sure to include at least one entry and highest pstate */ - if (max_pstate != min_pstate || i == 0) { - bw_params->clk_table.entries[i].fclk_mhz = max_fclk; - bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk; - bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[max_pstate].Voltage; - bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS); + /* Make sure to include at least one entry */ + if (i == 0) { + bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[0].FClk; + bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[0].MemClk; + bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[0].Voltage; + bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[0]; bw_params->clk_table.entries[i].wck_ratio = 1; i++; } - bw_params->clk_table.num_entries = i--; - - /* Make sure all highest clocks are included*/ - bw_params->clk_table.entries[i].socclk_mhz = find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS); - bw_params->clk_table.entries[i].dispclk_mhz = find_max_clk_value(clock_table->DispClocks, NUM_DISPCLK_DPM_LEVELS); - bw_params->clk_table.entries[i].dppclk_mhz = find_max_clk_value(clock_table->DppClocks, NUM_DPPCLK_DPM_LEVELS); - ASSERT(clock_table->DcfClocks[i] == find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS)); - bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz; - bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz; - bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; + bw_params->clk_table.num_entries = i; /* Set any 0 clocks to max default setting. Not an issue for * power since we aren't doing switching in such case anyway @@ -565,6 +535,11 @@ static void dcn315_clk_mgr_helper_populate_bw_params( if (!bw_params->clk_table.entries[i].dtbclk_mhz) bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; } + + /* Make sure all highest default clocks are included*/ + ASSERT(bw_params->clk_table.entries[i-1].phyclk_mhz == def_max.phyclk_mhz); + ASSERT(bw_params->clk_table.entries[i-1].phyclk_d18_mhz == def_max.phyclk_d18_mhz); + ASSERT(bw_params->clk_table.entries[i-1].dtbclk_mhz == def_max.dtbclk_mhz); ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz); bw_params->vram_type = bios_info->memory_type; bw_params->num_channels = bios_info->ma_channel_number; -- cgit v1.2.3 From bd829d5707730072fecc3267016a675a4789905b Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 20 Oct 2022 11:46:36 -0400 Subject: drm/amd/display: Refactor eDP PSR codes We split out PSR config from "global" to "per-panel" config settings. Tested-by: Mark Broadworth Reviewed-by: Robin Chen Acked-by: Rodrigo Siqueira Signed-off-by: Ian Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/dc_link.h | 14 +++++++++++--- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 15 +++++++++++++-- drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c | 14 +++++++++++++- drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c | 13 ++++++++++++- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 2 +- 11 files changed, 70 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bf938cda379a..e4e41f2e5054 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -764,7 +764,6 @@ struct dc_debug_options { bool disable_mem_low_power; bool pstate_enabled; bool disable_dmcu; - bool disable_psr; bool force_abm_enable; bool disable_stereo_support; bool vsr_support; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index caf0c7af2d0b..17f080f8af6c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -117,7 +117,7 @@ struct psr_settings { * Add a struct dc_panel_config under dc_link */ struct dc_panel_config { - // extra panel power sequence parameters + /* extra panel power sequence parameters */ struct pps { unsigned int extra_t3_ms; unsigned int extra_t7_ms; @@ -127,13 +127,21 @@ struct dc_panel_config { unsigned int extra_t12_ms; unsigned int extra_post_OUI_ms; } pps; - // ABM + /* PSR */ + struct psr { + bool disable_psr; + bool disallow_psrsu; + bool rc_disable; + bool rc_allow_static_screen; + bool rc_allow_fullscreen_VPB; + } psr; + /* ABM */ struct varib { unsigned int varibright_feature_enable; unsigned int def_varibright_level; unsigned int abm_config_setting; } varib; - // edp DSC + /* edp DSC */ struct dsc { bool disable_dsc_edp; unsigned int force_dsc_edp_policy; diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 887081472c0d..ce6c70e25703 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -671,12 +671,15 @@ static const struct dc_debug_options debug_defaults_diags = { .disable_pplib_wm_range = true, .disable_stutter = true, .disable_48mhz_pwrdwn = true, - .disable_psr = true, .enable_tri_buf = true, .use_max_lb = true }; static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, .ilr = { .optimize_edp_link_rate = true, }, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 020f512e9690..af4fe695535e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -723,7 +723,6 @@ static const struct dc_debug_options debug_defaults_drv = { .underflow_assert_delay_us = 0xFFFFFFFF, .dwb_fi_phase = -1, // -1 = disable, .dmub_command_table = true, - .disable_psr = false, .use_max_lb = true, .exit_idle_opt_for_cursor_updates = true }; @@ -742,11 +741,17 @@ static const struct dc_debug_options debug_defaults_diags = { .scl_reset_length10 = true, .dwb_fi_phase = -1, // -1 = disable .dmub_command_table = true, - .disable_psr = true, .enable_tri_buf = true, .use_max_lb = true }; +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, +}; + static void dcn30_dpp_destroy(struct dpp **dpp) { kfree(TO_DCN20_DPP(*dpp)); @@ -2212,6 +2217,11 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params } } +static void dcn30_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + static const struct resource_funcs dcn30_res_pool_funcs = { .destroy = dcn30_destroy_resource_pool, .link_enc_create = dcn30_link_encoder_create, @@ -2231,6 +2241,7 @@ static const struct resource_funcs dcn30_res_pool_funcs = { .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, .update_bw_bounding_box = dcn30_update_bw_bounding_box, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn30_get_panel_config_defaults, }; #define CTX ctx diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index b925b6ddde5a..d3945876aced 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -112,10 +112,16 @@ static const struct dc_debug_options debug_defaults_diags = { .dwb_fi_phase = -1, // -1 = disable .dmub_command_table = true, .enable_tri_buf = true, - .disable_psr = true, .use_max_lb = true }; +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, +}; + enum dcn302_clk_src_array_id { DCN302_CLK_SRC_PLL0, DCN302_CLK_SRC_PLL1, @@ -1132,6 +1138,11 @@ void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param DC_FP_END(); } +static void dcn302_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + static struct resource_funcs dcn302_res_pool_funcs = { .destroy = dcn302_destroy_resource_pool, .link_enc_create = dcn302_link_encoder_create, @@ -1151,6 +1162,7 @@ static struct resource_funcs dcn302_res_pool_funcs = { .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, .update_bw_bounding_box = dcn302_update_bw_bounding_box, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn302_get_panel_config_defaults, }; static struct dc_cap_funcs cap_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 527d5c902878..7e7f18bef098 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -96,7 +96,13 @@ static const struct dc_debug_options debug_defaults_diags = { .dwb_fi_phase = -1, // -1 = disable .dmub_command_table = true, .enable_tri_buf = true, - .disable_psr = true, +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, }; enum dcn303_clk_src_array_id { @@ -1055,6 +1061,10 @@ static void dcn303_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } +static void dcn303_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { @@ -1082,6 +1092,7 @@ static struct resource_funcs dcn303_res_pool_funcs = { .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, .update_bw_bounding_box = dcn303_update_bw_bounding_box, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn303_get_panel_config_defaults, }; static struct dc_cap_funcs cap_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index fddc21a5a04c..8729d6305996 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -911,6 +911,10 @@ static const struct dc_debug_options debug_defaults_diags = { }; static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, .ilr = { .optimize_edp_link_rate = true, }, diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index d0ad72caead2..92eb56873eee 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -937,6 +937,10 @@ static const struct dc_debug_options debug_defaults_diags = { }; static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, .ilr = { .optimize_edp_link_rate = true, }, diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index 58746c437554..31cbc5762eab 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -907,6 +907,10 @@ static const struct dc_debug_options debug_defaults_diags = { }; static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, .ilr = { .optimize_edp_link_rate = true, }, diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c index 6b40a11ac83a..af3eddc0cf32 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c @@ -906,6 +906,10 @@ static const struct dc_debug_options debug_defaults_diags = { }; static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, .ilr = { .optimize_edp_link_rate = true, }, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index d680f1c5b69f..ec2eae99b892 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -989,7 +989,7 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || optimized_min_dst_y_next_start_us > 5000) return DCN_ZSTATE_SUPPORT_ALLOW; - else if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && !dc->debug.disable_psr) + else if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr) return DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; else return DCN_ZSTATE_SUPPORT_DISALLOW; -- cgit v1.2.3 From 6be153dc8c88409e63309bcec300b03cd7bce9a7 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 20 Oct 2022 11:46:37 -0400 Subject: drm/amd/display: Convert documentation to a kernel-doc The dc_dmub_srv file has a lot of documentation associated with SubVP that could be converted to a kernel-doc. This commit just changes the comment style to a kernel-doc. Tested-by: Mark Broadworth Reviewed-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 124 +++++++++++---------------- 1 file changed, 48 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 0541e87e4f38..774e06936661 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -423,25 +423,20 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi #ifdef CONFIG_DRM_AMD_DC_DCN /** - * *********************************************************************************************** - * populate_subvp_cmd_drr_info: Helper to populate DRR pipe info for the DMCUB subvp command + * populate_subvp_cmd_drr_info - Helper to populate DRR pipe info for the DMCUB subvp command * - * Populate the DMCUB SubVP command with DRR pipe info. All the information required for calculating - * the SubVP + DRR microschedule is populated here. + * @dc: [in] current dc state + * @subvp_pipe: [in] pipe_ctx for the SubVP pipe + * @vblank_pipe: [in] pipe_ctx for the DRR pipe + * @pipe_data: [in] Pipe data which stores the VBLANK/DRR info + * + * Populate the DMCUB SubVP command with DRR pipe info. All the information + * required for calculating the SubVP + DRR microschedule is populated here. * * High level algorithm: * 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe * 2. Calculate the min and max vtotal which supports SubVP + DRR microschedule * 3. Populate the drr_info with the min and max supported vtotal values - * - * @param [in] dc: current dc state - * @param [in] subvp_pipe: pipe_ctx for the SubVP pipe - * @param [in] vblank_pipe: pipe_ctx for the DRR pipe - * @param [in] pipe_data: Pipe data which stores the VBLANK/DRR info - * - * @return: void - * - * *********************************************************************************************** */ static void populate_subvp_cmd_drr_info(struct dc *dc, struct pipe_ctx *subvp_pipe, @@ -493,22 +488,18 @@ static void populate_subvp_cmd_drr_info(struct dc *dc, } /** - * *********************************************************************************************** - * populate_subvp_cmd_vblank_pipe_info: Helper to populate VBLANK pipe info for the DMUB subvp command + * populate_subvp_cmd_vblank_pipe_info - Helper to populate VBLANK pipe info for the DMUB subvp command * - * Populate the DMCUB SubVP command with VBLANK pipe info. All the information required to calculate - * the microschedule for SubVP + VBLANK case is stored in the pipe_data (subvp_data and vblank_data). - * Also check if the VBLANK pipe is a DRR display -- if it is make a call to populate drr_info. + * @dc: [in] current dc state + * @context: [in] new dc state + * @cmd: [in] DMUB cmd to be populated with SubVP info + * @vblank_pipe: [in] pipe_ctx for the VBLANK pipe + * @cmd_pipe_index: [in] index for the pipe array in DMCUB SubVP cmd * - * @param [in] dc: current dc state - * @param [in] context: new dc state - * @param [in] cmd: DMUB cmd to be populated with SubVP info - * @param [in] vblank_pipe: pipe_ctx for the VBLANK pipe - * @param [in] cmd_pipe_index: index for the pipe array in DMCUB SubVP cmd - * - * @return: void - * - * *********************************************************************************************** + * Populate the DMCUB SubVP command with VBLANK pipe info. All the information + * required to calculate the microschedule for SubVP + VBLANK case is stored in + * the pipe_data (subvp_data and vblank_data). Also check if the VBLANK pipe + * is a DRR display -- if it is make a call to populate drr_info. */ static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc, struct dc_state *context, @@ -551,22 +542,18 @@ static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc, } /** - * *********************************************************************************************** - * update_subvp_prefetch_end_to_mall_start: Helper for SubVP + SubVP case - * - * For SubVP + SubVP, we use a single vertical interrupt to start the microschedule for both - * SubVP pipes. In order for this to work correctly, the MALL REGION of both SubVP pipes must - * start at the same time. This function lengthens the prefetch end to mall start delay of the - * SubVP pipe that has the shorter prefetch so that both MALL REGION's will start at the same time. - * - * @param [in] dc: current dc state - * @param [in] context: new dc state - * @param [in] cmd: DMUB cmd to be populated with SubVP info - * @param [in] subvp_pipes: Array of SubVP pipes (should always be length 2) + * update_subvp_prefetch_end_to_mall_start - Helper for SubVP + SubVP case * - * @return: void + * @dc: [in] current dc state + * @context: [in] new dc state + * @cmd: [in] DMUB cmd to be populated with SubVP info + * @subvp_pipes: [in] Array of SubVP pipes (should always be length 2) * - * *********************************************************************************************** + * For SubVP + SubVP, we use a single vertical interrupt to start the + * microschedule for both SubVP pipes. In order for this to work correctly, the + * MALL REGION of both SubVP pipes must start at the same time. This function + * lengthens the prefetch end to mall start delay of the SubVP pipe that has + * the shorter prefetch so that both MALL REGION's will start at the same time. */ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc, struct dc_state *context, @@ -608,22 +595,17 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc, } /** - * *************************************************************************************** - * setup_subvp_dmub_command: Helper to populate the SubVP pipe info for the DMUB subvp command + * setup_subvp_dmub_command - Helper to populate the SubVP pipe info for the DMUB subvp command * - * Populate the DMCUB SubVP command with SubVP pipe info. All the information required to - * calculate the microschedule for the SubVP pipe is stored in the pipe_data of the DMCUB - * SubVP command. + * @dc: [in] current dc state + * @context: [in] new dc state + * @cmd: [in] DMUB cmd to be populated with SubVP info + * @subvp_pipe: [in] pipe_ctx for the SubVP pipe + * @cmd_pipe_index: [in] index for the pipe array in DMCUB SubVP cmd * - * @param [in] dc: current dc state - * @param [in] context: new dc state - * @param [in] cmd: DMUB cmd to be populated with SubVP info - * @param [in] subvp_pipe: pipe_ctx for the SubVP pipe - * @param [in] cmd_pipe_index: index for the pipe array in DMCUB SubVP cmd - * - * @return: void - * - * *************************************************************************************** + * Populate the DMCUB SubVP command with SubVP pipe info. All the information + * required to calculate the microschedule for the SubVP pipe is stored in the + * pipe_data of the DMCUB SubVP command. */ static void populate_subvp_cmd_pipe_info(struct dc *dc, struct dc_state *context, @@ -703,19 +685,14 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc, } /** - * *************************************************************************************** - * dc_dmub_setup_subvp_dmub_command: Populate the DMCUB SubVP command - * - * This function loops through each pipe and populates the DMUB - * SubVP CMD info based on the pipe (e.g. SubVP, VBLANK). - * - * @param [in] dc: current dc state - * @param [in] context: new dc state - * @param [in] cmd: DMUB cmd to be populated with SubVP info + * dc_dmub_setup_subvp_dmub_command - Populate the DMCUB SubVP command * - * @return: void + * @dc: [in] current dc state + * @context: [in] new dc state + * @cmd: [in] DMUB cmd to be populated with SubVP info * - * *************************************************************************************** + * This function loops through each pipe and populates the DMUB SubVP CMD info + * based on the pipe (e.g. SubVP, VBLANK). */ void dc_dmub_setup_subvp_dmub_command(struct dc *dc, struct dc_state *context, @@ -962,19 +939,14 @@ static void dc_build_cursor_attribute_update_payload1( } /** - * *************************************************************************************** - * dc_send_update_cursor_info_to_dmu: Populate the DMCUB Cursor update info command + * dc_send_update_cursor_info_to_dmu - Populate the DMCUB Cursor update info command * - * This function would store the cursor related information and pass it into dmub + * @pCtx: [in] pipe context + * @pipe_idx: [in] pipe index * - * @param [in] pCtx: pipe context - * @param [in] pipe_idx: pipe index - * - * @return: void - * - * *************************************************************************************** + * This function would store the cursor related information and pass it into + * dmub */ - void dc_send_update_cursor_info_to_dmu( struct pipe_ctx *pCtx, uint8_t pipe_idx) { -- cgit v1.2.3 From f1943a51f0f9ce732e344fffb576b54f3e230a4d Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 20 Oct 2022 11:46:38 -0400 Subject: drm/amd/display: Add events log to trace OPTC lock and unlock As an attempt to offer more DCN debug tools for cases where the OPTC can hang, this commit introduces a trace event responsible for showing OPTC status when it requests lock and unlock. Tested-by: Mark Broadworth Reviewed-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h | 64 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_trace.h | 2 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 5 ++ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c | 9 +++ 4 files changed, 80 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h index d3bc9dc21771..0f580ea37576 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h @@ -37,6 +37,7 @@ #include #include #include +#include "dcn10/dcn10_optc.h" #include "dc/inc/core_types.h" @@ -662,6 +663,69 @@ TRACE_EVENT(dcn_fpu, ) ); +TRACE_EVENT(dcn_optc_lock_unlock_state, + TP_PROTO(const struct optc *optc_state, int instance, bool lock, const char *function, const int line), + TP_ARGS(optc_state, instance, lock, function, line), + + TP_STRUCT__entry( + __field(const char *, function) + __field(int, instance) + __field(bool, lock) + __field(int, line) + __field(int, opp_count) + __field(int, max_h_total) + __field(int, max_v_total) + __field(int, min_h_blank) + __field(int, min_h_sync_width) + __field(int, min_v_sync_width) + __field(int, min_v_blank) + __field(int, min_v_blank_interlace) + __field(int, vstartup_start) + __field(int, vupdate_offset) + __field(int, vupdate_width) + __field(int, vready_offset) + ), + TP_fast_assign( + __entry->function = function; + __entry->instance = instance; + __entry->lock = lock; + __entry->line = line; + __entry->opp_count = optc_state->opp_count; + __entry->max_h_total = optc_state->max_h_total; + __entry->max_v_total = optc_state->max_v_total; + __entry->min_h_blank = optc_state->min_h_blank; + __entry->min_h_sync_width = optc_state->min_h_sync_width; + __entry->min_v_sync_width = optc_state->min_v_sync_width; + __entry->min_v_blank = optc_state->min_v_blank; + __entry->min_v_blank_interlace = optc_state->min_v_blank_interlace; + __entry->vstartup_start = optc_state->vstartup_start; + __entry->vupdate_offset = optc_state->vupdate_offset; + __entry->vupdate_width = optc_state->vupdate_width; + __entry->vready_offset = optc_state->vupdate_offset; + ), + TP_printk("%s: %s()+%d: optc_instance=%d opp_count=%d max_h_total=%d max_v_total=%d " + "min_h_blank=%d min_h_sync_width=%d min_v_sync_width=%d min_v_blank=%d " + "min_v_blank_interlace=%d vstartup_start=%d vupdate_offset=%d vupdate_width=%d " + "vready_offset=%d", + __entry->lock ? "Lock" : "Unlock", + __entry->function, + __entry->line, + __entry->instance, + __entry->opp_count, + __entry->max_h_total, + __entry->max_v_total, + __entry->min_h_blank, + __entry->min_h_sync_width, + __entry->min_v_sync_width, + __entry->min_v_blank, + __entry->min_v_blank_interlace, + __entry->vstartup_start, + __entry->vupdate_offset, + __entry->vupdate_width, + __entry->vready_offset + ) +); + #endif /* _AMDGPU_DM_TRACE_H_ */ #undef TRACE_INCLUDE_PATH diff --git a/drivers/gpu/drm/amd/display/dc/dc_trace.h b/drivers/gpu/drm/amd/display/dc/dc_trace.h index c711797e5c9e..bbec308a3a5e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_trace.h +++ b/drivers/gpu/drm/amd/display/dc/dc_trace.h @@ -40,3 +40,5 @@ #define TRACE_DCN_FPU(begin, function, line, ref_count) \ trace_dcn_fpu(begin, function, line, ref_count) +#define TRACE_OPTC_LOCK_UNLOCK_STATE(optc, inst, lock) \ + trace_dcn_optc_lock_unlock_state(optc, inst, lock, __func__, __LINE__) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 33d780218790..c9e53dc49c92 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -27,6 +27,7 @@ #include "reg_helper.h" #include "dcn10_optc.h" #include "dc.h" +#include "dc_trace.h" #define REG(reg)\ optc1->tg_regs->reg @@ -657,6 +658,8 @@ void optc1_lock(struct timing_generator *optc) REG_WAIT(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1, 1, 10); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); } void optc1_unlock(struct timing_generator *optc) @@ -665,6 +668,8 @@ void optc1_unlock(struct timing_generator *optc) REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 0); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, false); } void optc1_get_position(struct timing_generator *optc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c index 892d3c4d01a1..867d60151aeb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c @@ -30,6 +30,7 @@ #include "dc_dmub_srv.h" #include "dml/dcn30/dcn30_fpu.h" +#include "dc_trace.h" #define REG(reg)\ optc1->tg_regs->reg @@ -58,6 +59,8 @@ void optc3_triplebuffer_lock(struct timing_generator *optc) REG_WAIT(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1, 1, 10); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); } void optc3_lock_doublebuffer_enable(struct timing_generator *optc) @@ -93,6 +96,8 @@ void optc3_lock_doublebuffer_enable(struct timing_generator *optc) MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); } void optc3_lock_doublebuffer_disable(struct timing_generator *optc) @@ -108,6 +113,8 @@ void optc3_lock_doublebuffer_disable(struct timing_generator *optc) REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0); REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 0); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); } void optc3_lock(struct timing_generator *optc) @@ -122,6 +129,8 @@ void optc3_lock(struct timing_generator *optc) REG_WAIT(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1, 1, 10); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); } void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest) -- cgit v1.2.3 From b473bd5fc333ab02479444dd4a51be5f5e324d97 Mon Sep 17 00:00:00 2001 From: Lewis Huang Date: Thu, 20 Oct 2022 11:46:39 -0400 Subject: drm/amd/display: refine wake up aux in retrieve link caps [Why] Read set_power_state dpcd after HPD cause USB4 CTS 4.2.1.1 [How] Read LTTPR caps first. If aux channel not ready, wake up aux channel. If wake up aux channel return pass, retrieve lttpr caps again. If wake up aux channel return false, register a detection retry timer. Tested-by: Mark Broadworth Reviewed-by: Wenjing Liu Acked-by: Rodrigo Siqueira Signed-off-by: Lewis Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 148 ++++++----------------- drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 2 +- 2 files changed, 41 insertions(+), 109 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index bd4cbe02d353..420119efcf5f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -5031,7 +5031,7 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) return true; } -bool dp_retrieve_lttpr_cap(struct dc_link *link) +enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) { uint8_t lttpr_dpcd_data[8]; enum dc_status status = DC_ERROR_UNEXPECTED; @@ -5099,7 +5099,7 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present); - return is_lttpr_present; + return status; } bool dp_is_lttpr_present(struct dc_link *link) @@ -5227,76 +5227,45 @@ static void retrieve_cable_id(struct dc_link *link) &link->dpcd_caps.cable_id, &usbc_cable_id); } -/* DPRX may take some time to respond to AUX messages after HPD asserted. - * If AUX read unsuccessful, try to wake unresponsive DPRX by toggling DPCD SET_POWER (0x600). - */ -static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout_ms) +enum dc_status wake_up_aux_channel(struct dc_link *link) { enum dc_status status = DC_ERROR_UNEXPECTED; - uint8_t dpcd_data = 0; - uint64_t start_ts = 0; - uint64_t current_ts = 0; - uint64_t time_taken_ms = 0; - enum dc_connection_type type = dc_connection_none; - bool lttpr_present; - bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; + uint32_t aux_channel_retry_cnt = 0; + uint8_t dpcd_power_state = '\0'; - lttpr_present = dp_is_lttpr_present(link) || - (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support); - DC_LOG_DC("lttpr_present = %d.\n", lttpr_present ? 1 : 0); + while (status != DC_OK && aux_channel_retry_cnt < 10) { + status = core_link_read_dpcd(link, DP_SET_POWER, + &dpcd_power_state, sizeof(dpcd_power_state)); - /* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to - * be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read. - */ - if (lttpr_present) - status = core_link_read_dpcd( - link, - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, - &dpcd_data, - sizeof(dpcd_data)); - else - status = core_link_read_dpcd( - link, - DP_SET_POWER, - &dpcd_data, - sizeof(dpcd_data)); + /* Delay 1 ms if AUX CH is in power down state. Based on spec + * section 2.3.1.2, if AUX CH may be powered down due to + * write to DPCD 600h = 2. Sink AUX CH is monitoring differential + * signal and may need up to 1 ms before being able to reply. + */ + if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) { + udelay(1000); + aux_channel_retry_cnt++; + } + } if (status != DC_OK) { - DC_LOG_WARNING("%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms.", - __func__, - timeout_ms); - start_ts = dm_get_timestamp(link->ctx); - - do { - if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) - break; - - dpcd_data = DP_SET_POWER_D3; - status = core_link_write_dpcd( - link, - DP_SET_POWER, - &dpcd_data, - sizeof(dpcd_data)); - - dpcd_data = DP_SET_POWER_D0; - status = core_link_write_dpcd( - link, - DP_SET_POWER, - &dpcd_data, - sizeof(dpcd_data)); - - current_ts = dm_get_timestamp(link->ctx); - time_taken_ms = div_u64(dm_get_elapse_time_in_ns(link->ctx, current_ts, start_ts), 1000000); - } while (status != DC_OK && time_taken_ms < timeout_ms); + dpcd_power_state = DP_SET_POWER_D0; + status = core_link_write_dpcd( + link, + DP_SET_POWER, + &dpcd_power_state, + sizeof(dpcd_power_state)); - DC_LOG_WARNING("%s: DPCD SET_POWER %s after %lld ms%s", - __func__, - (status == DC_OK) ? "succeeded" : "failed", - time_taken_ms, - (type == dc_connection_none) ? ". Unplugged." : "."); + dpcd_power_state = DP_SET_POWER_D3; + status = core_link_write_dpcd( + link, + DP_SET_POWER, + &dpcd_power_state, + sizeof(dpcd_power_state)); + return DC_ERROR_UNEXPECTED; } - return status; + return DC_OK; } static bool retrieve_link_cap(struct dc_link *link) @@ -5308,7 +5277,6 @@ static bool retrieve_link_cap(struct dc_link *link) /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST. */ uint8_t dpcd_dprx_data = '\0'; - uint8_t dpcd_power_state = '\0'; struct dp_device_vendor_id sink_id; union down_stream_port_count down_strm_port_count; @@ -5316,11 +5284,9 @@ static bool retrieve_link_cap(struct dc_link *link) union dp_downstream_port_present ds_port = { 0 }; enum dc_status status = DC_ERROR_UNEXPECTED; uint32_t read_dpcd_retry_cnt = 3; - uint32_t aux_channel_retry_cnt = 0; int i; struct dp_sink_hw_fw_revision dp_hw_fw_revision; const uint32_t post_oui_delay = 30; // 30ms - bool is_lttpr_present = false; memset(dpcd_data, '\0', sizeof(dpcd_data)); memset(&down_strm_port_count, @@ -5335,51 +5301,17 @@ static bool retrieve_link_cap(struct dc_link *link) dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD); - /* Try to ensure AUX channel active before proceeding. */ - if (link->dc->debug.aux_wake_wa.bits.enable_wa) { - uint64_t timeout_ms = link->dc->debug.aux_wake_wa.bits.timeout_ms; - - if (link->dc->debug.aux_wake_wa.bits.use_default_timeout) - timeout_ms = LINK_AUX_WAKE_TIMEOUT_MS; - status = wa_try_to_wake_dprx(link, timeout_ms); - } - - while (status != DC_OK && aux_channel_retry_cnt < 10) { - status = core_link_read_dpcd(link, DP_SET_POWER, - &dpcd_power_state, sizeof(dpcd_power_state)); - - /* Delay 1 ms if AUX CH is in power down state. Based on spec - * section 2.3.1.2, if AUX CH may be powered down due to - * write to DPCD 600h = 2. Sink AUX CH is monitoring differential - * signal and may need up to 1 ms before being able to reply. - */ - if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) { - udelay(1000); - aux_channel_retry_cnt++; - } - } + status = dp_retrieve_lttpr_cap(link); - /* If aux channel is not active, return false and trigger another detect*/ if (status != DC_OK) { - dpcd_power_state = DP_SET_POWER_D0; - status = core_link_write_dpcd( - link, - DP_SET_POWER, - &dpcd_power_state, - sizeof(dpcd_power_state)); - - dpcd_power_state = DP_SET_POWER_D3; - status = core_link_write_dpcd( - link, - DP_SET_POWER, - &dpcd_power_state, - sizeof(dpcd_power_state)); - return false; + status = wake_up_aux_channel(link); + if (status == DC_OK) + dp_retrieve_lttpr_cap(link); + else + return false; } - is_lttpr_present = dp_retrieve_lttpr_cap(link); - - if (is_lttpr_present) + if (dp_is_lttpr_present(link)) configure_lttpr_mode_transparent(link); /* Read DP tunneling information. */ @@ -5406,7 +5338,7 @@ static bool retrieve_link_cap(struct dc_link *link) return false; } - if (!is_lttpr_present) + if (!dp_is_lttpr_present(link)) dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); { diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index b304d450b038..e8d8c5cb1309 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -193,7 +193,7 @@ enum dc_status dpcd_configure_lttpr_mode( struct link_training_settings *lt_settings); enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings); -bool dp_retrieve_lttpr_cap(struct dc_link *link); +enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link); bool dp_is_lttpr_present(struct dc_link *link); enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, struct dc_link_settings *link_setting); void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override); -- cgit v1.2.3 From 12024b17617af9b953cf8801a6a3d3c769ebd06f Mon Sep 17 00:00:00 2001 From: wangjianli Date: Sat, 22 Oct 2022 14:01:55 +0800 Subject: amd/amdgpu: fix repeated words in comments Delete the redundant word 'the'. Signed-off-by: wangjianli Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ddaecb2610c9..6f958603c8cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1568,7 +1568,7 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) * @pdev: pci dev pointer * @state: vga_switcheroo state * - * Callback for the switcheroo driver. Suspends or resumes the + * Callback for the switcheroo driver. Suspends or resumes * the asics before or after it is powered up using ACPI methods. */ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, -- cgit v1.2.3 From 31bc2485e88537009fad9246bf48319fc9172230 Mon Sep 17 00:00:00 2001 From: wangjianli Date: Sat, 22 Oct 2022 14:04:17 +0800 Subject: drm/radeon: fix repeated words in comments Delete the redundant word 'the'. Signed-off-by: wangjianli Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index a556b6be1137..262e2bcb30c3 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1207,7 +1207,7 @@ static void radeon_check_arguments(struct radeon_device *rdev) * @pdev: pci dev pointer * @state: vga_switcheroo state * - * Callback for the switcheroo driver. Suspends or resumes the + * Callback for the switcheroo driver. Suspends or resumes * the asics before or after it is powered up using ACPI methods. */ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) -- cgit v1.2.3 From 93e28cf81406519622383ae51d6fd183b744ac46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20Ignacio=20Aramend=C3=ADa?= Date: Mon, 24 Oct 2022 08:33:59 -0300 Subject: drm/amd/display: Revert logic for plane modifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This file was split in commit 5d945cbcd4b16a29d6470a80dfb19738f9a4319f ("drm/amd/display: Create a file dedicated to planes") and the logic in dm_plane_format_mod_supported() function got changed by a switch logic. That change broke drm_plane modifiers setting on series 5000 APUs (tested on OXP mini AMD 5800U and HP Dev One 5850U PRO) leading to Gamescope not working as reported on GitHub[1] To reproduce the issue, enter a TTY and run: $ gamescope -- vkcube With said commit applied it will abort. This one restores the old logic, fixing the issue that affects Gamescope. [1](https://github.com/Plagman/gamescope/issues/624) Cc: # 6.0.x Signed-off-by: Joaquín Ignacio Aramendía Reviewed-by: Bas Nieuwenhuizen Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 50 +++------------------- 1 file changed, 7 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index dfd3be49eac8..e6854f7270a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -1369,7 +1369,7 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, { struct amdgpu_device *adev = drm_to_adev(plane->dev); const struct drm_format_info *info = drm_format_info(format); - struct hw_asic_id asic_id = adev->dm.dc->ctx->asic_id; + int i; enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3; @@ -1386,49 +1386,13 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, return true; } - /* check if swizzle mode is supported by this version of DCN */ - switch (asic_id.chip_family) { - case FAMILY_SI: - case FAMILY_CI: - case FAMILY_KV: - case FAMILY_CZ: - case FAMILY_VI: - /* asics before AI does not have modifier support */ - return false; - case FAMILY_AI: - case FAMILY_RV: - case FAMILY_NV: - case FAMILY_VGH: - case FAMILY_YELLOW_CARP: - case AMDGPU_FAMILY_GC_10_3_6: - case AMDGPU_FAMILY_GC_10_3_7: - switch (AMD_FMT_MOD_GET(TILE, modifier)) { - case AMD_FMT_MOD_TILE_GFX9_64K_R_X: - case AMD_FMT_MOD_TILE_GFX9_64K_D_X: - case AMD_FMT_MOD_TILE_GFX9_64K_S_X: - case AMD_FMT_MOD_TILE_GFX9_64K_D: - return true; - default: - return false; - } - break; - case AMDGPU_FAMILY_GC_11_0_0: - case AMDGPU_FAMILY_GC_11_0_1: - switch (AMD_FMT_MOD_GET(TILE, modifier)) { - case AMD_FMT_MOD_TILE_GFX11_256K_R_X: - case AMD_FMT_MOD_TILE_GFX9_64K_R_X: - case AMD_FMT_MOD_TILE_GFX9_64K_D_X: - case AMD_FMT_MOD_TILE_GFX9_64K_S_X: - case AMD_FMT_MOD_TILE_GFX9_64K_D: - return true; - default: - return false; - } - break; - default: - ASSERT(0); /* Unknown asic */ - break; + /* Check that the modifier is on the list of the plane's supported modifiers. */ + for (i = 0; i < plane->modifier_count; i++) { + if (modifier == plane->modifiers[i]) + break; } + if (i == plane->modifier_count) + return false; /* * For D swizzle the canonical modifier depends on the bpp, so check -- cgit v1.2.3 From d2c4c1569a7d7d5c8f75963bf2d62d7aeac30e2a Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 30 Sep 2022 10:43:08 +0530 Subject: drm/amdgpu: Remove ATC L2 access for MMHUB 2.1.x MMHUB 2.1.x versions don't have ATCL2. Remove accesses to ATCL2 registers. Since they are non-existing registers, read access will cause a 'Completer Abort' and gets reported when AER is enabled with the below patch. Tagging with the patch so that this is backported along with it. v2: squash in uninitialized warning fix (Nathan Chancellor) Fixes: 8795e182b02d ("PCI/portdrv: Don't disable AER reporting in get_port_device_capability()") Signed-off-by: Lijo Lazar Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 4d304f22889e..998b5d17b271 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -32,8 +32,6 @@ #include "gc/gc_10_1_0_offset.h" #include "soc15_common.h" -#define mmMM_ATC_L2_MISC_CG_Sienna_Cichlid 0x064d -#define mmMM_ATC_L2_MISC_CG_Sienna_Cichlid_BASE_IDX 0 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid 0x0070 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid_BASE_IDX 0 @@ -574,7 +572,6 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): - def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid); def1 = data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid); break; default: @@ -608,8 +605,6 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): - if (def != data) - WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid, data); if (def1 != data1) WREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid, data1); break; @@ -634,8 +629,8 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): - def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid); - break; + /* There is no ATCL2 in MMHUB for 2.1.x */ + return; default: def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG); break; @@ -646,18 +641,8 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade else data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK; - if (def != data) { - switch (adev->ip_versions[MMHUB_HWIP][0]) { - case IP_VERSION(2, 1, 0): - case IP_VERSION(2, 1, 1): - case IP_VERSION(2, 1, 2): - WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid, data); - break; - default: - WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data); - break; - } - } + if (def != data) + WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data); } static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, @@ -695,7 +680,10 @@ static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags) case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): - data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid); + /* There is no ATCL2 in MMHUB for 2.1.x. Keep the status + * based on DAGB + */ + data = MM_ATC_L2_MISC_CG__ENABLE_MASK; data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid); break; default: -- cgit v1.2.3 From 90bfee142af0f0e9d3bec80e7acd5f49b230acf7 Mon Sep 17 00:00:00 2001 From: Rafael Mendonca Date: Mon, 17 Oct 2022 22:27:50 -0300 Subject: drm/amdkfd: Fix memory leak in kfd_mem_dmamap_userptr() If the number of pages from the userptr BO differs from the SG BO then the allocated memory for the SG table doesn't get freed before returning -EINVAL, which may lead to a memory leak in some error paths. Fix this by checking the number of pages before allocating memory for the SG table. Fixes: 264fb4d332f5 ("drm/amdgpu: Add multi-GPU DMA mapping helpers") Signed-off-by: Rafael Mendonca Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 978d3970b5cc..84f44f7e4111 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -510,13 +510,13 @@ kfd_mem_dmamap_userptr(struct kgd_mem *mem, struct ttm_tt *ttm = bo->tbo.ttm; int ret; + if (WARN_ON(ttm->num_pages != src_ttm->num_pages)) + return -EINVAL; + ttm->sg = kmalloc(sizeof(*ttm->sg), GFP_KERNEL); if (unlikely(!ttm->sg)) return -ENOMEM; - if (WARN_ON(ttm->num_pages != src_ttm->num_pages)) - return -EINVAL; - /* Same sequence as in amdgpu_ttm_tt_pin_userptr */ ret = sg_alloc_table_from_pages(ttm->sg, src_ttm->pages, ttm->num_pages, 0, -- cgit v1.2.3 From 08841950db932dc3ba8bbd4c0f1f7f27ccfbae42 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 20 Oct 2022 15:25:25 +0800 Subject: drm/amd/pm: allow gfxoff on gc_11_0_3 allow gfxoff on gc_11_0_3 Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 671ca5a0f208..0fecc5bf45bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -5051,6 +5051,7 @@ static int gfx_v11_0_set_powergating_state(void *handle, switch (adev->ip_versions[GC_HWIP][0]) { case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 2): + case IP_VERSION(11, 0, 3): amdgpu_gfx_off_ctrl(adev, enable); break; case IP_VERSION(11, 0, 1): diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index feb4d68f3fd9..43fb102a65f5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -840,6 +840,7 @@ int smu_v13_0_gfx_off_control(struct smu_context *smu, bool enable) case IP_VERSION(13, 0, 5): case IP_VERSION(13, 0, 7): case IP_VERSION(13, 0, 8): + case IP_VERSION(13, 0, 10): if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) -- cgit v1.2.3 From ca08a1725d0d78efca8d2dbdbce5ea70355da0f2 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 6 Oct 2022 17:26:48 -0400 Subject: drm/amd/display: Remove wrong pipe control lock When using a device based on DCN32/321, we have an issue where a second 4k@60Hz display does not light up, and the system becomes unresponsive for a few minutes. In the debug process, it was possible to see a hang in the function dcn20_post_unlock_program_front_end in this part: for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000 && hubp->funcs->hubp_is_flip_pending(hubp); j++) mdelay(1); } The hubp_is_flip_pending always returns positive for waiting pending flips which is a symptom of pipe hang. Additionally, the dmesg log shows this message after a few minutes: BUG: soft lockup - CPU#4 stuck for 26s! ... [ +0.000003] dcn20_post_unlock_program_front_end+0x112/0x340 [amdgpu] [ +0.000171] dc_commit_state_no_check+0x63d/0xbf0 [amdgpu] [ +0.000155] ? dc_validate_global_state+0x358/0x3d0 [amdgpu] [ +0.000154] dc_commit_state+0xe2/0xf0 [amdgpu] This confirmed the hypothesis that we had a pipe hanging somewhere. Next, after checking the ftrace entries, we have the below weird sequence: [..] 2) | dcn10_lock_all_pipes [amdgpu]() { 2) 0.120 us | optc1_is_tg_enabled [amdgpu](); 2) | dcn20_pipe_control_lock [amdgpu]() { 2) | dc_dmub_srv_clear_inbox0_ack [amdgpu]() { 2) 0.121 us | amdgpu_dm_dmub_reg_write [amdgpu](); 2) 0.551 us | } 2) | dc_dmub_srv_send_inbox0_cmd [amdgpu]() { 2) 0.110 us | amdgpu_dm_dmub_reg_write [amdgpu](); 2) 0.511 us | } 2) | dc_dmub_srv_wait_for_inbox0_ack [amdgpu]() { 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); 2) 0.110 us | amdgpu_dm_dmub_reg_read [amdgpu](); [..] We are not expected to read from dmub register so many times and for so long. From the trace log, it was possible to identify that the function dcn20_pipe_control_lock was triggering the dmub operation when it was unnecessary and causing the hang issue. This commit drops the unnecessary dmub code and, consequently, fixes the second display not lighting up the issue. Tested-by: Daniel Wheeler Acked-by: Qingqing Zhuo Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index d732b6f031a1..a7e0001a8f46 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1270,16 +1270,6 @@ void dcn20_pipe_control_lock( lock, &hw_locks, &inst_flags); - } else if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN) { - union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 }; - hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK; - hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER; - hw_lock_cmd.bits.lock_pipe = 1; - hw_lock_cmd.bits.otg_inst = pipe->stream_res.tg->inst; - hw_lock_cmd.bits.lock = lock; - if (!lock) - hw_lock_cmd.bits.should_release = 1; - dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd); } else if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) { if (lock) pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); @@ -1856,7 +1846,7 @@ void dcn20_post_unlock_program_front_end( for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000 && hubp->funcs->hubp_is_flip_pending(hubp); j++) - mdelay(1); + udelay(1); } } -- cgit v1.2.3 From abe4d9f03fae76c9650b0d942faf6990b35c377b Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 6 Oct 2022 17:26:49 -0400 Subject: drm/amd/display: Don't return false if no stream pipe_ctx[i] exists even if the pipe is not in use. If the pipe is not in use it will always have a null stream, so don't return false in this case. Tested-by: Daniel Wheeler Reviewed-by: Rodrigo Siqueira Acked-by: Qingqing Zhuo Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index d51d0c40ae5b..b03a7814e96d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -200,7 +200,7 @@ bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc, struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; if (!pipe->stream) - return false; + continue; if (!pipe->plane_state) return false; -- cgit v1.2.3 From 68bc147363bd9769a07d1cbf5cbe2bb4573f4e3c Mon Sep 17 00:00:00 2001 From: David Francis Date: Fri, 16 Sep 2022 11:15:01 -0400 Subject: drm/amd: Add IMU fw version to fw version queries IMU is a new firmware for GFX11. There are four means by which firmware version can be queried from the driver: device attributes, vf2pf, debugfs, and the AMDGPU_INFO_FW_VERSION option in the amdgpu info ioctl. Add IMU as an option for those four methods. V2: Added debugfs Reviewed-by: Likun Gao Reviewed-by: Alex Deucher Signed-off-by: David Francis Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 13 +++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 4 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index fe23e09eec98..bf1ff8f0e712 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -344,6 +344,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, fw_info->ver = adev->mes.ucode_fw_version[1]; fw_info->feature = 0; break; + case AMDGPU_INFO_FW_IMU: + fw_info->ver = adev->gfx.imu_fw_version; + fw_info->feature = 0; + break; default: return -EINVAL; } @@ -1520,6 +1524,15 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused) fw_info.feature, fw_info.ver); } + /* IMU */ + query_fw.fw_type = AMDGPU_INFO_FW_IMU; + query_fw.index = 0; + ret = amdgpu_firmware_info(&fw_info, &query_fw, adev); + if (ret) + return ret; + seq_printf(m, "IMU feature version: %u, firmware version: 0x%08x\n", + fw_info.feature, fw_info.ver); + /* PSP SOS */ query_fw.fw_type = AMDGPU_INFO_FW_SOS; ret = amdgpu_firmware_info(&fw_info, &query_fw, adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index dd0bc649a57d..5cb62e6249c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -698,6 +698,7 @@ FW_VERSION_ATTR(rlc_srlg_fw_version, 0444, gfx.rlc_srlg_fw_version); FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version); FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version); FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version); +FW_VERSION_ATTR(imu_fw_version, 0444, gfx.imu_fw_version); FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version); FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_context.bin_desc.fw_version); FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.fw_version); @@ -719,7 +720,8 @@ static struct attribute *fw_attrs[] = { &dev_attr_ta_ras_fw_version.attr, &dev_attr_ta_xgmi_fw_version.attr, &dev_attr_smc_fw_version.attr, &dev_attr_sdma_fw_version.attr, &dev_attr_sdma2_fw_version.attr, &dev_attr_vcn_fw_version.attr, - &dev_attr_dmcu_fw_version.attr, NULL + &dev_attr_dmcu_fw_version.attr, &dev_attr_imu_fw_version.attr, + NULL }; static const struct attribute_group fw_attr_group = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 9c765b04aae3..c73abe54d974 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -547,6 +547,7 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev) POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_IMU, adev->gfx.imu_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd_context.bin_desc.fw_version); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h index e78e4c27b62a..6c97148ca0ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -70,6 +70,7 @@ enum amd_sriov_ucode_engine_id { AMD_SRIOV_UCODE_ID_RLC_SRLS, AMD_SRIOV_UCODE_ID_MEC, AMD_SRIOV_UCODE_ID_MEC2, + AMD_SRIOV_UCODE_ID_IMU, AMD_SRIOV_UCODE_ID_SOS, AMD_SRIOV_UCODE_ID_ASD, AMD_SRIOV_UCODE_ID_TA_RAS, -- cgit v1.2.3 From e105b6212f1f90c56c04439279d0ef0f8dd1c308 Mon Sep 17 00:00:00 2001 From: YuBiao Wang Date: Wed, 19 Oct 2022 11:36:32 +0800 Subject: drm/amdgpu: skip mes self test for gc 11.0.3 in recover Temporary disable mes self teset for gc 11.0.3 during gpu_recovery. Signed-off-by: YuBiao Wang Acked-by: Luben Tuikov Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index e0445e8cc342..5b8362727226 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -5381,7 +5381,7 @@ skip_hw_reset: drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res); } - if (adev->enable_mes) + if (adev->enable_mes && adev->ip_versions[GC_HWIP][0] != IP_VERSION(11, 0, 3)) amdgpu_mes_self_test(tmp_adev); if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) { -- cgit v1.2.3 From 9656db1b933caf6ffaaef10322093fe018359090 Mon Sep 17 00:00:00 2001 From: Prike Liang Date: Thu, 20 Oct 2022 14:44:26 +0800 Subject: drm/amdkfd: update gfx1037 Lx cache setting Update the gfx1037 L1/L2 cache setting. Signed-off-by: Prike Liang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 53 ++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index cd5f8b219bf9..d6fa787ff490 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -795,6 +795,54 @@ static struct kfd_gpu_cache_info yellow_carp_cache_info[] = { }, }; +static struct kfd_gpu_cache_info gfx1037_cache_info[] = { + { + /* TCP L1 Cache per CU */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 1, + }, + { + /* Scalar L1 Instruction Cache per SQC */ + .cache_size = 32, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_INST_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* Scalar L1 Data Cache per SQC */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* GL1 Data Cache per SA */ + .cache_size = 128, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* L2 Data Cache per GPU (Total Tex Cache) */ + .cache_size = 256, + .cache_level = 2, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, +}; + static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev, struct crat_subtype_computeunit *cu) { @@ -1515,10 +1563,13 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, break; case IP_VERSION(10, 3, 3): case IP_VERSION(10, 3, 6): /* TODO: Double check these on production silicon */ - case IP_VERSION(10, 3, 7): /* TODO: Double check these on production silicon */ pcache_info = yellow_carp_cache_info; num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info); break; + case IP_VERSION(10, 3, 7): + pcache_info = gfx1037_cache_info; + num_of_cache_types = ARRAY_SIZE(gfx1037_cache_info); + break; case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 2): -- cgit v1.2.3 From 969758bbf5e9360b63bbb2328ac3fda46bbbc9f5 Mon Sep 17 00:00:00 2001 From: Jesse Zhang Date: Tue, 11 Oct 2022 05:23:10 +0000 Subject: drm/amdkfd: correct the cache info for gfx1036 correct the cache information for gfx1036 Acked-by: Alex Deucher Reviewed-by: Yifan Zhang Signed-off-by: Yifan Zhang Signed-off-by: Jesse Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 53 ++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index d6fa787ff490..8bfdfd062ff6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -843,6 +843,54 @@ static struct kfd_gpu_cache_info gfx1037_cache_info[] = { }, }; +static struct kfd_gpu_cache_info gc_10_3_6_cache_info[] = { + { + /* TCP L1 Cache per CU */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 1, + }, + { + /* Scalar L1 Instruction Cache per SQC */ + .cache_size = 32, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_INST_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* Scalar L1 Data Cache per SQC */ + .cache_size = 16, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* GL1 Data Cache per SA */ + .cache_size = 128, + .cache_level = 1, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, + { + /* L2 Data Cache per GPU (Total Tex Cache) */ + .cache_size = 256, + .cache_level = 2, + .flags = (CRAT_CACHE_FLAGS_ENABLED | + CRAT_CACHE_FLAGS_DATA_CACHE | + CRAT_CACHE_FLAGS_SIMD_CACHE), + .num_cu_shared = 2, + }, +}; + static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev, struct crat_subtype_computeunit *cu) { @@ -1562,10 +1610,13 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, num_of_cache_types = ARRAY_SIZE(beige_goby_cache_info); break; case IP_VERSION(10, 3, 3): - case IP_VERSION(10, 3, 6): /* TODO: Double check these on production silicon */ pcache_info = yellow_carp_cache_info; num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info); break; + case IP_VERSION(10, 3, 6): + pcache_info = gc_10_3_6_cache_info; + num_of_cache_types = ARRAY_SIZE(gc_10_3_6_cache_info); + break; case IP_VERSION(10, 3, 7): pcache_info = gfx1037_cache_info; num_of_cache_types = ARRAY_SIZE(gfx1037_cache_info); -- cgit v1.2.3 From 809734c110548dca410fb0cca52e6b1540319f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20Ignacio=20Aramend=C3=ADa?= Date: Mon, 24 Oct 2022 08:33:59 -0300 Subject: drm/amd/display: Revert logic for plane modifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This file was split in commit 5d945cbcd4b16a29d6470a80dfb19738f9a4319f ("drm/amd/display: Create a file dedicated to planes") and the logic in dm_plane_format_mod_supported() function got changed by a switch logic. That change broke drm_plane modifiers setting on series 5000 APUs (tested on OXP mini AMD 5800U and HP Dev One 5850U PRO) leading to Gamescope not working as reported on GitHub[1] To reproduce the issue, enter a TTY and run: $ gamescope -- vkcube With said commit applied it will abort. This one restores the old logic, fixing the issue that affects Gamescope. [1](https://github.com/Plagman/gamescope/issues/624) Cc: # 6.0.x Signed-off-by: Joaquín Ignacio Aramendía Reviewed-by: Bas Nieuwenhuizen Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 50 +++------------------- 1 file changed, 7 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index dfd3be49eac8..e6854f7270a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -1369,7 +1369,7 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, { struct amdgpu_device *adev = drm_to_adev(plane->dev); const struct drm_format_info *info = drm_format_info(format); - struct hw_asic_id asic_id = adev->dm.dc->ctx->asic_id; + int i; enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3; @@ -1386,49 +1386,13 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, return true; } - /* check if swizzle mode is supported by this version of DCN */ - switch (asic_id.chip_family) { - case FAMILY_SI: - case FAMILY_CI: - case FAMILY_KV: - case FAMILY_CZ: - case FAMILY_VI: - /* asics before AI does not have modifier support */ - return false; - case FAMILY_AI: - case FAMILY_RV: - case FAMILY_NV: - case FAMILY_VGH: - case FAMILY_YELLOW_CARP: - case AMDGPU_FAMILY_GC_10_3_6: - case AMDGPU_FAMILY_GC_10_3_7: - switch (AMD_FMT_MOD_GET(TILE, modifier)) { - case AMD_FMT_MOD_TILE_GFX9_64K_R_X: - case AMD_FMT_MOD_TILE_GFX9_64K_D_X: - case AMD_FMT_MOD_TILE_GFX9_64K_S_X: - case AMD_FMT_MOD_TILE_GFX9_64K_D: - return true; - default: - return false; - } - break; - case AMDGPU_FAMILY_GC_11_0_0: - case AMDGPU_FAMILY_GC_11_0_1: - switch (AMD_FMT_MOD_GET(TILE, modifier)) { - case AMD_FMT_MOD_TILE_GFX11_256K_R_X: - case AMD_FMT_MOD_TILE_GFX9_64K_R_X: - case AMD_FMT_MOD_TILE_GFX9_64K_D_X: - case AMD_FMT_MOD_TILE_GFX9_64K_S_X: - case AMD_FMT_MOD_TILE_GFX9_64K_D: - return true; - default: - return false; - } - break; - default: - ASSERT(0); /* Unknown asic */ - break; + /* Check that the modifier is on the list of the plane's supported modifiers. */ + for (i = 0; i < plane->modifier_count; i++) { + if (modifier == plane->modifiers[i]) + break; } + if (i == plane->modifier_count) + return false; /* * For D swizzle the canonical modifier depends on the bpp, so check -- cgit v1.2.3 From 4a4b6848d1e932b977e6a00cda393adf7e839ff8 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Fri, 21 Oct 2022 11:07:11 +0200 Subject: net: lan966x: Stop replacing tx dcbs and dcbs_buf when changing MTU When a frame is sent using FDMA, the skb is mapped and then the mapped address is given to an tx dcb that is different than the last used tx dcb. Once the HW finish with this frame, it would generate an interrupt and then the dcb can be reused and memory can be freed. For each dcb there is an dcb buf that contains some meta-data(is used by PTP, is it free). There is 1 to 1 relationship between dcb and dcb_buf. The following issue was observed. That sometimes after changing the MTU to allocate new tx dcbs and dcbs_buf, two frames were not transmitted. The frames were not transmitted because when reloading the tx dcbs, it was always presuming to use the first dcb but that was not always happening. Because it could be that the last tx dcb used before changing MTU was first dcb and then when it tried to get the next dcb it would take dcb 1 instead of 0. Because it is supposed to take a different dcb than the last used one. This can be fixed simply by changing tx->last_in_use to -1 when the fdma is disabled to reload the new dcb and dcbs_buff. But there could be a different issue. For example, right after the frame is sent, the MTU is changed. Now all the dcbs and dcbs_buf will be cleared. And now get the interrupt from HW that it finished with the frame. So when we try to clear the skb, it is not possible because we lost all the dcbs_buf. The solution here is to stop replacing the tx dcbs and dcbs_buf when changing MTU because the TX doesn't care what is the MTU size, it is only the RX that needs this information. Fixes: 2ea1cbac267e ("net: lan966x: Update FDMA to change MTU.") Signed-off-by: Horatiu Vultur Link: https://lore.kernel.org/r/20221021090711.3749009-1-horatiu.vultur@microchip.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/microchip/lan966x/lan966x_fdma.c | 24 +++------------------- 1 file changed, 3 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c index 7e4061c854f0..a42035cec611 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c @@ -309,6 +309,7 @@ static void lan966x_fdma_tx_disable(struct lan966x_tx *tx) lan966x, FDMA_CH_DB_DISCARD); tx->activated = false; + tx->last_in_use = -1; } static void lan966x_fdma_tx_reload(struct lan966x_tx *tx) @@ -687,17 +688,14 @@ static int lan966x_qsys_sw_status(struct lan966x *lan966x) static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu) { - void *rx_dcbs, *tx_dcbs, *tx_dcbs_buf; - dma_addr_t rx_dma, tx_dma; + dma_addr_t rx_dma; + void *rx_dcbs; u32 size; int err; /* Store these for later to free them */ rx_dma = lan966x->rx.dma; - tx_dma = lan966x->tx.dma; rx_dcbs = lan966x->rx.dcbs; - tx_dcbs = lan966x->tx.dcbs; - tx_dcbs_buf = lan966x->tx.dcbs_buf; napi_synchronize(&lan966x->napi); napi_disable(&lan966x->napi); @@ -715,17 +713,6 @@ static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu) size = ALIGN(size, PAGE_SIZE); dma_free_coherent(lan966x->dev, size, rx_dcbs, rx_dma); - lan966x_fdma_tx_disable(&lan966x->tx); - err = lan966x_fdma_tx_alloc(&lan966x->tx); - if (err) - goto restore_tx; - - size = sizeof(struct lan966x_tx_dcb) * FDMA_DCB_MAX; - size = ALIGN(size, PAGE_SIZE); - dma_free_coherent(lan966x->dev, size, tx_dcbs, tx_dma); - - kfree(tx_dcbs_buf); - lan966x_fdma_wakeup_netdev(lan966x); napi_enable(&lan966x->napi); @@ -735,11 +722,6 @@ restore: lan966x->rx.dcbs = rx_dcbs; lan966x_fdma_rx_start(&lan966x->rx); -restore_tx: - lan966x->tx.dma = tx_dma; - lan966x->tx.dcbs = tx_dcbs; - lan966x->tx.dcbs_buf = tx_dcbs_buf; - return err; } -- cgit v1.2.3 From b5f9a01fae42684648c2ee3cd9985f80c67ab9f7 Mon Sep 17 00:00:00 2001 From: Li Zhijian Date: Thu, 13 Oct 2022 12:03:33 +0800 Subject: RDMA/rxe: Fix mr leak in RESPST_ERR_RNR rxe_recheck_mr() will increase mr's ref_cnt, so we should call rxe_put(mr) to drop mr's ref_cnt in RESPST_ERR_RNR to avoid below warning: WARNING: CPU: 0 PID: 4156 at drivers/infiniband/sw/rxe/rxe_pool.c:259 __rxe_cleanup+0x1df/0x240 [rdma_rxe] ... Call Trace: rxe_dereg_mr+0x4c/0x60 [rdma_rxe] ib_dereg_mr_user+0xa8/0x200 [ib_core] ib_mr_pool_destroy+0x77/0xb0 [ib_core] nvme_rdma_destroy_queue_ib+0x89/0x240 [nvme_rdma] nvme_rdma_free_queue+0x40/0x50 [nvme_rdma] nvme_rdma_teardown_io_queues.part.0+0xc3/0x120 [nvme_rdma] nvme_rdma_error_recovery_work+0x4d/0xf0 [nvme_rdma] process_one_work+0x582/0xa40 ? pwq_dec_nr_in_flight+0x100/0x100 ? rwlock_bug.part.0+0x60/0x60 worker_thread+0x2a9/0x700 ? process_one_work+0xa40/0xa40 kthread+0x168/0x1a0 ? kthread_complete_and_exit+0x20/0x20 ret_from_fork+0x22/0x30 Link: https://lore.kernel.org/r/20221024052049.20577-1-lizhijian@fujitsu.com Fixes: 8a1a0be894da ("RDMA/rxe: Replace mr by rkey in responder resources") Signed-off-by: Li Zhijian Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky --- drivers/infiniband/sw/rxe/rxe_resp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c index ed5a09e86417..693081e813ec 100644 --- a/drivers/infiniband/sw/rxe/rxe_resp.c +++ b/drivers/infiniband/sw/rxe/rxe_resp.c @@ -806,8 +806,10 @@ static enum resp_states read_reply(struct rxe_qp *qp, skb = prepare_ack_packet(qp, &ack_pkt, opcode, payload, res->cur_psn, AETH_ACK_UNLIMITED); - if (!skb) + if (!skb) { + rxe_put(mr); return RESPST_ERR_RNR; + } rxe_mr_copy(mr, res->read.va, payload_addr(&ack_pkt), payload, RXE_FROM_MR_OBJ); -- cgit v1.2.3 From 3e5b3418827cefb5e1cc658806f02965791b8f07 Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Mon, 24 Oct 2022 19:48:07 +0800 Subject: can: mscan: mpc5xxx: mpc5xxx_can_probe(): add missing put_clock() in error path The commit 1149108e2fbf ("can: mscan: improve clock API use") only adds put_clock() in mpc5xxx_can_remove() function, forgetting to add put_clock() in the error handling code. Fix this bug by adding put_clock() in the error handling code. Fixes: 1149108e2fbf ("can: mscan: improve clock API use") Signed-off-by: Dongliang Mu Link: https://lore.kernel.org/all/20221024133828.35881-1-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/mscan/mpc5xxx_can.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index c469b2f3e57d..b0ed798ae70f 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -322,14 +322,14 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) &mscan_clksrc); if (!priv->can.clock.freq) { dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n"); - goto exit_free_mscan; + goto exit_put_clock; } err = register_mscandev(dev, mscan_clksrc); if (err) { dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", DRV_NAME, err); - goto exit_free_mscan; + goto exit_put_clock; } dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n", @@ -337,7 +337,9 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) return 0; -exit_free_mscan: +exit_put_clock: + if (data->put_clock) + data->put_clock(ofdev); free_candev(dev); exit_dispose_irq: irq_dispose_mapping(irq); -- cgit v1.2.3 From b1a09b63684cea56774786ca14c13b7041ffee63 Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Mon, 24 Oct 2022 17:02:52 +0800 Subject: can: mcp251x: mcp251x_can_probe(): add missing unregister_candev() in error path In mcp251x_can_probe(), if mcp251x_gpio_setup() fails, it forgets to unregister the CAN device. Fix this by unregistering can device in mcp251x_can_probe(). Fixes: 2d52dabbef60 ("can: mcp251x: add GPIO support") Signed-off-by: Dongliang Mu Link: https://lore.kernel.org/all/20221024090256.717236-1-dzm91@hust.edu.cn [mkl: adjust label] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/mcp251x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index c320de474f40..24883a65ca66 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1415,11 +1415,14 @@ static int mcp251x_can_probe(struct spi_device *spi) ret = mcp251x_gpio_setup(priv); if (ret) - goto error_probe; + goto out_unregister_candev; netdev_info(net, "MCP%x successfully initialized.\n", priv->model); return 0; +out_unregister_candev: + unregister_candev(net); + error_probe: destroy_workqueue(priv->wq); priv->wq = NULL; -- cgit v1.2.3 From 1a2dcbdde82e3a5f1db9b2f4c48aa1aeba534fb2 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 13 Sep 2022 17:35:38 +0530 Subject: scsi: mpt3sas: re-do lost mpt3sas DMA mask fix This is a re-do of commit e0e0747de0ea ("scsi: mpt3sas: Fix return value check of dma_get_required_mask()"), which I ended up undoing in a mis-merge in commit 62e6e5940c0c ("Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi"). The original commit message was scsi: mpt3sas: Fix return value check of dma_get_required_mask() Fix the incorrect return value check of dma_get_required_mask(). Due to this incorrect check, the driver was always setting the DMA mask to 63 bit. Link: https://lore.kernel.org/r/20220913120538.18759-2-sreekanth.reddy@broadcom.com Fixes: ba27c5cf286d ("scsi: mpt3sas: Don't change the DMA coherent mask after allocations") Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen and this fix was lost when I mis-merged the conflict with commit 9df650963bf6 ("scsi: mpt3sas: Don't change DMA mask while reallocating pools"). Reported-by: Juergen Gross Fixes: 62e6e5940c0c ("Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi") Link: https://lore.kernel.org/all/CAHk-=wjaK-TxrNaGtFDpL9qNHL1MVkWXO1TT6vObD5tXMSC4Zg@mail.gmail.com Signed-off-by: Linus Torvalds --- drivers/scsi/mpt3sas/mpt3sas_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 8b22df8c1792..4e981ccaac41 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2993,7 +2993,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) u64 coherent_dma_mask, dma_mask; if (ioc->is_mcpu_endpoint || sizeof(dma_addr_t) == 4 || - dma_get_required_mask(&pdev->dev) <= 32) { + dma_get_required_mask(&pdev->dev) <= DMA_BIT_MASK(32)) { ioc->dma_mask = 32; coherent_dma_mask = dma_mask = DMA_BIT_MASK(32); /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */ -- cgit v1.2.3 From 88619e77b33d5718fae3c13d29f94b2646facfcd Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 21 Oct 2022 19:24:22 +0200 Subject: net: stmmac: rk3588: Allow multiple gmac controller RK3588(s) can have multiple gmac controllers. Re-use rk3568 logic to distinguish them. Fixes: 2f2b60a0ec28 ("net: ethernet: stmmac: dwmac-rk: Add gmac support for rk3588") Signed-off-by: Benjamin Gaignard Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20221021172422.88534-1-sebastian.reichel@collabora.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index f7269d79a385..6656d76b6766 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -1243,6 +1243,12 @@ static const struct rk_gmac_ops rk3588_ops = { .set_rgmii_speed = rk3588_set_gmac_speed, .set_rmii_speed = rk3588_set_gmac_speed, .set_clock_selection = rk3588_set_clock_selection, + .regs_valid = true, + .regs = { + 0xfe1b0000, /* gmac0 */ + 0xfe1c0000, /* gmac1 */ + 0x0, /* sentinel */ + }, }; #define RV1108_GRF_GMAC_CON0 0X0900 -- cgit v1.2.3 From b3af84383e7abdc5e63435817bb73a268e7c3637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 27 Sep 2022 18:43:03 +0200 Subject: drm/scheduler: fix fence ref counting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We leaked dependency fences when processes were beeing killed. Additional to that grab a reference to the last scheduled fence. Signed-off-by: Christian König Reviewed-by: Andrey Grodzovsky Link: https://patchwork.freedesktop.org/patch/msgid/20220929180151.139751-1-christian.koenig@amd.com --- drivers/gpu/drm/scheduler/sched_entity.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 6137537aaea4..4b913dbb7d7b 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -207,6 +207,7 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, struct drm_sched_job *job = container_of(cb, struct drm_sched_job, finish_cb); + dma_fence_put(f); INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work); schedule_work(&job->work); } @@ -234,8 +235,10 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) struct drm_sched_fence *s_fence = job->s_fence; /* Wait for all dependencies to avoid data corruptions */ - while ((f = drm_sched_job_dependency(job, entity))) + while ((f = drm_sched_job_dependency(job, entity))) { dma_fence_wait(f, false); + dma_fence_put(f); + } drm_sched_fence_scheduled(s_fence); dma_fence_set_error(&s_fence->finished, -ESRCH); @@ -250,6 +253,7 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) continue; } + dma_fence_get(entity->last_scheduled); r = dma_fence_add_callback(entity->last_scheduled, &job->finish_cb, drm_sched_entity_kill_jobs_cb); -- cgit v1.2.3 From 8dbab94d45fb1094cefac7956b7fb987a36e2b12 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 24 Oct 2022 21:21:00 +0200 Subject: cpufreq: intel_pstate: Read all MSRs on the target CPU Some of the MSR accesses in intel_pstate are carried out on the CPU that is running the code, but the values coming from them are used for the performance scaling of the other CPUs. This is problematic, for example, on hybrid platforms where MSR_TURBO_RATIO_LIMIT for P-cores and E-cores is different, so the values read from it on a P-core are generally not applicable to E-cores and the other way around. For this reason, make the driver access all MSRs on the target CPU on platforms using the "core" pstate_funcs callbacks which is the case for all of the hybrid platforms released to date. For this purpose, pass a CPU argument to the ->get_max(), ->get_max_physical(), ->get_min() and ->get_turbo() pstate_funcs callbacks and from there pass it to rdmsrl_on_cpu() or rdmsrl_safe_on_cpu() to access the MSR on the target CPU. Fixes: 46573fd6369f ("cpufreq: intel_pstate: hybrid: Rework HWP calibration") Acked-by: Srinivas Pandruvada Tested-by: Srinivas Pandruvada Cc: 5.15+ # 5.15+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 66 +++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index fc3ebeb0bbe5..457694a2d0e8 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -280,10 +280,10 @@ static struct cpudata **all_cpu_data; * structure is used to store those callbacks. */ struct pstate_funcs { - int (*get_max)(void); - int (*get_max_physical)(void); - int (*get_min)(void); - int (*get_turbo)(void); + int (*get_max)(int cpu); + int (*get_max_physical)(int cpu); + int (*get_min)(int cpu); + int (*get_turbo)(int cpu); int (*get_scaling)(void); int (*get_cpu_scaling)(int cpu); int (*get_aperf_mperf_shift)(void); @@ -531,12 +531,12 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu) { int perf_ctl_max_phys = cpu->pstate.max_pstate_physical; int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling; - int perf_ctl_turbo = pstate_funcs.get_turbo(); + int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu); int turbo_freq = perf_ctl_turbo * perf_ctl_scaling; int scaling = cpu->pstate.scaling; pr_debug("CPU%d: perf_ctl_max_phys = %d\n", cpu->cpu, perf_ctl_max_phys); - pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max()); + pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max(cpu->cpu)); pr_debug("CPU%d: perf_ctl_turbo = %d\n", cpu->cpu, perf_ctl_turbo); pr_debug("CPU%d: perf_ctl_scaling = %d\n", cpu->cpu, perf_ctl_scaling); pr_debug("CPU%d: HWP_CAP guaranteed = %d\n", cpu->cpu, cpu->pstate.max_pstate); @@ -1740,7 +1740,7 @@ static void intel_pstate_hwp_enable(struct cpudata *cpudata) intel_pstate_update_epp_defaults(cpudata); } -static int atom_get_min_pstate(void) +static int atom_get_min_pstate(int not_used) { u64 value; @@ -1748,7 +1748,7 @@ static int atom_get_min_pstate(void) return (value >> 8) & 0x7F; } -static int atom_get_max_pstate(void) +static int atom_get_max_pstate(int not_used) { u64 value; @@ -1756,7 +1756,7 @@ static int atom_get_max_pstate(void) return (value >> 16) & 0x7F; } -static int atom_get_turbo_pstate(void) +static int atom_get_turbo_pstate(int not_used) { u64 value; @@ -1834,23 +1834,23 @@ static void atom_get_vid(struct cpudata *cpudata) cpudata->vid.turbo = value & 0x7f; } -static int core_get_min_pstate(void) +static int core_get_min_pstate(int cpu) { u64 value; - rdmsrl(MSR_PLATFORM_INFO, value); + rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &value); return (value >> 40) & 0xFF; } -static int core_get_max_pstate_physical(void) +static int core_get_max_pstate_physical(int cpu) { u64 value; - rdmsrl(MSR_PLATFORM_INFO, value); + rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &value); return (value >> 8) & 0xFF; } -static int core_get_tdp_ratio(u64 plat_info) +static int core_get_tdp_ratio(int cpu, u64 plat_info) { /* Check how many TDP levels present */ if (plat_info & 0x600000000) { @@ -1860,13 +1860,13 @@ static int core_get_tdp_ratio(u64 plat_info) int err; /* Get the TDP level (0, 1, 2) to get ratios */ - err = rdmsrl_safe(MSR_CONFIG_TDP_CONTROL, &tdp_ctrl); + err = rdmsrl_safe_on_cpu(cpu, MSR_CONFIG_TDP_CONTROL, &tdp_ctrl); if (err) return err; /* TDP MSR are continuous starting at 0x648 */ tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x03); - err = rdmsrl_safe(tdp_msr, &tdp_ratio); + err = rdmsrl_safe_on_cpu(cpu, tdp_msr, &tdp_ratio); if (err) return err; @@ -1883,7 +1883,7 @@ static int core_get_tdp_ratio(u64 plat_info) return -ENXIO; } -static int core_get_max_pstate(void) +static int core_get_max_pstate(int cpu) { u64 tar; u64 plat_info; @@ -1891,10 +1891,10 @@ static int core_get_max_pstate(void) int tdp_ratio; int err; - rdmsrl(MSR_PLATFORM_INFO, plat_info); + rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &plat_info); max_pstate = (plat_info >> 8) & 0xFF; - tdp_ratio = core_get_tdp_ratio(plat_info); + tdp_ratio = core_get_tdp_ratio(cpu, plat_info); if (tdp_ratio <= 0) return max_pstate; @@ -1903,7 +1903,7 @@ static int core_get_max_pstate(void) return tdp_ratio; } - err = rdmsrl_safe(MSR_TURBO_ACTIVATION_RATIO, &tar); + err = rdmsrl_safe_on_cpu(cpu, MSR_TURBO_ACTIVATION_RATIO, &tar); if (!err) { int tar_levels; @@ -1918,13 +1918,13 @@ static int core_get_max_pstate(void) return max_pstate; } -static int core_get_turbo_pstate(void) +static int core_get_turbo_pstate(int cpu) { u64 value; int nont, ret; - rdmsrl(MSR_TURBO_RATIO_LIMIT, value); - nont = core_get_max_pstate(); + rdmsrl_on_cpu(cpu, MSR_TURBO_RATIO_LIMIT, &value); + nont = core_get_max_pstate(cpu); ret = (value) & 255; if (ret <= nont) ret = nont; @@ -1952,13 +1952,13 @@ static int knl_get_aperf_mperf_shift(void) return 10; } -static int knl_get_turbo_pstate(void) +static int knl_get_turbo_pstate(int cpu) { u64 value; int nont, ret; - rdmsrl(MSR_TURBO_RATIO_LIMIT, value); - nont = core_get_max_pstate(); + rdmsrl_on_cpu(cpu, MSR_TURBO_RATIO_LIMIT, &value); + nont = core_get_max_pstate(cpu); ret = (((value) >> 8) & 0xFF); if (ret <= nont) ret = nont; @@ -2025,10 +2025,10 @@ static void intel_pstate_max_within_limits(struct cpudata *cpu) static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) { - int perf_ctl_max_phys = pstate_funcs.get_max_physical(); + int perf_ctl_max_phys = pstate_funcs.get_max_physical(cpu->cpu); int perf_ctl_scaling = pstate_funcs.get_scaling(); - cpu->pstate.min_pstate = pstate_funcs.get_min(); + cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu); cpu->pstate.max_pstate_physical = perf_ctl_max_phys; cpu->pstate.perf_ctl_scaling = perf_ctl_scaling; @@ -2044,8 +2044,8 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) } } else { cpu->pstate.scaling = perf_ctl_scaling; - cpu->pstate.max_pstate = pstate_funcs.get_max(); - cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); + cpu->pstate.max_pstate = pstate_funcs.get_max(cpu->cpu); + cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu); } if (cpu->pstate.scaling == perf_ctl_scaling) { @@ -3221,9 +3221,9 @@ static unsigned int force_load __initdata; static int __init intel_pstate_msrs_not_valid(void) { - if (!pstate_funcs.get_max() || - !pstate_funcs.get_min() || - !pstate_funcs.get_turbo()) + if (!pstate_funcs.get_max(0) || + !pstate_funcs.get_min(0) || + !pstate_funcs.get_turbo(0)) return -ENODEV; return 0; -- cgit v1.2.3 From f5c8cf2a4992dd929fa0c2f25c09ee69b8dcbce1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 24 Oct 2022 21:22:48 +0200 Subject: cpufreq: intel_pstate: hybrid: Use known scaling factor for P-cores Commit 46573fd6369f ("cpufreq: intel_pstate: hybrid: Rework HWP calibration") attempted to use the information from CPPC (the nominal performance in particular) to obtain the scaling factor allowing the frequency to be computed if the HWP performance level of the given CPU is known or vice versa. However, it turns out that on some platforms this doesn't work, because the CPPC information on them does not align with the contents of the MSR_HWP_CAPABILITIES registers. This basically means that the only way to make intel_pstate work on all of the hybrid platforms to date is to use the observation that on all of them the scaling factor between the HWP performance levels and frequency for P-cores is 78741 (approximately 100000/1.27). For E-cores it is 100000, which is the same as for all of the non-hybrid "core" platforms and does not require any changes. Accordingly, make intel_pstate use 78741 as the scaling factor between HWP performance levels and frequency for P-cores on all hybrid platforms and drop the dependency of the HWP calibration code on CPPC. Fixes: 46573fd6369f ("cpufreq: intel_pstate: hybrid: Rework HWP calibration") Reported-by: Srinivas Pandruvada Acked-by: Srinivas Pandruvada Tested-by: Srinivas Pandruvada Cc: 5.15+ # 5.15+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 69 +++++++++--------------------------------- 1 file changed, 15 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 457694a2d0e8..6ff73c30769f 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -398,16 +399,6 @@ static int intel_pstate_get_cppc_guaranteed(int cpu) return cppc_perf.nominal_perf; } - -static u32 intel_pstate_cppc_nominal(int cpu) -{ - u64 nominal_perf; - - if (cppc_get_nominal_perf(cpu, &nominal_perf)) - return 0; - - return nominal_perf; -} #else /* CONFIG_ACPI_CPPC_LIB */ static inline void intel_pstate_set_itmt_prio(int cpu) { @@ -532,34 +523,17 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu) int perf_ctl_max_phys = cpu->pstate.max_pstate_physical; int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling; int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu); - int turbo_freq = perf_ctl_turbo * perf_ctl_scaling; int scaling = cpu->pstate.scaling; pr_debug("CPU%d: perf_ctl_max_phys = %d\n", cpu->cpu, perf_ctl_max_phys); - pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max(cpu->cpu)); pr_debug("CPU%d: perf_ctl_turbo = %d\n", cpu->cpu, perf_ctl_turbo); pr_debug("CPU%d: perf_ctl_scaling = %d\n", cpu->cpu, perf_ctl_scaling); pr_debug("CPU%d: HWP_CAP guaranteed = %d\n", cpu->cpu, cpu->pstate.max_pstate); pr_debug("CPU%d: HWP_CAP highest = %d\n", cpu->cpu, cpu->pstate.turbo_pstate); pr_debug("CPU%d: HWP-to-frequency scaling factor: %d\n", cpu->cpu, scaling); - /* - * If the product of the HWP performance scaling factor and the HWP_CAP - * highest performance is greater than the maximum turbo frequency - * corresponding to the pstate_funcs.get_turbo() return value, the - * scaling factor is too high, so recompute it to make the HWP_CAP - * highest performance correspond to the maximum turbo frequency. - */ - cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * scaling; - if (turbo_freq < cpu->pstate.turbo_freq) { - cpu->pstate.turbo_freq = turbo_freq; - scaling = DIV_ROUND_UP(turbo_freq, cpu->pstate.turbo_pstate); - cpu->pstate.scaling = scaling; - - pr_debug("CPU%d: refined HWP-to-frequency scaling factor: %d\n", - cpu->cpu, scaling); - } - + cpu->pstate.turbo_freq = rounddown(cpu->pstate.turbo_pstate * scaling, + perf_ctl_scaling); cpu->pstate.max_freq = rounddown(cpu->pstate.max_pstate * scaling, perf_ctl_scaling); @@ -1965,37 +1939,24 @@ static int knl_get_turbo_pstate(int cpu) return ret; } -#ifdef CONFIG_ACPI_CPPC_LIB -static u32 hybrid_ref_perf; - -static int hybrid_get_cpu_scaling(int cpu) +static void hybrid_get_type(void *data) { - return DIV_ROUND_UP(core_get_scaling() * hybrid_ref_perf, - intel_pstate_cppc_nominal(cpu)); + u8 *cpu_type = data; + + *cpu_type = get_this_hybrid_cpu_type(); } -static void intel_pstate_cppc_set_cpu_scaling(void) +static int hybrid_get_cpu_scaling(int cpu) { - u32 min_nominal_perf = U32_MAX; - int cpu; + u8 cpu_type = 0; - for_each_present_cpu(cpu) { - u32 nominal_perf = intel_pstate_cppc_nominal(cpu); + smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1); + /* P-cores have a smaller perf level-to-freqency scaling factor. */ + if (cpu_type == 0x40) + return 78741; - if (nominal_perf && nominal_perf < min_nominal_perf) - min_nominal_perf = nominal_perf; - } - - if (min_nominal_perf < U32_MAX) { - hybrid_ref_perf = min_nominal_perf; - pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling; - } + return core_get_scaling(); } -#else -static inline void intel_pstate_cppc_set_cpu_scaling(void) -{ -} -#endif /* CONFIG_ACPI_CPPC_LIB */ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) { @@ -3450,7 +3411,7 @@ static int __init intel_pstate_init(void) default_driver = &intel_pstate; if (boot_cpu_has(X86_FEATURE_HYBRID_CPU)) - intel_pstate_cppc_set_cpu_scaling(); + pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling; goto hwp_cpu_matched; } -- cgit v1.2.3 From 5fa9add66b00ad0c796185ff7438eaa3e67c1187 Mon Sep 17 00:00:00 2001 From: Nam Cao Date: Sat, 22 Oct 2022 19:46:36 +0200 Subject: nvme-tcp: replace sg_init_marker() with sg_init_table() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In nvme_tcp_ddgst_update(), sg_init_marker() is called with an uninitialized scatterlist. This is probably fine, but gcc complains: CC [M] drivers/nvme/host/tcp.o In file included from ./include/linux/dma-mapping.h:10, from ./include/linux/skbuff.h:31, from ./include/net/net_namespace.h:43, from ./include/linux/netdevice.h:38, from ./include/net/sock.h:46, from drivers/nvme/host/tcp.c:12: In function ‘sg_mark_end’, inlined from ‘sg_init_marker’ at ./include/linux/scatterlist.h:356:2, inlined from ‘nvme_tcp_ddgst_update’ at drivers/nvme/host/tcp.c:390:2: ./include/linux/scatterlist.h:234:11: error: ‘sg.page_link’ is used uninitialized [-Werror=uninitialized] 234 | sg->page_link |= SG_END; | ~~^~~~~~~~~~~ drivers/nvme/host/tcp.c: In function ‘nvme_tcp_ddgst_update’: drivers/nvme/host/tcp.c:388:28: note: ‘sg’ declared here 388 | struct scatterlist sg; | ^~ cc1: all warnings being treated as errors Use sg_init_table() instead, which basically memset the scatterlist to zero first before calling sg_init_marker(). Signed-off-by: Nam Cao Reviewed-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/host/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 1eed0fc26b3a..dc2def86076d 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -387,7 +387,7 @@ static inline void nvme_tcp_ddgst_update(struct ahash_request *hash, { struct scatterlist sg; - sg_init_marker(&sg, 1); + sg_init_table(&sg, 1); sg_set_page(&sg, page, len, off); ahash_request_set_crypt(hash, &sg, NULL, len); crypto_ahash_update(hash); -- cgit v1.2.3 From 83e1226b0ee2d7e3fb6e002fbbfc6ab36aabdc35 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Sun, 23 Oct 2022 11:04:43 +0300 Subject: nvme-tcp: fix possible circular locking when deleting a controller under memory pressure When destroying a queue, when calling sock_release, the network stack might need to allocate an skb to send a FIN/RST. When that happens during memory pressure, there is a need to reclaim memory, which in turn may ask the nvme-tcp device to write out dirty pages, however this is not possible due to a ctrl teardown that is going on. Set PF_MEMALLOC to the task that releases the socket to grant access to PF_MEMALLOC reserves. In addition, do the same for the nvme-tcp thread as this may also originate from the swap itself and should be more resilient to memory pressure situations. This fixes the following lockdep complaint: -- ====================================================== WARNING: possible circular locking dependency detected 6.0.0-rc2+ #25 Tainted: G W ------------------------------------------------------ kswapd0/92 is trying to acquire lock: ffff888114003240 (sk_lock-AF_INET-NVME){+.+.}-{0:0}, at: tcp_sendpage+0x23/0xa0 but task is already holding lock: ffffffff97e95ca0 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat+0x987/0x10d0 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (fs_reclaim){+.+.}-{0:0}: fs_reclaim_acquire+0x11e/0x160 kmem_cache_alloc_node+0x44/0x530 __alloc_skb+0x158/0x230 tcp_send_active_reset+0x7e/0x730 tcp_disconnect+0x1272/0x1ae0 __tcp_close+0x707/0xd90 tcp_close+0x26/0x80 inet_release+0xfa/0x220 sock_release+0x85/0x1a0 nvme_tcp_free_queue+0x1fd/0x470 [nvme_tcp] nvme_do_delete_ctrl+0x130/0x13d [nvme_core] nvme_sysfs_delete.cold+0x8/0xd [nvme_core] kernfs_fop_write_iter+0x356/0x530 vfs_write+0x4e8/0xce0 ksys_write+0xfd/0x1d0 do_syscall_64+0x58/0x80 entry_SYSCALL_64_after_hwframe+0x63/0xcd -> #0 (sk_lock-AF_INET-NVME){+.+.}-{0:0}: __lock_acquire+0x2a0c/0x5690 lock_acquire+0x18e/0x4f0 lock_sock_nested+0x37/0xc0 tcp_sendpage+0x23/0xa0 inet_sendpage+0xad/0x120 kernel_sendpage+0x156/0x440 nvme_tcp_try_send+0x48a/0x2630 [nvme_tcp] nvme_tcp_queue_rq+0xefb/0x17e0 [nvme_tcp] __blk_mq_try_issue_directly+0x452/0x660 blk_mq_plug_issue_direct.constprop.0+0x207/0x700 blk_mq_flush_plug_list+0x6f5/0xc70 __blk_flush_plug+0x264/0x410 blk_finish_plug+0x4b/0xa0 shrink_lruvec+0x1263/0x1ea0 shrink_node+0x736/0x1a80 balance_pgdat+0x740/0x10d0 kswapd+0x5f2/0xaf0 kthread+0x256/0x2f0 ret_from_fork+0x1f/0x30 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(fs_reclaim); lock(sk_lock-AF_INET-NVME); lock(fs_reclaim); lock(sk_lock-AF_INET-NVME); *** DEADLOCK *** 3 locks held by kswapd0/92: #0: ffffffff97e95ca0 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat+0x987/0x10d0 #1: ffff88811f21b0b0 (q->srcu){....}-{0:0}, at: blk_mq_flush_plug_list+0x6b3/0xc70 #2: ffff888170b11470 (&queue->send_mutex){+.+.}-{3:3}, at: nvme_tcp_queue_rq+0xeb9/0x17e0 [nvme_tcp] Fixes: 3f2304f8c6d6 ("nvme-tcp: add NVMe over TCP host driver") Reported-by: Daniel Wagner Signed-off-by: Sagi Grimberg Tested-by: Daniel Wagner Signed-off-by: Christoph Hellwig --- drivers/nvme/host/tcp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index dc2def86076d..9b47dcb2a7d9 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -1141,6 +1141,7 @@ static int nvme_tcp_try_send_ddgst(struct nvme_tcp_request *req) static int nvme_tcp_try_send(struct nvme_tcp_queue *queue) { struct nvme_tcp_request *req; + unsigned int noreclaim_flag; int ret = 1; if (!queue->request) { @@ -1150,12 +1151,13 @@ static int nvme_tcp_try_send(struct nvme_tcp_queue *queue) } req = queue->request; + noreclaim_flag = memalloc_noreclaim_save(); if (req->state == NVME_TCP_SEND_CMD_PDU) { ret = nvme_tcp_try_send_cmd_pdu(req); if (ret <= 0) goto done; if (!nvme_tcp_has_inline_data(req)) - return ret; + goto out; } if (req->state == NVME_TCP_SEND_H2C_PDU) { @@ -1181,6 +1183,8 @@ done: nvme_tcp_fail_request(queue->request); nvme_tcp_done_send_req(queue); } +out: + memalloc_noreclaim_restore(noreclaim_flag); return ret; } @@ -1296,6 +1300,7 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid) struct page *page; struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl); struct nvme_tcp_queue *queue = &ctrl->queues[qid]; + unsigned int noreclaim_flag; if (!test_and_clear_bit(NVME_TCP_Q_ALLOCATED, &queue->flags)) return; @@ -1308,7 +1313,11 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid) __page_frag_cache_drain(page, queue->pf_cache.pagecnt_bias); queue->pf_cache.va = NULL; } + + noreclaim_flag = memalloc_noreclaim_save(); sock_release(queue->sock); + memalloc_noreclaim_restore(noreclaim_flag); + kfree(queue->pdu); mutex_destroy(&queue->send_mutex); mutex_destroy(&queue->queue_lock); -- cgit v1.2.3 From fe8714b04fb137aa62e9a69424c48b5301b721b9 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Mon, 24 Oct 2022 11:57:45 -0700 Subject: nvme-multipath: set queue dma alignment to 3 NVMe spec requires all transports support dword aligned addresses, which is already set in the namespace request_queue. Set the same limit in the multipath device's request_queue as well. Signed-off-by: Keith Busch Reviewed-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/host/multipath.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 0ea7e441e080..93e2138a8b42 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -516,6 +516,7 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head) /* set to a default value of 512 until the disk is validated */ blk_queue_logical_block_size(head->disk->queue, 512); blk_set_stacking_limits(&head->disk->queue->limits); + blk_queue_dma_alignment(head->disk->queue, 3); /* we need to propagate up the VMC settings */ if (ctrl->vwc & NVME_CTRL_VWC_PRESENT) -- cgit v1.2.3 From f8bcaf714abfc94818dff8c0db84d750433984f4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Oct 2022 15:32:28 +0100 Subject: media: vivid: s_fbuf: add more sanity checks VIDIOC_S_FBUF is by definition a scary ioctl, which is why only root can use it. But at least check if the framebuffer parameters match that of one of the framebuffer created by vivid, and reject anything else. Signed-off-by: Hans Verkuil Fixes: ef834f7836ec ([media] vivid: add the video capture and output parts) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/test-drivers/vivid/vivid-core.c | 22 ++++++++++++++++++++++ drivers/media/test-drivers/vivid/vivid-core.h | 2 ++ drivers/media/test-drivers/vivid/vivid-vid-cap.c | 9 ++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/test-drivers/vivid/vivid-core.c b/drivers/media/test-drivers/vivid/vivid-core.c index 04b75666bad4..61d48fbc3d15 100644 --- a/drivers/media/test-drivers/vivid/vivid-core.c +++ b/drivers/media/test-drivers/vivid/vivid-core.c @@ -339,6 +339,28 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a return vivid_vid_out_g_fbuf(file, fh, a); } +/* + * Only support the framebuffer of one of the vivid instances. + * Anything else is rejected. + */ +bool vivid_validate_fb(const struct v4l2_framebuffer *a) +{ + struct vivid_dev *dev; + int i; + + for (i = 0; i < n_devs; i++) { + dev = vivid_devs[i]; + if (!dev || !dev->video_pbase) + continue; + if ((unsigned long)a->base == dev->video_pbase && + a->fmt.width <= dev->display_width && + a->fmt.height <= dev->display_height && + a->fmt.bytesperline <= dev->display_byte_stride) + return true; + } + return false; +} + static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a) { struct video_device *vdev = video_devdata(file); diff --git a/drivers/media/test-drivers/vivid/vivid-core.h b/drivers/media/test-drivers/vivid/vivid-core.h index bfcfb3515901..473f3598db5a 100644 --- a/drivers/media/test-drivers/vivid/vivid-core.h +++ b/drivers/media/test-drivers/vivid/vivid-core.h @@ -613,4 +613,6 @@ static inline bool vivid_is_hdmi_out(const struct vivid_dev *dev) return dev->output_type[dev->output] == HDMI; } +bool vivid_validate_fb(const struct v4l2_framebuffer *a); + #endif diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c index 86b158eeb2d8..e3e78b5bd227 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -1276,7 +1276,14 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh, return -EINVAL; if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8) return -EINVAL; - if (a->fmt.height * a->fmt.bytesperline < a->fmt.sizeimage) + if (a->fmt.bytesperline > a->fmt.sizeimage / a->fmt.height) + return -EINVAL; + + /* + * Only support the framebuffer of one of the vivid instances. + * Anything else is rejected. + */ + if (!vivid_validate_fb(a)) return -EINVAL; dev->fb_vbase_cap = phys_to_virt((unsigned long)a->base); -- cgit v1.2.3 From 1f65ea411cc7b6ff128d82a3493d7b5648054e6f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Oct 2022 15:18:46 +0100 Subject: media: vivid: dev->bitmap_cap wasn't freed in all cases Whenever the compose width/height values change, the dev->bitmap_cap vmalloc'ed array must be freed and dev->bitmap_cap set to NULL. This was done in some places, but not all. This is only an issue if overlay support is enabled and the bitmap clipping is used. Signed-off-by: Hans Verkuil Fixes: ef834f7836ec ([media] vivid: add the video capture and output parts) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/test-drivers/vivid/vivid-vid-cap.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c index e3e78b5bd227..d52d24b61d34 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -453,6 +453,12 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls) tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap); dev->crop_cap = dev->src_rect; dev->crop_bounds_cap = dev->src_rect; + if (dev->bitmap_cap && + (dev->compose_cap.width != dev->crop_cap.width || + dev->compose_cap.height != dev->crop_cap.height)) { + vfree(dev->bitmap_cap); + dev->bitmap_cap = NULL; + } dev->compose_cap = dev->crop_cap; if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap)) dev->compose_cap.height /= 2; @@ -913,6 +919,8 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection struct vivid_dev *dev = video_drvdata(file); struct v4l2_rect *crop = &dev->crop_cap; struct v4l2_rect *compose = &dev->compose_cap; + unsigned orig_compose_w = compose->width; + unsigned orig_compose_h = compose->height; unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1; int ret; @@ -1029,17 +1037,17 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection s->r.height /= factor; } v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect); - if (dev->bitmap_cap && (compose->width != s->r.width || - compose->height != s->r.height)) { - vfree(dev->bitmap_cap); - dev->bitmap_cap = NULL; - } *compose = s->r; break; default: return -EINVAL; } + if (dev->bitmap_cap && (compose->width != orig_compose_w || + compose->height != orig_compose_h)) { + vfree(dev->bitmap_cap); + dev->bitmap_cap = NULL; + } tpg_s_crop_compose(&dev->tpg, crop, compose); return 0; } -- cgit v1.2.3 From 4b6d66a45ed34a15721cb9e11492fa1a24bc83df Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 13 Oct 2022 09:00:34 +0100 Subject: media: v4l2-dv-timings: add sanity checks for blanking values Add sanity checks to v4l2_valid_dv_timings() to ensure that the provided blanking values are reasonable. Signed-off-by: Hans Verkuil Fixes: b18787ed1ce3 ([media] v4l2-dv-timings: add new helper module) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dv-timings.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index af48705c704f..003c32fed3f7 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -161,6 +161,20 @@ bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) return false; + + /* sanity checks for the blanking timings */ + if (!bt->interlaced && + (bt->il_vbackporch || bt->il_vsync || bt->il_vfrontporch)) + return false; + if (bt->hfrontporch > 2 * bt->width || + bt->hsync > 1024 || bt->hbackporch > 1024) + return false; + if (bt->vfrontporch > 4096 || + bt->vsync > 128 || bt->vbackporch > 4096) + return false; + if (bt->interlaced && (bt->il_vfrontporch > 4096 || + bt->il_vsync > 128 || bt->il_vbackporch > 4096)) + return false; return fnc == NULL || fnc(t, fnc_handle); } EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings); -- cgit v1.2.3 From eb1d969203eb8212741751f88dcf5cb56bb11830 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 21 Oct 2022 13:21:25 +0100 Subject: media: vivid: fix control handler mutex deadlock vivid_update_format_cap() can be called from an s_ctrl callback. In that case (keep_controls == true) no control framework functions can be called that take the control handler mutex. The new call to v4l2_ctrl_modify_dimensions() did exactly that. Signed-off-by: Hans Verkuil Fixes: 6bc7643d1b9c (media: vivid: add pixel_array test control) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/test-drivers/vivid/vivid-vid-cap.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c index d52d24b61d34..11620eaf941e 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -466,6 +466,14 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls) tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev)); tpg_s_pixel_aspect(&dev->tpg, vivid_get_pixel_aspect(dev)); tpg_update_mv_step(&dev->tpg); + + /* + * We can be called from within s_ctrl, in that case we can't + * modify controls. Luckily we don't need to in that case. + */ + if (keep_controls) + return; + dims[0] = roundup(dev->src_rect.width, PIXEL_ARRAY_DIV); dims[1] = roundup(dev->src_rect.height, PIXEL_ARRAY_DIV); v4l2_ctrl_modify_dimensions(dev->pixel_array, dims); -- cgit v1.2.3 From 957148e22870e4021082dddd12f8619a49d9bb50 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Oct 2022 15:31:51 +0100 Subject: media: vivid: drop GFP_DMA32 >From what I can see, this is not needed. And since using it issues a 'deprecated' warning, just drop it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/test-drivers/vivid/vivid-osd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/test-drivers/vivid/vivid-osd.c b/drivers/media/test-drivers/vivid/vivid-osd.c index fbaec8acc161..ec25edc679b3 100644 --- a/drivers/media/test-drivers/vivid/vivid-osd.c +++ b/drivers/media/test-drivers/vivid/vivid-osd.c @@ -357,7 +357,7 @@ int vivid_fb_init(struct vivid_dev *dev) int ret; dev->video_buffer_size = MAX_OSD_HEIGHT * MAX_OSD_WIDTH * 2; - dev->video_vbase = kzalloc(dev->video_buffer_size, GFP_KERNEL | GFP_DMA32); + dev->video_vbase = kzalloc(dev->video_buffer_size, GFP_KERNEL); if (dev->video_vbase == NULL) return -ENOMEM; dev->video_pbase = virt_to_phys(dev->video_vbase); -- cgit v1.2.3 From 69d78a80da4ef12faf2a6f9cfa2097ab4ac43983 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 17 Oct 2022 15:09:06 +0100 Subject: media: vivid: set num_in/outputs to 0 if not supported If node_types does not have video/vbi/meta inputs or outputs, then set num_inputs/num_outputs to 0 instead of 1. Signed-off-by: Hans Verkuil Fixes: 0c90f649d2f5 (media: vivid: add vivid_create_queue() helper) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/test-drivers/vivid/vivid-core.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/test-drivers/vivid/vivid-core.c b/drivers/media/test-drivers/vivid/vivid-core.c index 61d48fbc3d15..f28440e6c9f8 100644 --- a/drivers/media/test-drivers/vivid/vivid-core.c +++ b/drivers/media/test-drivers/vivid/vivid-core.c @@ -942,8 +942,12 @@ static int vivid_detect_feature_set(struct vivid_dev *dev, int inst, /* how many inputs do we have and of what type? */ dev->num_inputs = num_inputs[inst]; - if (dev->num_inputs < 1) - dev->num_inputs = 1; + if (node_type & 0x20007) { + if (dev->num_inputs < 1) + dev->num_inputs = 1; + } else { + dev->num_inputs = 0; + } if (dev->num_inputs >= MAX_INPUTS) dev->num_inputs = MAX_INPUTS; for (i = 0; i < dev->num_inputs; i++) { @@ -960,8 +964,12 @@ static int vivid_detect_feature_set(struct vivid_dev *dev, int inst, /* how many outputs do we have and of what type? */ dev->num_outputs = num_outputs[inst]; - if (dev->num_outputs < 1) - dev->num_outputs = 1; + if (node_type & 0x40300) { + if (dev->num_outputs < 1) + dev->num_outputs = 1; + } else { + dev->num_outputs = 0; + } if (dev->num_outputs >= MAX_OUTPUTS) dev->num_outputs = MAX_OUTPUTS; for (i = 0; i < dev->num_outputs; i++) { -- cgit v1.2.3 From 19905240aef0181d1e6944070eb85fce75f75bcd Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 18 Oct 2022 00:11:41 +0200 Subject: usb: gadget: uvc: limit isoc_sg to super speed gadgets The overhead of preparing sg data is high for transfers with limited payload. When transferring isoc over high-speed usb the maximum payload is rather small which is a good argument no to use sg. This patch is changing the uvc_video_encode_isoc_sg encode function only to be used for super speed gadgets. Signed-off-by: Michael Grzeschik Cc: stable Link: https://lore.kernel.org/r/20221017221141.3134818-1-m.grzeschik@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/uvc_queue.c | 9 +++------ drivers/usb/gadget/function/uvc_video.c | 9 +++++++-- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 0aa3d7e1f3cc..782eaae93140 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -84,12 +84,9 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb) return -ENODEV; buf->state = UVC_BUF_STATE_QUEUED; - if (queue->use_sg) { - buf->sgt = vb2_dma_sg_plane_desc(vb, 0); - buf->sg = buf->sgt->sgl; - } else { - buf->mem = vb2_plane_vaddr(vb, 0); - } + buf->sgt = vb2_dma_sg_plane_desc(vb, 0); + buf->sg = buf->sgt->sgl; + buf->mem = vb2_plane_vaddr(vb, 0); buf->length = vb2_plane_size(vb, 0); if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) buf->bytesused = 0; diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index dd1c6b2ca7c6..b6ea600b0111 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -459,6 +459,9 @@ static void uvcg_video_pump(struct work_struct *work) */ int uvcg_video_enable(struct uvc_video *video, int enable) { + struct uvc_device *uvc = video->uvc; + struct usb_composite_dev *cdev = uvc->func.config->cdev; + struct usb_gadget *gadget = cdev->gadget; unsigned int i; int ret; @@ -490,9 +493,11 @@ int uvcg_video_enable(struct uvc_video *video, int enable) if (video->max_payload_size) { video->encode = uvc_video_encode_bulk; video->payload_size = 0; - } else - video->encode = video->queue.use_sg ? + } else { + video->encode = (video->queue.use_sg && + !(gadget->speed <= USB_SPEED_HIGH)) ? uvc_video_encode_isoc_sg : uvc_video_encode_isoc; + } video->req_int_count = 0; -- cgit v1.2.3 From 3f53c329b31d53b2a2e7992819242fc0d4f883e0 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 30 Sep 2022 16:20:18 +0200 Subject: usb: dwc3: st: Rely on child's compatible instead of name To ensure that child node is found, don't rely on child's node name which can take different value, but on child's compatible name. Fixes: f5c5936d6b4d ("usb: dwc3: st: Fix node's child name") Cc: stable Cc: Jerome Audu Reported-by: Felipe Balbi Signed-off-by: Patrice Chotard Link: https://lore.kernel.org/r/20220930142018.890535-1-patrice.chotard@foss.st.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/dwc3-st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c index 6c14a79279f9..fea5290de83f 100644 --- a/drivers/usb/dwc3/dwc3-st.c +++ b/drivers/usb/dwc3/dwc3-st.c @@ -251,7 +251,7 @@ static int st_dwc3_probe(struct platform_device *pdev) /* Manage SoftReset */ reset_control_deassert(dwc3_data->rstc_rst); - child = of_get_child_by_name(node, "usb"); + child = of_get_compatible_child(node, "snps,dwc3"); if (!child) { dev_err(&pdev->dev, "failed to find dwc3 core node\n"); ret = -ENODEV; -- cgit v1.2.3 From 6746eae4bbaddcc16b40efb33dab79210828b3ce Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 25 Oct 2022 14:10:32 +0100 Subject: coresight: cti: Fix hang in cti_disable_hw() cti_enable_hw() and cti_disable_hw() are called from an atomic context so shouldn't use runtime PM because it can result in a sleep when communicating with firmware. Since commit 3c6656337852 ("Revert "firmware: arm_scmi: Add clock management to the SCMI power domain""), this causes a hang on Juno when running the Perf Coresight tests or running this command: perf record -e cs_etm//u -- ls This was also missed until the revert commit because pm_runtime_put() was called with the wrong device until commit 692c9a499b28 ("coresight: cti: Correct the parameter for pm_runtime_put") With lock and scheduler debugging enabled the following is output: coresight cti_sys0: cti_enable_hw -- dev:cti_sys0 parent: 20020000.cti BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1151 in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 330, name: perf-exec preempt_count: 2, expected: 0 RCU nest depth: 0, expected: 0 INFO: lockdep is turned off. irq event stamp: 0 hardirqs last enabled at (0): [<0000000000000000>] 0x0 hardirqs last disabled at (0): [] copy_process+0xa0c/0x1948 softirqs last enabled at (0): [] copy_process+0xa0c/0x1948 softirqs last disabled at (0): [<0000000000000000>] 0x0 CPU: 3 PID: 330 Comm: perf-exec Not tainted 6.0.0-00053-g042116d99298 #7 Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform, BIOS EDK II Sep 13 2022 Call trace: dump_backtrace+0x134/0x140 show_stack+0x20/0x58 dump_stack_lvl+0x8c/0xb8 dump_stack+0x18/0x34 __might_resched+0x180/0x228 __might_sleep+0x50/0x88 __pm_runtime_resume+0xac/0xb0 cti_enable+0x44/0x120 coresight_control_assoc_ectdev+0xc0/0x150 coresight_enable_path+0xb4/0x288 etm_event_start+0x138/0x170 etm_event_add+0x48/0x70 event_sched_in.isra.122+0xb4/0x280 merge_sched_in+0x1fc/0x3d0 visit_groups_merge.constprop.137+0x16c/0x4b0 ctx_sched_in+0x114/0x1f0 perf_event_sched_in+0x60/0x90 ctx_resched+0x68/0xb0 perf_event_exec+0x138/0x508 begin_new_exec+0x52c/0xd40 load_elf_binary+0x6b8/0x17d0 bprm_execve+0x360/0x7f8 do_execveat_common.isra.47+0x218/0x238 __arm64_sys_execve+0x48/0x60 invoke_syscall+0x4c/0x110 el0_svc_common.constprop.4+0xfc/0x120 do_el0_svc+0x34/0xc0 el0_svc+0x40/0x98 el0t_64_sync_handler+0x98/0xc0 el0t_64_sync+0x170/0x174 Fix the issue by removing the runtime PM calls completely. They are not needed here because it must have already been done when building the path for a trace. Fixes: 835d722ba10a ("coresight: cti: Initial CoreSight CTI Driver") Cc: stable Reported-by: Aishwarya TCV Reported-by: Cristian Marussi Suggested-by: Suzuki K Poulose Signed-off-by: James Clark Reviewed-by: Mike Leach Tested-by: Mike Leach [ Fix build warnings ] Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20221025131032.1149459-1-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-cti-core.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index 1be92342b5b9..c6e8c6542f24 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -90,11 +90,9 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) static int cti_enable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - struct device *dev = &drvdata->csdev->dev; unsigned long flags; int rc = 0; - pm_runtime_get_sync(dev->parent); spin_lock_irqsave(&drvdata->spinlock, flags); /* no need to do anything if enabled or unpowered*/ @@ -119,7 +117,6 @@ cti_state_unchanged: /* cannot enable due to error */ cti_err_not_enabled: spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(dev->parent); return rc; } @@ -153,7 +150,6 @@ cti_hp_not_enabled: static int cti_disable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - struct device *dev = &drvdata->csdev->dev; struct coresight_device *csdev = drvdata->csdev; spin_lock(&drvdata->spinlock); @@ -175,7 +171,6 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); spin_unlock(&drvdata->spinlock); - pm_runtime_put(dev->parent); return 0; /* not disabled this call */ -- cgit v1.2.3 From 677047383296ea25fdfc001be3cdcdf5cc874be2 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 25 Oct 2022 04:52:23 +0200 Subject: misc: sgi-gru: use explicitly signed char With char becoming unsigned by default, and with `char` alone being ambiguous and based on architecture, signed chars need to be marked explicitly as such. This fixes warnings like: drivers/misc/sgi-gru/grumain.c:711 gru_check_chiplet_assignment() warn: 'gts->ts_user_chiplet_id' is unsigned Cc: Dimitri Sivanich Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Signed-off-by: Jason A. Donenfeld Link: https://lore.kernel.org/r/20221025025223.573543-1-Jason@zx2c4.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/sgi-gru/grumain.c | 6 +++--- drivers/misc/sgi-gru/grutables.h | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c index 9afda47efbf2..6706ef3c5977 100644 --- a/drivers/misc/sgi-gru/grumain.c +++ b/drivers/misc/sgi-gru/grumain.c @@ -152,7 +152,7 @@ static int gru_assign_asid(struct gru_state *gru) * Optionally, build an array of chars that contain the bit numbers allocated. */ static unsigned long reserve_resources(unsigned long *p, int n, int mmax, - char *idx) + signed char *idx) { unsigned long bits = 0; int i; @@ -170,14 +170,14 @@ static unsigned long reserve_resources(unsigned long *p, int n, int mmax, } unsigned long gru_reserve_cb_resources(struct gru_state *gru, int cbr_au_count, - char *cbmap) + signed char *cbmap) { return reserve_resources(&gru->gs_cbr_map, cbr_au_count, GRU_CBR_AU, cbmap); } unsigned long gru_reserve_ds_resources(struct gru_state *gru, int dsr_au_count, - char *dsmap) + signed char *dsmap) { return reserve_resources(&gru->gs_dsr_map, dsr_au_count, GRU_DSR_AU, dsmap); diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h index 5efc869fe59a..8c52776db234 100644 --- a/drivers/misc/sgi-gru/grutables.h +++ b/drivers/misc/sgi-gru/grutables.h @@ -351,7 +351,7 @@ struct gru_thread_state { pid_t ts_tgid_owner; /* task that is using the context - for migration */ short ts_user_blade_id;/* user selected blade */ - char ts_user_chiplet_id;/* user selected chiplet */ + signed char ts_user_chiplet_id;/* user selected chiplet */ unsigned short ts_sizeavail; /* Pagesizes in use */ int ts_tsid; /* thread that owns the structure */ @@ -364,11 +364,11 @@ struct gru_thread_state { required for contest */ unsigned char ts_cbr_au_count;/* Number of CBR resources required for contest */ - char ts_cch_req_slice;/* CCH packet slice */ - char ts_blade; /* If >= 0, migrate context if + signed char ts_cch_req_slice;/* CCH packet slice */ + signed char ts_blade; /* If >= 0, migrate context if ref from different blade */ - char ts_force_cch_reload; - char ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each + signed char ts_force_cch_reload; + signed char ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each allocated CB */ int ts_data_valid; /* Indicates if ts_gdata has valid data */ @@ -643,9 +643,9 @@ extern struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, int cbr_au_count, int dsr_au_count, unsigned char tlb_preload_count, int options, int tsid); extern unsigned long gru_reserve_cb_resources(struct gru_state *gru, - int cbr_au_count, char *cbmap); + int cbr_au_count, signed char *cbmap); extern unsigned long gru_reserve_ds_resources(struct gru_state *gru, - int dsr_au_count, char *dsmap); + int dsr_au_count, signed char *dsmap); extern vm_fault_t gru_fault(struct vm_fault *vmf); extern struct gru_mm_struct *gru_register_mmu_notifier(void); extern void gru_drop_mmu_notifier(struct gru_mm_struct *gms); -- cgit v1.2.3 From 937ec9f7d5f2625d60077bb7824fee35dc447c6e Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 25 Oct 2022 14:21:50 +0200 Subject: staging: rtl8192e: remove bogus ssid character sign test This error triggers on some architectures with unsigned `char` types: drivers/staging/rtl8192e/rtllib_softmac_wx.c:459 rtllib_wx_set_essid() warn: impossible condition '(extra[i] < 0) => (0-255 < 0)' But actually, the entire test is bogus, as ssids don't have any sign validity rules like that. So just remove this check look all together. Cc: Greg Kroah-Hartman Cc: linux-staging@lists.linux.dev Signed-off-by: Jason A. Donenfeld Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20221025122150.583617-1-Jason@zx2c4.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac_wx.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c index f9589c5b62ba..1e5ad3b476ef 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c +++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c @@ -439,7 +439,7 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee, union iwreq_data *wrqu, char *extra) { - int ret = 0, len, i; + int ret = 0, len; short proto_started; unsigned long flags; @@ -455,13 +455,6 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee, goto out; } - for (i = 0; i < len; i++) { - if (extra[i] < 0) { - ret = -1; - goto out; - } - } - if (proto_started) rtllib_stop_protocol(ieee, true); -- cgit v1.2.3 From 4f547472380136718b56064ea5689a61e135f904 Mon Sep 17 00:00:00 2001 From: Jens Glathe Date: Mon, 24 Oct 2022 17:27:17 +0300 Subject: usb: xhci: add XHCI_SPURIOUS_SUCCESS to ASM1042 despite being a V0.96 controller This appears to fix the error: "xhci_hcd
; ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13" that appear spuriously (or pretty often) when using a r8152 USB3 ethernet adapter with integrated hub. ASM1042 reports as a 0.96 controller, but appears to behave more like 1.0 Inspired by this email thread: https://markmail.org/thread/7vzqbe7t6du6qsw3 Cc: stable@vger.kernel.org Signed-off-by: Jens Glathe Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20221024142720.4122053-2-mathias.nyman@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 40228a3d77a0..6dd3102749b7 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -306,8 +306,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) } if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && - pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) + pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) { + /* + * try to tame the ASMedia 1042 controller which reports 0.96 + * but appears to behave more like 1.0 + */ + xhci->quirks |= XHCI_SPURIOUS_SUCCESS; xhci->quirks |= XHCI_BROKEN_STREAMS; + } if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) { xhci->quirks |= XHCI_TRUST_TX_LENGTH; -- cgit v1.2.3 From 34cd2db408d591bc15771cbcc90939ade0a99a21 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 24 Oct 2022 17:27:18 +0300 Subject: xhci: Add quirk to reset host back to default state at shutdown Systems based on Alder Lake P see significant boot time delay if boot firmware tries to control usb ports in unexpected link states. This is seen with self-powered usb devices that survive in U3 link suspended state over S5. A more generic solution to power off ports at shutdown was attempted in commit 83810f84ecf1 ("xhci: turn off port power in shutdown") but it caused regression. Add host specific XHCI_RESET_TO_DEFAULT quirk which will reset host and ports back to default state in shutdown. Cc: stable@vger.kernel.org Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20221024142720.4122053-3-mathias.nyman@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 4 ++++ drivers/usb/host/xhci.c | 10 ++++++++-- drivers/usb/host/xhci.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 6dd3102749b7..fbbd547ba12a 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -257,6 +257,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) xhci->quirks |= XHCI_MISSING_CAS; + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI) + xhci->quirks |= XHCI_RESET_TO_DEFAULT; + if (pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_XHCI || diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5176765c4013..79d7931c048a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -810,9 +810,15 @@ void xhci_shutdown(struct usb_hcd *hcd) spin_lock_irq(&xhci->lock); xhci_halt(xhci); - /* Workaround for spurious wakeups at shutdown with HSW */ - if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) + + /* + * Workaround for spurious wakeps at shutdown with HSW, and for boot + * firmware delay in ADL-P PCH if port are left in U3 at shutdown + */ + if (xhci->quirks & XHCI_SPURIOUS_WAKEUP || + xhci->quirks & XHCI_RESET_TO_DEFAULT) xhci_reset(xhci, XHCI_RESET_SHORT_USEC); + spin_unlock_irq(&xhci->lock); xhci_cleanup_msix(xhci); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c0964fe8ac12..cc084d9505cd 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1897,6 +1897,7 @@ struct xhci_hcd { #define XHCI_BROKEN_D3COLD BIT_ULL(41) #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) +#define XHCI_RESET_TO_DEFAULT BIT_ULL(44) unsigned int num_active_eps; unsigned int limit_active_eps; -- cgit v1.2.3 From a611bf473d1f77b70f7188b5577542cb39b4701b Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 24 Oct 2022 17:27:19 +0300 Subject: xhci-pci: Set runtime PM as default policy on all xHC 1.2 or later devices For optimal power consumption of USB4 routers the XHCI PCIe endpoint used for tunneling must be in D3. Historically this is accomplished by a long list of PCIe IDs that correspond to these endpoints because the xhci_hcd driver will not default to allowing runtime PM for all devices. As both AMD and Intel have released new products with new XHCI controllers this list continues to grow. In reviewing the XHCI specification v1.2 on page 607 there is already a requirement that the PCI power management states D3hot and D3cold must be supported. In the quirk list, use this to indicate that runtime PM should be allowed on XHCI controllers. The following controllers are known to be xHC 1.2 and dropped explicitly: * AMD Yellow Carp * Intel Alder Lake * Intel Meteor Lake * Intel Raptor Lake [keep PCI ID for Alder Lake PCH for recently added quirk -Mathias] Cc: stable@vger.kernel.org Suggested-by: Mathias Nyman Link: https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf Signed-off-by: Mario Limonciello Reviewed-by: Mika Westerberg Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20221024142720.4122053-4-mathias.nyman@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fbbd547ba12a..7bccbe50bab1 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -58,25 +58,13 @@ #define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 -#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e -#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI 0x464e -#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed -#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI 0xa71e -#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI 0x7ec0 +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 0x161a -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 0x161b -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 0x161d -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 0x161e -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 0x15d6 -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 0x15d7 -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 0x161c -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8 0x161f #define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042 #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 @@ -272,12 +260,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI)) + pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI)) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; if (pdev->vendor == PCI_VENDOR_ID_ETRON && @@ -346,15 +329,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) xhci->quirks |= XHCI_NO_SOFT_RETRY; - if (pdev->vendor == PCI_VENDOR_ID_AMD && - (pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8)) + /* xHC spec requires PCI devices to support D3hot and D3cold */ + if (xhci->hci_version >= 0x120) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; if (xhci->quirks & XHCI_RESET_ON_RESUME) -- cgit v1.2.3 From 5aed5b7c2430ce318a8e62f752f181e66f0d1053 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 24 Oct 2022 17:27:20 +0300 Subject: xhci: Remove device endpoints from bandwidth list when freeing the device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Endpoints are normally deleted from the bandwidth list when they are dropped, before the virt device is freed. If xHC host is dying or being removed then the endpoints aren't dropped cleanly due to functions returning early to avoid interacting with a non-accessible host controller. So check and delete endpoints that are still on the bandwidth list when freeing the virt device. Solves a list_del corruption kernel crash when unbinding xhci-pci, caused by xhci_mem_cleanup() when it later tried to delete already freed endpoints from the bandwidth list. This only affects hosts that use software bandwidth checking, which currenty is only the xHC in intel Panther Point PCH (Ivy Bridge) Cc: stable@vger.kernel.org Reported-by: Marek Marczykowski-Górecki Tested-by: Marek Marczykowski-Górecki Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20221024142720.4122053-5-mathias.nyman@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 9e56aa28efcd..81ca2bc1f0be 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -889,15 +889,19 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) if (dev->eps[i].stream_info) xhci_free_stream_info(xhci, dev->eps[i].stream_info); - /* Endpoints on the TT/root port lists should have been removed - * when usb_disable_device() was called for the device. - * We can't drop them anyway, because the udev might have gone - * away by this point, and we can't tell what speed it was. + /* + * Endpoints are normally deleted from the bandwidth list when + * endpoints are dropped, before device is freed. + * If host is dying or being removed then endpoints aren't + * dropped cleanly, so delete the endpoint from list here. + * Only applicable for hosts with software bandwidth checking. */ - if (!list_empty(&dev->eps[i].bw_endpoint_list)) - xhci_warn(xhci, "Slot %u endpoint %u " - "not removed from BW list!\n", - slot_id, i); + + if (!list_empty(&dev->eps[i].bw_endpoint_list)) { + list_del_init(&dev->eps[i].bw_endpoint_list); + xhci_dbg(xhci, "Slot %u endpoint %u not removed from BW list!\n", + slot_id, i); + } } /* If this is a hub, free the TT(s) from the TT list */ xhci_free_tt_info(xhci, dev, slot_id); -- cgit v1.2.3 From 92e10465acaffcf65e803f40e884ffa86fd3ff2f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 6 Oct 2022 15:38:07 +0300 Subject: device property: Fix documentation for *_match_string() APIs The returned value on success is an index of the matching string, starting from 0. Reflect this in the documentation. Fixes: 3f5c8d318785 ("device property: Add fwnode_property_match_string()") Signed-off-by: Andy Shevchenko Reviewed-by: Sakari Ailus Signed-off-by: Rafael J. Wysocki --- drivers/base/property.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/property.c b/drivers/base/property.c index 4d6278a84868..2a5a37fcd998 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -229,7 +229,7 @@ EXPORT_SYMBOL_GPL(device_property_read_string); * Find a given string in a string array and if it is found return the * index back. * - * Return: %0 if the property was found (success), + * Return: index, starting from %0, if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of strings, @@ -450,7 +450,7 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_string); * Find a given string in a string array and if it is found return the * index back. * - * Return: %0 if the property was found (success), + * Return: index, starting from %0, if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO if the property is not an array of strings, -- cgit v1.2.3 From 54b5af5a438076082d482cab105b1bd484ab5074 Mon Sep 17 00:00:00 2001 From: Slawomir Laba Date: Mon, 24 Oct 2022 03:05:24 -0700 Subject: i40e: Fix ethtool rx-flow-hash setting for X722 When enabling flow type for RSS hash via ethtool: ethtool -N $pf rx-flow-hash tcp4|tcp6|udp4|udp6 s|d the driver would fail to setup this setting on X722 device since it was using the mask on the register dedicated for X710 devices. Apply a different mask on the register when setting the RSS hash for the X722 device. When displaying the flow types enabled via ethtool: ethtool -n $pf rx-flow-hash tcp4|tcp6|udp4|udp6 the driver would print wrong values for X722 device. Fix this issue by testing masks for X722 device in i40e_get_rss_hash_opts function. Fixes: eb0dd6e4a3b3 ("i40e: Allow RSS Hash set with less than four parameters") Signed-off-by: Slawomir Laba Signed-off-by: Michal Jaron Signed-off-by: Mateusz Palczewski Tested-by: Gurucharan (A Contingent worker at Intel) Signed-off-by: Jacob Keller Link: https://lore.kernel.org/r/20221024100526.1874914-1-jacob.e.keller@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 31 +++++++++++++++++++------- drivers/net/ethernet/intel/i40e/i40e_type.h | 4 ++++ 2 files changed, 27 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 87f36d1ce800..314ef40aa260 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -3185,10 +3185,17 @@ static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd) if (cmd->flow_type == TCP_V4_FLOW || cmd->flow_type == UDP_V4_FLOW) { - if (i_set & I40E_L3_SRC_MASK) - cmd->data |= RXH_IP_SRC; - if (i_set & I40E_L3_DST_MASK) - cmd->data |= RXH_IP_DST; + if (hw->mac.type == I40E_MAC_X722) { + if (i_set & I40E_X722_L3_SRC_MASK) + cmd->data |= RXH_IP_SRC; + if (i_set & I40E_X722_L3_DST_MASK) + cmd->data |= RXH_IP_DST; + } else { + if (i_set & I40E_L3_SRC_MASK) + cmd->data |= RXH_IP_SRC; + if (i_set & I40E_L3_DST_MASK) + cmd->data |= RXH_IP_DST; + } } else if (cmd->flow_type == TCP_V6_FLOW || cmd->flow_type == UDP_V6_FLOW) { if (i_set & I40E_L3_V6_SRC_MASK) @@ -3546,12 +3553,15 @@ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, /** * i40e_get_rss_hash_bits - Read RSS Hash bits from register + * @hw: hw structure * @nfc: pointer to user request * @i_setc: bits currently set * * Returns value of bits to be set per user request **/ -static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc) +static u64 i40e_get_rss_hash_bits(struct i40e_hw *hw, + struct ethtool_rxnfc *nfc, + u64 i_setc) { u64 i_set = i_setc; u64 src_l3 = 0, dst_l3 = 0; @@ -3570,8 +3580,13 @@ static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc) dst_l3 = I40E_L3_V6_DST_MASK; } else if (nfc->flow_type == TCP_V4_FLOW || nfc->flow_type == UDP_V4_FLOW) { - src_l3 = I40E_L3_SRC_MASK; - dst_l3 = I40E_L3_DST_MASK; + if (hw->mac.type == I40E_MAC_X722) { + src_l3 = I40E_X722_L3_SRC_MASK; + dst_l3 = I40E_X722_L3_DST_MASK; + } else { + src_l3 = I40E_L3_SRC_MASK; + dst_l3 = I40E_L3_DST_MASK; + } } else { /* Any other flow type are not supported here */ return i_set; @@ -3686,7 +3701,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) flow_pctype)) | ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype)) << 32); - i_set = i40e_get_rss_hash_bits(nfc, i_setc); + i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc); i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_pctype), (u32)i_set); i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype), diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 7b3f30beb757..388c3d36d96a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1404,6 +1404,10 @@ struct i40e_lldp_variables { #define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000 /* INPUT SET MASK for RSS, flow director, and flexible payload */ +#define I40E_X722_L3_SRC_SHIFT 49 +#define I40E_X722_L3_SRC_MASK (0x3ULL << I40E_X722_L3_SRC_SHIFT) +#define I40E_X722_L3_DST_SHIFT 41 +#define I40E_X722_L3_DST_MASK (0x3ULL << I40E_X722_L3_DST_SHIFT) #define I40E_L3_SRC_SHIFT 47 #define I40E_L3_SRC_MASK (0x3ULL << I40E_L3_SRC_SHIFT) #define I40E_L3_V6_SRC_SHIFT 43 -- cgit v1.2.3 From 52424f974bc53c26ba3f00300a00e9de9afcd972 Mon Sep 17 00:00:00 2001 From: Sylwester Dziedziuch Date: Mon, 24 Oct 2022 03:05:25 -0700 Subject: i40e: Fix VF hang when reset is triggered on another VF When a reset was triggered on one VF with i40e_reset_vf global PF state __I40E_VF_DISABLE was set on a PF until the reset finished. If immediately after triggering reset on one VF there is a request to reset on another it will cause a hang on VF side because VF will be notified of incoming reset but the reset will never happen because of this global state, we will get such error message: [ +4.890195] iavf 0000:86:02.1: Never saw reset and VF will hang waiting for the reset to be triggered. Fix this by introducing new VF state I40E_VF_STATE_RESETTING that will be set on a VF if it is currently resetting instead of the global __I40E_VF_DISABLE PF state. Fixes: 3ba9bcb4b68f ("i40e: add locking around VF reset") Signed-off-by: Sylwester Dziedziuch Signed-off-by: Mateusz Palczewski Tested-by: Konrad Jankowski Signed-off-by: Jacob Keller Link: https://lore.kernel.org/r/20221024100526.1874914-2-jacob.e.keller@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 43 ++++++++++++++++------ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 1 + 2 files changed, 33 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 7e9f6a69eb10..72ddcefc45b1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1536,10 +1536,12 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) return true; - /* If the VFs have been disabled, this means something else is - * resetting the VF, so we shouldn't continue. - */ - if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) + /* Bail out if VFs are disabled. */ + if (test_bit(__I40E_VF_DISABLE, pf->state)) + return true; + + /* If VF is being reset already we don't need to continue. */ + if (test_and_set_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) return true; i40e_trigger_vf_reset(vf, flr); @@ -1576,7 +1578,7 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) i40e_cleanup_reset_vf(vf); i40e_flush(hw); - clear_bit(__I40E_VF_DISABLE, pf->state); + clear_bit(I40E_VF_STATE_RESETTING, &vf->vf_states); return true; } @@ -1609,8 +1611,12 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) return false; /* Begin reset on all VFs at once */ - for (v = 0; v < pf->num_alloc_vfs; v++) - i40e_trigger_vf_reset(&pf->vf[v], flr); + for (v = 0; v < pf->num_alloc_vfs; v++) { + vf = &pf->vf[v]; + /* If VF is being reset no need to trigger reset again */ + if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) + i40e_trigger_vf_reset(&pf->vf[v], flr); + } /* HW requires some time to make sure it can flush the FIFO for a VF * when it resets it. Poll the VPGEN_VFRSTAT register for each VF in @@ -1626,9 +1632,11 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) */ while (v < pf->num_alloc_vfs) { vf = &pf->vf[v]; - reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id)); - if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK)) - break; + if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) { + reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id)); + if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK)) + break; + } /* If the current VF has finished resetting, move on * to the next VF in sequence. @@ -1656,6 +1664,10 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) if (pf->vf[v].lan_vsi_idx == 0) continue; + /* If VF is reset in another thread just continue */ + if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) + continue; + i40e_vsi_stop_rings_no_wait(pf->vsi[pf->vf[v].lan_vsi_idx]); } @@ -1667,6 +1679,10 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) if (pf->vf[v].lan_vsi_idx == 0) continue; + /* If VF is reset in another thread just continue */ + if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) + continue; + i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[v].lan_vsi_idx]); } @@ -1676,8 +1692,13 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) mdelay(50); /* Finish the reset on each VF */ - for (v = 0; v < pf->num_alloc_vfs; v++) + for (v = 0; v < pf->num_alloc_vfs; v++) { + /* If VF is reset in another thread just continue */ + if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) + continue; + i40e_cleanup_reset_vf(&pf->vf[v]); + } i40e_flush(hw); clear_bit(__I40E_VF_DISABLE, pf->state); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index a554d0a0b09b..358bbdb58795 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h @@ -39,6 +39,7 @@ enum i40e_vf_states { I40E_VF_STATE_MC_PROMISC, I40E_VF_STATE_UC_PROMISC, I40E_VF_STATE_PRE_ENABLE, + I40E_VF_STATE_RESETTING }; /* VF capabilities */ -- cgit v1.2.3 From 3b32c9932853e11d71f9db012d69e92e4669ba23 Mon Sep 17 00:00:00 2001 From: Slawomir Laba Date: Mon, 24 Oct 2022 03:05:26 -0700 Subject: i40e: Fix flow-type by setting GL_HASH_INSET registers Fix setting bits for specific flow_type for GLQF_HASH_INSET register. In previous version all of the bits were set only in hena register, while in inset only one bit was set. In order for this working correctly on all types of cards these bits needs to be set correctly for both hena and inset registers. Fixes: eb0dd6e4a3b3 ("i40e: Allow RSS Hash set with less than four parameters") Signed-off-by: Slawomir Laba Signed-off-by: Michal Jaron Signed-off-by: Mateusz Palczewski Signed-off-by: Jacob Keller Link: https://lore.kernel.org/r/20221024100526.1874914-3-jacob.e.keller@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 71 ++++++++++++++------------ 1 file changed, 38 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 314ef40aa260..4a6a6e48c615 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -3604,6 +3604,7 @@ static u64 i40e_get_rss_hash_bits(struct i40e_hw *hw, return i_set; } +#define FLOW_PCTYPES_SIZE 64 /** * i40e_set_rss_hash_opt - Enable/Disable flow types for RSS hash * @pf: pointer to the physical function struct @@ -3616,9 +3617,11 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) struct i40e_hw *hw = &pf->hw; u64 hena = (u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0)) | ((u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1)) << 32); - u8 flow_pctype = 0; + DECLARE_BITMAP(flow_pctypes, FLOW_PCTYPES_SIZE); u64 i_set, i_setc; + bitmap_zero(flow_pctypes, FLOW_PCTYPES_SIZE); + if (pf->flags & I40E_FLAG_MFP_ENABLED) { dev_err(&pf->pdev->dev, "Change of RSS hash input set is not supported when MFP mode is enabled\n"); @@ -3634,36 +3637,35 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) switch (nfc->flow_type) { case TCP_V4_FLOW: - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP; + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, flow_pctypes); if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK, + flow_pctypes); break; case TCP_V6_FLOW: - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_TCP; - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, flow_pctypes); if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK); + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK, + flow_pctypes); break; case UDP_V4_FLOW: - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP); - + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, flow_pctypes); + if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) { + set_bit(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP, + flow_pctypes); + set_bit(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP, + flow_pctypes); + } hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4); break; case UDP_V6_FLOW: - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_UDP; - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP); - + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, flow_pctypes); + if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) { + set_bit(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP, + flow_pctypes); + set_bit(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP, + flow_pctypes); + } hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6); break; case AH_ESP_V4_FLOW: @@ -3696,17 +3698,20 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) return -EINVAL; } - if (flow_pctype) { - i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, - flow_pctype)) | - ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, - flow_pctype)) << 32); - i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc); - i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_pctype), - (u32)i_set); - i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype), - (u32)(i_set >> 32)); - hena |= BIT_ULL(flow_pctype); + if (bitmap_weight(flow_pctypes, FLOW_PCTYPES_SIZE)) { + u8 flow_id; + + for_each_set_bit(flow_id, flow_pctypes, FLOW_PCTYPES_SIZE) { + i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_id)) | + ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_id)) << 32); + i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc); + + i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_id), + (u32)i_set); + i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_id), + (u32)(i_set >> 32)); + hena |= BIT_ULL(flow_id); + } } i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (u32)hena); -- cgit v1.2.3 From 5da6d65590a0698199df44d095e54b0ed1708178 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 24 Oct 2022 21:13:38 +0800 Subject: net: ksz884x: fix missing pci_disable_device() on error in pcidev_init() pci_disable_device() need be called while module exiting, switch to use pcim_enable(), pci_disable_device() will be called in pcim_release() while unbinding device. Fixes: 8ca86fd83eae ("net: Micrel KSZ8841/2 PCI Ethernet driver") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221024131338.2848959-1-yangyingliang@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/micrel/ksz884x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 468520079c65..e6acd1e7b263 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -6851,7 +6851,7 @@ static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id) char banner[sizeof(version)]; struct ksz_switch *sw = NULL; - result = pci_enable_device(pdev); + result = pcim_enable_device(pdev); if (result) return result; -- cgit v1.2.3 From f23a566bbfc0896c97b1949216eb87fcdcb154bb Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 24 Oct 2022 22:03:31 +0100 Subject: net: ipa: fix v3.5.1 resource limit max values Some resource limits on IPA v3.5.1 have their max values set to 255, this causes a few splats in ipa_reg_encode and prevents the IPA from booting properly. The limits are all 6 bits wide so adjust the max values to 63. Fixes: 1c418c4a929c ("net: ipa: define resource group/type IPA register fields") Signed-off-by: Caleb Connolly Reviewed-by: Alex Elder Link: https://lore.kernel.org/r/20221024210336.4014983-1-caleb.connolly@linaro.org Signed-off-by: Jakub Kicinski --- drivers/net/ipa/data/ipa_data-v3.5.1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ipa/data/ipa_data-v3.5.1.c b/drivers/net/ipa/data/ipa_data-v3.5.1.c index 383ef1890065..42f2c88a92d4 100644 --- a/drivers/net/ipa/data/ipa_data-v3.5.1.c +++ b/drivers/net/ipa/data/ipa_data-v3.5.1.c @@ -179,10 +179,10 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = { static const struct ipa_resource ipa_resource_src[] = { [IPA_RESOURCE_TYPE_SRC_PKT_CONTEXTS] = { .limits[IPA_RSRC_GROUP_SRC_LWA_DL] = { - .min = 1, .max = 255, + .min = 1, .max = 63, }, .limits[IPA_RSRC_GROUP_SRC_UL_DL] = { - .min = 1, .max = 255, + .min = 1, .max = 63, }, .limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = { .min = 1, .max = 63, -- cgit v1.2.3 From 05a31b94af3226ee47dcb6802229a7a576105d47 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 24 Oct 2022 22:03:32 +0100 Subject: net: ipa: fix v3.1 resource limit masks The resource group limits for IPA v3.1 mistakenly used 6 bit wide mask values, when the hardware actually uses 8. Out of range values were silently ignored before, so the IPA worked as expected. However the new generalised register definitions introduce stricter checking here, they now cause some splats and result in the value 0 being written instead. Fix the limit bitmask widths so that the correct values can be written. Fixes: 1c418c4a929c ("net: ipa: define resource group/type IPA register fields") Signed-off-by: Caleb Connolly Reviewed-by: Alex Elder Tested-by: Jami Kettunen Link: https://lore.kernel.org/r/20221024210336.4014983-2-caleb.connolly@linaro.org Signed-off-by: Jakub Kicinski --- drivers/net/ipa/reg/ipa_reg-v3.1.c | 96 +++++++++++++------------------------- 1 file changed, 32 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ipa/reg/ipa_reg-v3.1.c b/drivers/net/ipa/reg/ipa_reg-v3.1.c index 116b27717e3d..0d002c3c38a2 100644 --- a/drivers/net/ipa/reg/ipa_reg-v3.1.c +++ b/drivers/net/ipa/reg/ipa_reg-v3.1.c @@ -127,112 +127,80 @@ static const u32 ipa_reg_counter_cfg_fmask[] = { IPA_REG_FIELDS(COUNTER_CFG, counter_cfg, 0x000001f0); static const u32 ipa_reg_src_rsrc_grp_01_rsrc_type_fmask[] = { - [X_MIN_LIM] = GENMASK(5, 0), - /* Bits 6-7 reserved */ - [X_MAX_LIM] = GENMASK(13, 8), - /* Bits 14-15 reserved */ - [Y_MIN_LIM] = GENMASK(21, 16), - /* Bits 22-23 reserved */ - [Y_MAX_LIM] = GENMASK(29, 24), - /* Bits 30-31 reserved */ + [X_MIN_LIM] = GENMASK(7, 0), + [X_MAX_LIM] = GENMASK(15, 8), + [Y_MIN_LIM] = GENMASK(23, 16), + [Y_MAX_LIM] = GENMASK(31, 24), }; IPA_REG_STRIDE_FIELDS(SRC_RSRC_GRP_01_RSRC_TYPE, src_rsrc_grp_01_rsrc_type, 0x00000400, 0x0020); static const u32 ipa_reg_src_rsrc_grp_23_rsrc_type_fmask[] = { - [X_MIN_LIM] = GENMASK(5, 0), - /* Bits 6-7 reserved */ - [X_MAX_LIM] = GENMASK(13, 8), - /* Bits 14-15 reserved */ - [Y_MIN_LIM] = GENMASK(21, 16), - /* Bits 22-23 reserved */ - [Y_MAX_LIM] = GENMASK(29, 24), - /* Bits 30-31 reserved */ + [X_MIN_LIM] = GENMASK(7, 0), + [X_MAX_LIM] = GENMASK(15, 8), + [Y_MIN_LIM] = GENMASK(23, 16), + [Y_MAX_LIM] = GENMASK(31, 24), }; IPA_REG_STRIDE_FIELDS(SRC_RSRC_GRP_23_RSRC_TYPE, src_rsrc_grp_23_rsrc_type, 0x00000404, 0x0020); static const u32 ipa_reg_src_rsrc_grp_45_rsrc_type_fmask[] = { - [X_MIN_LIM] = GENMASK(5, 0), - /* Bits 6-7 reserved */ - [X_MAX_LIM] = GENMASK(13, 8), - /* Bits 14-15 reserved */ - [Y_MIN_LIM] = GENMASK(21, 16), - /* Bits 22-23 reserved */ - [Y_MAX_LIM] = GENMASK(29, 24), - /* Bits 30-31 reserved */ + [X_MIN_LIM] = GENMASK(7, 0), + [X_MAX_LIM] = GENMASK(15, 8), + [Y_MIN_LIM] = GENMASK(23, 16), + [Y_MAX_LIM] = GENMASK(31, 24), }; IPA_REG_STRIDE_FIELDS(SRC_RSRC_GRP_45_RSRC_TYPE, src_rsrc_grp_45_rsrc_type, 0x00000408, 0x0020); static const u32 ipa_reg_src_rsrc_grp_67_rsrc_type_fmask[] = { - [X_MIN_LIM] = GENMASK(5, 0), - /* Bits 6-7 reserved */ - [X_MAX_LIM] = GENMASK(13, 8), - /* Bits 14-15 reserved */ - [Y_MIN_LIM] = GENMASK(21, 16), - /* Bits 22-23 reserved */ - [Y_MAX_LIM] = GENMASK(29, 24), - /* Bits 30-31 reserved */ + [X_MIN_LIM] = GENMASK(7, 0), + [X_MAX_LIM] = GENMASK(15, 8), + [Y_MIN_LIM] = GENMASK(23, 16), + [Y_MAX_LIM] = GENMASK(31, 24), }; IPA_REG_STRIDE_FIELDS(SRC_RSRC_GRP_67_RSRC_TYPE, src_rsrc_grp_67_rsrc_type, 0x0000040c, 0x0020); static const u32 ipa_reg_dst_rsrc_grp_01_rsrc_type_fmask[] = { - [X_MIN_LIM] = GENMASK(5, 0), - /* Bits 6-7 reserved */ - [X_MAX_LIM] = GENMASK(13, 8), - /* Bits 14-15 reserved */ - [Y_MIN_LIM] = GENMASK(21, 16), - /* Bits 22-23 reserved */ - [Y_MAX_LIM] = GENMASK(29, 24), - /* Bits 30-31 reserved */ + [X_MIN_LIM] = GENMASK(7, 0), + [X_MAX_LIM] = GENMASK(15, 8), + [Y_MIN_LIM] = GENMASK(23, 16), + [Y_MAX_LIM] = GENMASK(31, 24), }; IPA_REG_STRIDE_FIELDS(DST_RSRC_GRP_01_RSRC_TYPE, dst_rsrc_grp_01_rsrc_type, 0x00000500, 0x0020); static const u32 ipa_reg_dst_rsrc_grp_23_rsrc_type_fmask[] = { - [X_MIN_LIM] = GENMASK(5, 0), - /* Bits 6-7 reserved */ - [X_MAX_LIM] = GENMASK(13, 8), - /* Bits 14-15 reserved */ - [Y_MIN_LIM] = GENMASK(21, 16), - /* Bits 22-23 reserved */ - [Y_MAX_LIM] = GENMASK(29, 24), - /* Bits 30-31 reserved */ + [X_MIN_LIM] = GENMASK(7, 0), + [X_MAX_LIM] = GENMASK(15, 8), + [Y_MIN_LIM] = GENMASK(23, 16), + [Y_MAX_LIM] = GENMASK(31, 24), }; IPA_REG_STRIDE_FIELDS(DST_RSRC_GRP_23_RSRC_TYPE, dst_rsrc_grp_23_rsrc_type, 0x00000504, 0x0020); static const u32 ipa_reg_dst_rsrc_grp_45_rsrc_type_fmask[] = { - [X_MIN_LIM] = GENMASK(5, 0), - /* Bits 6-7 reserved */ - [X_MAX_LIM] = GENMASK(13, 8), - /* Bits 14-15 reserved */ - [Y_MIN_LIM] = GENMASK(21, 16), - /* Bits 22-23 reserved */ - [Y_MAX_LIM] = GENMASK(29, 24), - /* Bits 30-31 reserved */ + [X_MIN_LIM] = GENMASK(7, 0), + [X_MAX_LIM] = GENMASK(15, 8), + [Y_MIN_LIM] = GENMASK(23, 16), + [Y_MAX_LIM] = GENMASK(31, 24), }; IPA_REG_STRIDE_FIELDS(DST_RSRC_GRP_45_RSRC_TYPE, dst_rsrc_grp_45_rsrc_type, 0x00000508, 0x0020); static const u32 ipa_reg_dst_rsrc_grp_67_rsrc_type_fmask[] = { - [X_MIN_LIM] = GENMASK(5, 0), - /* Bits 6-7 reserved */ - [X_MAX_LIM] = GENMASK(13, 8), - /* Bits 14-15 reserved */ - [Y_MIN_LIM] = GENMASK(21, 16), - /* Bits 22-23 reserved */ - [Y_MAX_LIM] = GENMASK(29, 24), - /* Bits 30-31 reserved */ + [X_MIN_LIM] = GENMASK(7, 0), + [X_MAX_LIM] = GENMASK(15, 8), + [Y_MIN_LIM] = GENMASK(23, 16), + [Y_MAX_LIM] = GENMASK(31, 24), }; IPA_REG_STRIDE_FIELDS(DST_RSRC_GRP_67_RSRC_TYPE, dst_rsrc_grp_67_rsrc_type, -- cgit v1.2.3 From 95a0396a0642d3c28b6cefdc76697e0b8f594825 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 25 Oct 2022 00:48:50 +0100 Subject: net: ipa: don't configure IDLE_INDICATION on v3.1 IPA v3.1 doesn't support the IDLE_INDICATION_CFG register, this was causing a harmless splat in ipa_idle_indication_cfg(), add a version check to prevent trying to fetch this register on v3.1 Fixes: 6a244b75cfab ("net: ipa: introduce ipa_reg()") Signed-off-by: Caleb Connolly Reviewed-by: Alex Elder Tested-by: Jami Kettunen Link: https://lore.kernel.org/r/20221024234850.4049778-1-caleb.connolly@linaro.org Signed-off-by: Jakub Kicinski --- drivers/net/ipa/ipa_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index 3461ad3029ab..49537fccf6ad 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -434,6 +434,9 @@ static void ipa_idle_indication_cfg(struct ipa *ipa, const struct ipa_reg *reg; u32 val; + if (ipa->version < IPA_VERSION_3_5_1) + return; + reg = ipa_reg(ipa, IDLE_INDICATION_CFG); val = ipa_reg_encode(reg, ENTER_IDLE_DEBOUNCE_THRESH, enter_idle_debounce_thresh); -- cgit v1.2.3 From 8d280b1df87e0b3d1355aeac7e62b62214b93f1c Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 24 Oct 2022 11:02:59 -0700 Subject: mmc: sdhci_am654: 'select', not 'depends' REGMAP_MMIO REGMAP_MMIO is not user-configurable, so we can only satisfy this dependency by enabling some other Kconfig symbol that properly 'select's it. Use select like everybody else. Noticed when trying to enable this driver for compile testing. Fixes: 59592cc1f593 ("mmc: sdhci_am654: Add dependency on MMC_SDHCI_AM654") Signed-off-by: Brian Norris Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221024180300.2292208-1-briannorris@chromium.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index f324daadaf70..fb1062a6394c 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -1075,9 +1075,10 @@ config MMC_SDHCI_OMAP config MMC_SDHCI_AM654 tristate "Support for the SDHCI Controller in TI's AM654 SOCs" - depends on MMC_SDHCI_PLTFM && OF && REGMAP_MMIO + depends on MMC_SDHCI_PLTFM && OF select MMC_SDHCI_IO_ACCESSORS select MMC_CQHCI + select REGMAP_MMIO help This selects the Secure Digital Host Controller Interface (SDHCI) support present in TI's AM654 SOCs. The controller supports -- cgit v1.2.3 From a9003f74f5a2f487e101f3aa1dd5c3d3a78c6999 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 7 Oct 2022 15:10:01 +0200 Subject: clk: renesas: r8a779g0: Fix HSCIF parent clocks As serial communication requires a clean clock signal, the High Speed Serial Communication Interfaces with FIFO (HSCIF) is clocked by a clock that is not affected by Spread Spectrum or Fractional Multiplication. Hence change the parent clocks for the HSCIF modules from the S0D3_PER clock to the SASYNCPERD1 clock (which has the same clock rate), cfr. R-Car V4H Hardware User's Manual rev. 0.54. Fixes: 0ab55cf1834177a2 ("clk: renesas: cpg-mssr: Add support for R-Car V4H") Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Link: https://lore.kernel.org/r/b7928abc8b9f53d5b06ec8624342f449de3d24ec.1665147497.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779g0-cpg-mssr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c index 3e8c93facfa1..d5b325e3c539 100644 --- a/drivers/clk/renesas/r8a779g0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c @@ -158,10 +158,10 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = { DEF_MOD("avb0", 211, R8A779G0_CLK_S0D4_HSC), DEF_MOD("avb1", 212, R8A779G0_CLK_S0D4_HSC), DEF_MOD("avb2", 213, R8A779G0_CLK_S0D4_HSC), - DEF_MOD("hscif0", 514, R8A779G0_CLK_S0D3_PER), - DEF_MOD("hscif1", 515, R8A779G0_CLK_S0D3_PER), - DEF_MOD("hscif2", 516, R8A779G0_CLK_S0D3_PER), - DEF_MOD("hscif3", 517, R8A779G0_CLK_S0D3_PER), + DEF_MOD("hscif0", 514, R8A779G0_CLK_SASYNCPERD1), + DEF_MOD("hscif1", 515, R8A779G0_CLK_SASYNCPERD1), + DEF_MOD("hscif2", 516, R8A779G0_CLK_SASYNCPERD1), + DEF_MOD("hscif3", 517, R8A779G0_CLK_SASYNCPERD1), DEF_MOD("i2c0", 518, R8A779G0_CLK_S0D6_PER), DEF_MOD("i2c1", 519, R8A779G0_CLK_S0D6_PER), DEF_MOD("i2c2", 520, R8A779G0_CLK_S0D6_PER), -- cgit v1.2.3 From e0c57a5c70c13317238cb19a7ded0eab4a5f7de5 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 25 Oct 2022 13:34:32 +0100 Subject: PM: domains: Fix handling of unavailable/disabled idle states Platforms can provide the information about the availability of each idle states via status flag. Platforms may have to disable one or more idle states for various reasons like broken firmware or other unmet dependencies. Fix handling of such unavailable/disabled idle states by ignoring them while parsing the states. Fixes: a3381e3a65cb ("PM / domains: Fix up domain-idle-states OF parsing") Signed-off-by: Sudeep Holla Reviewed-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index ead135c7044c..6471b559230e 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2952,6 +2952,10 @@ static int genpd_iterate_idle_states(struct device_node *dn, np = it.node; if (!of_match_node(idle_state_match, np)) continue; + + if (!of_device_is_available(np)) + continue; + if (states) { ret = genpd_parse_state(&states[i], np); if (ret) { -- cgit v1.2.3 From 8338b74a750c534c223e8943cc0ed0e198ece261 Mon Sep 17 00:00:00 2001 From: Manank Patel Date: Tue, 18 Oct 2022 00:13:39 +0530 Subject: ACPI: PCC: Fix unintentional integer overflow Fix an unintentional u32 overflow by changing PCC_CMD_WAIT_RETRIES_NUM to 500ULL. Fixes: 91cefefb6991 ("ACPI: PCC: replace wait_for_completion()") Signed-off-by: Manank Patel Acked-by: Sudeep Holla Acked-by: Huisong Li Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_pcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c index ee4ce5ba1fb2..3e252be047b8 100644 --- a/drivers/acpi/acpi_pcc.c +++ b/drivers/acpi/acpi_pcc.c @@ -27,7 +27,7 @@ * Arbitrary retries in case the remote processor is slow to respond * to PCC commands */ -#define PCC_CMD_WAIT_RETRIES_NUM 500 +#define PCC_CMD_WAIT_RETRIES_NUM 500ULL struct pcc_data { struct pcc_mbox_chan *pcc_chan; -- cgit v1.2.3 From b5f9223a105d9b56954ad1ca3eace4eaf26c99ed Mon Sep 17 00:00:00 2001 From: Tamim Khan Date: Fri, 14 Oct 2022 01:19:31 -0400 Subject: ACPI: resource: Skip IRQ override on Asus Vivobook S5602ZA Like the Asus Vivobook K3402ZA/K3502ZA/S5402ZA Asus Vivobook S5602ZA has an ACPI DSDT table the describes IRQ 1 as ActiveLow while the kernel overrides it to Edge_High. This prevents the keyboard on this laptop from working. To fix this add this laptop to the skip_override_table so that the kernel does not override IRQ 1. Link: https://bugzilla.kernel.org/show_bug.cgi?id=216579 Tested-by: Dzmitry Signed-off-by: Tamim Khan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 78c2804164c6..f27914aedbd5 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -425,6 +425,13 @@ static const struct dmi_system_id asus_laptop[] = { DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"), }, }, + { + .ident = "Asus Vivobook S5602ZA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"), + }, + }, { } }; -- cgit v1.2.3 From fa153b7cddce795662d38f78a87612c166c0f692 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 25 Oct 2022 14:12:23 +0200 Subject: ACPI: scan: Add LATT2021 to acpi_ignore_dep_ids[] Some x86/ACPI laptops with MIPI cameras have a LATT2021 ACPI device in the _DEP dependency list of the ACPI devices for the camera-sensors (which have flags.honor_deps set). The _DDN for the LATT2021 device is "Lattice FW Update Client Driver", suggesting that this is used for firmware updates of something. There is no Linux driver for this and if Linux gets support for updates it will likely be in userspace through fwupd. For now add the LATT2021 HID to acpi_ignore_dep_ids[] so that acpi_dev_ready_for_enumeration() will return true once the other _DEP dependencies are met. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 024cc373a197..b47e93a24a9a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -789,6 +789,7 @@ static bool acpi_info_matches_ids(struct acpi_device_info *info, static const char * const acpi_ignore_dep_ids[] = { "PNP0D80", /* Windows-compatible System Power Management Controller */ "INT33BD", /* Intel Baytrail Mailbox Device */ + "LATT2021", /* Lattice FW Update Client Driver */ NULL }; -- cgit v1.2.3 From 88c8e05ed5c0f05a637e654bbe4e49a1ebe7013c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Oct 2022 14:09:06 +0200 Subject: Revert "usb: gadget: uvc: limit isoc_sg to super speed gadgets" This reverts commit 19905240aef0181d1e6944070eb85fce75f75bcd. It was a new feature, and it doesn't even work properly yet, so revert it from this branch as it is not needed for 6.1-final. Cc: Michael Grzeschik Cc: stable Fixes: 19905240aef0 ("usb: gadget: uvc: limit isoc_sg to super speed gadgets") Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/uvc_queue.c | 9 ++++++--- drivers/usb/gadget/function/uvc_video.c | 9 ++------- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 782eaae93140..0aa3d7e1f3cc 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -84,9 +84,12 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb) return -ENODEV; buf->state = UVC_BUF_STATE_QUEUED; - buf->sgt = vb2_dma_sg_plane_desc(vb, 0); - buf->sg = buf->sgt->sgl; - buf->mem = vb2_plane_vaddr(vb, 0); + if (queue->use_sg) { + buf->sgt = vb2_dma_sg_plane_desc(vb, 0); + buf->sg = buf->sgt->sgl; + } else { + buf->mem = vb2_plane_vaddr(vb, 0); + } buf->length = vb2_plane_size(vb, 0); if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) buf->bytesused = 0; diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index b6ea600b0111..dd1c6b2ca7c6 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -459,9 +459,6 @@ static void uvcg_video_pump(struct work_struct *work) */ int uvcg_video_enable(struct uvc_video *video, int enable) { - struct uvc_device *uvc = video->uvc; - struct usb_composite_dev *cdev = uvc->func.config->cdev; - struct usb_gadget *gadget = cdev->gadget; unsigned int i; int ret; @@ -493,11 +490,9 @@ int uvcg_video_enable(struct uvc_video *video, int enable) if (video->max_payload_size) { video->encode = uvc_video_encode_bulk; video->payload_size = 0; - } else { - video->encode = (video->queue.use_sg && - !(gadget->speed <= USB_SPEED_HIGH)) ? + } else + video->encode = video->queue.use_sg ? uvc_video_encode_isoc_sg : uvc_video_encode_isoc; - } video->req_int_count = 0; -- cgit v1.2.3 From 1b6074112742f65ece71b0f299ca5a6a887d2db6 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 14 Oct 2022 12:24:58 +0200 Subject: s390/cio: fix out-of-bounds access on cio_ignore free The channel-subsystem-driver scans for newly available devices whenever device-IDs are removed from the cio_ignore list using a command such as: echo free >/proc/cio_ignore Since an I/O device scan might interfer with running I/Os, commit 172da89ed0ea ("s390/cio: avoid excessive path-verification requests") introduced an optimization to exclude online devices from the scan. The newly added check for online devices incorrectly assumes that an I/O-subchannel's drvdata points to a struct io_subchannel_private. For devices that are bound to a non-default I/O subchannel driver, such as the vfio_ccw driver, this results in an out-of-bounds read access during each scan. Fix this by changing the scan logic to rely on a driver-independent online indication. For this we can use struct subchannel->config.ena, which is the driver's requested subchannel-enabled state. Since I/Os can only be started on enabled subchannels, this matches the intent of the original optimization of not scanning devices where I/O might be running. Fixes: 172da89ed0ea ("s390/cio: avoid excessive path-verification requests") Fixes: 0c3812c347bf ("s390/cio: derive cdev information only for IO-subchannels") Cc: # v5.15 Reported-by: Alexander Egorenkov Reviewed-by: Vineeth Vijayan Signed-off-by: Peter Oberparleiter Signed-off-by: Vasily Gorbik --- drivers/s390/cio/css.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 913b6ddd040b..c7db95398500 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -753,13 +753,9 @@ static int __unset_online(struct device *dev, void *data) { struct idset *set = data; struct subchannel *sch = to_subchannel(dev); - struct ccw_device *cdev; - if (sch->st == SUBCHANNEL_TYPE_IO) { - cdev = sch_get_cdev(sch); - if (cdev && cdev->online) - idset_sch_del(set, sch->schid); - } + if (sch->st == SUBCHANNEL_TYPE_IO && sch->config.ena) + idset_sch_del(set, sch->schid); return 0; } -- cgit v1.2.3 From e38de4804421b064a9c73c5a9b7f3df96b863e4b Mon Sep 17 00:00:00 2001 From: "Jason J. Herne" Date: Fri, 21 Oct 2022 10:50:02 -0400 Subject: s390/vfio-ap: Fix memory allocation for mdev_types array The vfio-ap crypto driver fails to allocate memory for an array of pointers used to pass supported mdev types to mdev_register_parent(). Since we only support a single mdev type, the fix is to allocate a single entry in the ap_matrix_dev->mdev_types array. Link: https://lore.kernel.org/r/20221021145905.15100-1-jjherne@linux.ibm.com Fixes: da44c340c4fe ("vfio/mdev: simplify mdev_type handling") Cc: stable@vger.kernel.org Cc: Tony Krowiak Reported-by: Christian Borntraeger Reviewed-by: Matthew Rosato Signed-off-by: Jason J. Herne Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/vfio_ap_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h index 2eddd5f34ed3..976a65f32e7d 100644 --- a/drivers/s390/crypto/vfio_ap_private.h +++ b/drivers/s390/crypto/vfio_ap_private.h @@ -52,7 +52,7 @@ struct ap_matrix_dev { struct mutex guests_lock; /* serializes access to each KVM guest */ struct mdev_parent parent; struct mdev_type mdev_type; - struct mdev_type *mdev_types[]; + struct mdev_type *mdev_types[1]; }; extern struct ap_matrix_dev *matrix_dev; -- cgit v1.2.3 From 04694e50020b62b10bd0d46ff9e9708a6e1c7eb3 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 26 Oct 2022 09:58:28 +0200 Subject: spi: meson-spicc: move wait completion in driver to take bursts delay in account Some delay occurs between each bursts, thus the default delay is wrong and a timeout will occur with big enough transfers. The solution is to handle the timeout management in the driver and add some delay for each bursts in the timeout calculation. Reported-by: Da Xue Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20221026-spicc-burst-delay-v1-0-1be5ffb7051a@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-meson-spicc.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index bad201510a99..52bffab18329 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -160,6 +160,7 @@ struct meson_spicc_device { struct clk *clk; struct spi_message *message; struct spi_transfer *xfer; + struct completion done; const struct meson_spicc_data *data; u8 *tx_buf; u8 *rx_buf; @@ -282,7 +283,7 @@ static irqreturn_t meson_spicc_irq(int irq, void *data) /* Disable all IRQs */ writel(0, spicc->base + SPICC_INTREG); - spi_finalize_current_transfer(spicc->master); + complete(&spicc->done); return IRQ_HANDLED; } @@ -386,6 +387,7 @@ static int meson_spicc_transfer_one(struct spi_master *master, struct spi_transfer *xfer) { struct meson_spicc_device *spicc = spi_master_get_devdata(master); + unsigned long timeout; /* Store current transfer */ spicc->xfer = xfer; @@ -410,13 +412,29 @@ static int meson_spicc_transfer_one(struct spi_master *master, /* Setup burst */ meson_spicc_setup_burst(spicc); + /* Setup wait for completion */ + reinit_completion(&spicc->done); + + /* For each byte we wait for 8 cycles of the SPI clock */ + timeout = 8LL * MSEC_PER_SEC * xfer->len; + do_div(timeout, xfer->speed_hz); + + /* Add 10us delay between each fifo bursts */ + timeout += ((xfer->len >> 4) * 10) / MSEC_PER_SEC; + + /* Increase it twice and add 200 ms tolerance */ + timeout += timeout + 200; + /* Start burst */ writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG); /* Enable interrupts */ writel_relaxed(SPICC_TC_EN, spicc->base + SPICC_INTREG); - return 1; + if (!wait_for_completion_timeout(&spicc->done, msecs_to_jiffies(timeout))) + return -ETIMEDOUT; + + return 0; } static int meson_spicc_prepare_message(struct spi_master *master, @@ -743,6 +761,8 @@ static int meson_spicc_probe(struct platform_device *pdev) spicc->pdev = pdev; platform_set_drvdata(pdev, spicc); + init_completion(&spicc->done); + spicc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spicc->base)) { dev_err(&pdev->dev, "io resource mapping failed\n"); -- cgit v1.2.3 From f78961f8380b940e0cfc7e549336c21a2ad44f4d Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Tue, 25 Oct 2022 15:10:14 -0700 Subject: usb: dwc3: gadget: Stop processing more requests on IMI When servicing a transfer completion event, the dwc3 driver will reclaim TRBs of started requests up to the request associated with the interrupt event. Currently we don't check for interrupt due to missed isoc, and the driver may attempt to reclaim TRBs beyond the associated event. This causes invalid memory access when the hardware still owns the TRB. If there's a missed isoc TRB with IMI (interrupt on missed isoc), make sure to stop servicing further. Note that only the last TRB of chained TRBs has its status updated with missed isoc. Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable@vger.kernel.org Reported-by: Jeff Vanhoof Reported-by: Dan Vacura Signed-off-by: Thinh Nguyen Reviewed-by: Jeff Vanhoof Tested-by: Jeff Vanhoof Link: https://lore.kernel.org/r/b29acbeab531b666095dfdafd8cb5c7654fbb3e1.1666735451.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index dd8ecbe61bec..230b3c660054 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3248,6 +3248,10 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, if (event->status & DEPEVT_STATUS_SHORT && !chain) return 1; + if ((trb->ctrl & DWC3_TRB_CTRL_ISP_IMI) && + DWC3_TRB_SIZE_TRBSTS(trb->size) == DWC3_TRBSTS_MISSED_ISOC) + return 1; + if ((trb->ctrl & DWC3_TRB_CTRL_IOC) || (trb->ctrl & DWC3_TRB_CTRL_LST)) return 1; -- cgit v1.2.3 From 308c316d16cbad99bb834767382baa693ac42169 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Tue, 25 Oct 2022 15:10:20 -0700 Subject: usb: dwc3: gadget: Don't set IMI for no_interrupt The gadget driver may have a certain expectation of how the request completion flow should be from to its configuration. Make sure the controller driver respect that. That is, don't set IMI (Interrupt on Missed Isoc) when usb_request->no_interrupt is set. Also, the driver should only set IMI to the last TRB of a chain. Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable@vger.kernel.org Signed-off-by: Thinh Nguyen Reviewed-by: Jeff Vanhoof Tested-by: Jeff Vanhoof Link: https://lore.kernel.org/r/ced336c84434571340c07994e3667a0ee284fefe.1666735451.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 230b3c660054..5fe2d136dff5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1292,8 +1292,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS; } - /* always enable Interrupt on Missed ISOC */ - trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; + if (!no_interrupt && !chain) + trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; break; case USB_ENDPOINT_XFER_BULK: -- cgit v1.2.3 From d61e1d1d5225a9baeb995bcbdb904f66f70ed87e Mon Sep 17 00:00:00 2001 From: Prike Liang Date: Fri, 21 Oct 2022 10:04:40 +0800 Subject: drm/amdgpu: disallow gfxoff until GC IP blocks complete s2idle resume In the S2idle suspend/resume phase the gfxoff is keeping functional so some IP blocks will be likely to reinitialize at gfxoff entry and that will result in failing to program GC registers.Therefore, let disallow gfxoff until AMDGPU IPs reinitialized completely. Signed-off-by: Prike Liang Acked-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 5.15.x --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5b8362727226..ddaecb2610c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3210,6 +3210,15 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev) return r; } adev->ip_blocks[i].status.hw = true; + + if (adev->in_s0ix && adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) { + /* disable gfxoff for IP resume. The gfxoff will be re-enabled in + * amdgpu_device_resume() after IP resume. + */ + amdgpu_gfx_off_ctrl(adev, false); + DRM_DEBUG("will disable gfxoff for re-initializing other blocks\n"); + } + } return 0; @@ -4185,6 +4194,13 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) /* Make sure IB tests flushed */ flush_delayed_work(&adev->delayed_init_work); + if (adev->in_s0ix) { + /* re-enable gfxoff after IP resume. This re-enables gfxoff after + * it was disabled for IP resume in amdgpu_device_ip_resume_phase2(). + */ + amdgpu_gfx_off_ctrl(adev, true); + DRM_DEBUG("will enable gfxoff for the mission mode\n"); + } if (fbcon) drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false); -- cgit v1.2.3 From 0a8b43b12dd78daa77a7dc007b92770d262a2714 Mon Sep 17 00:00:00 2001 From: Juergen Borleis Date: Mon, 24 Oct 2022 10:05:52 +0200 Subject: net: fec: limit register access on i.MX6UL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using 'ethtool -d […]' on an i.MX6UL leads to a kernel crash: Unhandled fault: external abort on non-linefetch (0x1008) at […] due to this SoC has less registers in its FEC implementation compared to other i.MX6 variants. Thus, a run-time decision is required to avoid access to non-existing registers. Fixes: a51d3ab50702 ("net: fec: use a more proper compatible string for i.MX6UL type device") Signed-off-by: Juergen Borleis Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20221024080552.21004-1-jbe@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_main.c | 46 +++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 98d5cd313fdd..28ef4d3c1878 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2432,6 +2432,31 @@ static u32 fec_enet_register_offset[] = { IEEE_R_DROP, IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN, IEEE_R_MACERR, IEEE_R_FDXFC, IEEE_R_OCTETS_OK }; +/* for i.MX6ul */ +static u32 fec_enet_register_offset_6ul[] = { + FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0, + FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL, + FEC_X_CNTRL, FEC_ADDR_LOW, FEC_ADDR_HIGH, FEC_OPD, FEC_TXIC0, FEC_RXIC0, + FEC_HASH_TABLE_HIGH, FEC_HASH_TABLE_LOW, FEC_GRP_HASH_TABLE_HIGH, + FEC_GRP_HASH_TABLE_LOW, FEC_X_WMRK, FEC_R_DES_START_0, + FEC_X_DES_START_0, FEC_R_BUFF_SIZE_0, FEC_R_FIFO_RSFL, FEC_R_FIFO_RSEM, + FEC_R_FIFO_RAEM, FEC_R_FIFO_RAFL, FEC_RACC, + RMON_T_DROP, RMON_T_PACKETS, RMON_T_BC_PKT, RMON_T_MC_PKT, + RMON_T_CRC_ALIGN, RMON_T_UNDERSIZE, RMON_T_OVERSIZE, RMON_T_FRAG, + RMON_T_JAB, RMON_T_COL, RMON_T_P64, RMON_T_P65TO127, RMON_T_P128TO255, + RMON_T_P256TO511, RMON_T_P512TO1023, RMON_T_P1024TO2047, + RMON_T_P_GTE2048, RMON_T_OCTETS, + IEEE_T_DROP, IEEE_T_FRAME_OK, IEEE_T_1COL, IEEE_T_MCOL, IEEE_T_DEF, + IEEE_T_LCOL, IEEE_T_EXCOL, IEEE_T_MACERR, IEEE_T_CSERR, IEEE_T_SQE, + IEEE_T_FDXFC, IEEE_T_OCTETS_OK, + RMON_R_PACKETS, RMON_R_BC_PKT, RMON_R_MC_PKT, RMON_R_CRC_ALIGN, + RMON_R_UNDERSIZE, RMON_R_OVERSIZE, RMON_R_FRAG, RMON_R_JAB, + RMON_R_RESVD_O, RMON_R_P64, RMON_R_P65TO127, RMON_R_P128TO255, + RMON_R_P256TO511, RMON_R_P512TO1023, RMON_R_P1024TO2047, + RMON_R_P_GTE2048, RMON_R_OCTETS, + IEEE_R_DROP, IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN, IEEE_R_MACERR, + IEEE_R_FDXFC, IEEE_R_OCTETS_OK +}; #else static __u32 fec_enet_register_version = 1; static u32 fec_enet_register_offset[] = { @@ -2456,7 +2481,24 @@ static void fec_enet_get_regs(struct net_device *ndev, u32 *buf = (u32 *)regbuf; u32 i, off; int ret; +#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ + defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST) + u32 *reg_list; + u32 reg_cnt; + if (!of_machine_is_compatible("fsl,imx6ul")) { + reg_list = fec_enet_register_offset; + reg_cnt = ARRAY_SIZE(fec_enet_register_offset); + } else { + reg_list = fec_enet_register_offset_6ul; + reg_cnt = ARRAY_SIZE(fec_enet_register_offset_6ul); + } +#else + /* coldfire */ + static u32 *reg_list = fec_enet_register_offset; + static const u32 reg_cnt = ARRAY_SIZE(fec_enet_register_offset); +#endif ret = pm_runtime_resume_and_get(dev); if (ret < 0) return; @@ -2465,8 +2507,8 @@ static void fec_enet_get_regs(struct net_device *ndev, memset(buf, 0, regs->len); - for (i = 0; i < ARRAY_SIZE(fec_enet_register_offset); i++) { - off = fec_enet_register_offset[i]; + for (i = 0; i < reg_cnt; i++) { + off = reg_list[i]; if ((off == FEC_R_BOUND || off == FEC_R_FSTART) && !(fep->quirks & FEC_QUIRK_HAS_FRREG)) -- cgit v1.2.3 From e2badb4bd33abe13ddc35975bd7f7f8693955a4b Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Mon, 24 Oct 2022 16:22:27 +0900 Subject: net: ethernet: ave: Fix MAC to be in charge of PHY PM The phylib callback is called after MAC driver's own resume callback is called. For AVE driver, after resuming immediately, PHY state machine is in PHY_NOLINK because there is a time lag from link-down to link-up due to autoneg. The result is WARN_ON() dump in mdio_bus_phy_resume(). Since ave_resume() itself calls phy_resume(), AVE driver should manage PHY PM. To indicate that MAC driver manages PHY PM, set phydev->mac_managed_pm to true to avoid the unnecessary phylib call and add missing phy_init_hw() to ave_resume(). Suggested-by: Heiner Kallweit Fixes: fba863b81604 ("net: phy: make PHY PM ops a no-op if MAC driver manages PHY PM") Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/20221024072227.24769-1-hayashi.kunihiko@socionext.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/socionext/sni_ave.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index 1fa09b49ba7f..d2c6a5dfdc0e 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c @@ -1229,6 +1229,8 @@ static int ave_init(struct net_device *ndev) phy_support_asym_pause(phydev); + phydev->mac_managed_pm = true; + phy_attached_info(phydev); return 0; @@ -1756,6 +1758,10 @@ static int ave_resume(struct device *dev) ave_global_reset(ndev); + ret = phy_init_hw(ndev->phydev); + if (ret) + return ret; + ave_ethtool_get_wol(ndev, &wol); wol.wolopts = priv->wolopts; __ave_ethtool_set_wol(ndev, &wol); -- cgit v1.2.3 From 2871edb32f4622c3a25ce4b3977bad9050b91974 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Mon, 10 Oct 2022 20:52:27 +0200 Subject: can: kvaser_usb: Fix possible completions during init_completion kvaser_usb uses completions to signal when a response event is received for outgoing commands. However, it uses init_completion() to reinitialize the start_comp and stop_comp completions before sending the start/stop commands. In case the device sends the corresponding response just before the actual command is sent, complete() may be called concurrently with init_completion() which is not safe. This might be triggerable even with a properly functioning device by stopping the interface (CMD_STOP_CHIP) just after it goes bus-off (which also causes the driver to send CMD_STOP_CHIP when restart-ms is off), but that was not tested. Fix the issue by using reinit_completion() instead. Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") Tested-by: Jimmy Assarsson Signed-off-by: Anssi Hannula Signed-off-by: Jimmy Assarsson Link: https://lore.kernel.org/all/20221010185237.319219-2-extja@kvaser.com Cc: stable@vger.kernel.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 4 ++-- drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index 7b52fda73d82..66f672ea631b 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -1875,7 +1875,7 @@ static int kvaser_usb_hydra_start_chip(struct kvaser_usb_net_priv *priv) { int err; - init_completion(&priv->start_comp); + reinit_completion(&priv->start_comp); err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_START_CHIP_REQ, priv->channel); @@ -1893,7 +1893,7 @@ static int kvaser_usb_hydra_stop_chip(struct kvaser_usb_net_priv *priv) { int err; - init_completion(&priv->stop_comp); + reinit_completion(&priv->stop_comp); /* Make sure we do not report invalid BUS_OFF from CMD_CHIP_STATE_EVENT * see comment in kvaser_usb_hydra_update_state() diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index 50f2ac8319ff..19958037720f 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -1320,7 +1320,7 @@ static int kvaser_usb_leaf_start_chip(struct kvaser_usb_net_priv *priv) { int err; - init_completion(&priv->start_comp); + reinit_completion(&priv->start_comp); err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_START_CHIP, priv->channel); @@ -1338,7 +1338,7 @@ static int kvaser_usb_leaf_stop_chip(struct kvaser_usb_net_priv *priv) { int err; - init_completion(&priv->stop_comp); + reinit_completion(&priv->stop_comp); err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_STOP_CHIP, priv->channel); -- cgit v1.2.3 From a0c9f1f2e53b8eb2ae43987a30e547ba56b4fa18 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 27 Oct 2022 09:12:05 +0200 Subject: parisc: Export iosapic_serial_irq() symbol for serial port driver The parisc serial port driver needs this symbol when it's compiled as module. Signed-off-by: Helge Deller Reported-by: kernel test robot Cc: --- drivers/parisc/iosapic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index bdef7a8d6ab8..bcc1dae00780 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -866,6 +866,7 @@ int iosapic_serial_irq(struct parisc_device *dev) return vi->txn_irq; } +EXPORT_SYMBOL(iosapic_serial_irq); #endif -- cgit v1.2.3 From e0ba1a39b8dfe4f005bebdd85daa89e7382e26b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Thu, 27 Oct 2022 02:06:16 +0200 Subject: fbdev/core: Avoid uninitialized read in aperture_remove_conflicting_pci_device() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return on error directly from the BAR-iterating loop instead of break+return. This is actually a cosmetic fix, since it would be highly unusual to have this called for a PCI device without any memory BARs. Fixes: 9d69ef183815 ("fbdev/core: Remove remove_conflicting_pci_framebuffers()") Signed-off-by: Michał Mirosław Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/e75323732bedc46d613d72ecb40f97e3bc75eea8.1666829073.git.mirq-linux@rere.qmqm.pl --- drivers/video/aperture.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c index 9e6bcc03a1a4..41e77de1ea82 100644 --- a/drivers/video/aperture.c +++ b/drivers/video/aperture.c @@ -340,12 +340,9 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na size = pci_resource_len(pdev, bar); ret = aperture_remove_conflicting_devices(base, size, primary, name); if (ret) - break; + return ret; } - if (ret) - return ret; - /* * WARNING: Apparently we must kick fbdev drivers before vgacon, * otherwise the vga fbdev driver falls over. -- cgit v1.2.3 From 702de2c21eed04c67cefaaedc248ef16e5f6b293 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 25 Oct 2022 16:56:55 +0100 Subject: can: rcar_canfd: rcar_canfd_handle_global_receive(): fix IRQ storm on global FIFO receive We are seeing an IRQ storm on the global receive IRQ line under heavy CAN bus load conditions with both CAN channels enabled. Conditions: The global receive IRQ line is shared between can0 and can1, either of the channels can trigger interrupt while the other channel's IRQ line is disabled (RFIE). When global a receive IRQ interrupt occurs, we mask the interrupt in the IRQ handler. Clearing and unmasking of the interrupt is happening in rx_poll(). There is a race condition where rx_poll() unmasks the interrupt, but the next IRQ handler does not mask the IRQ due to NAPIF_STATE_MISSED flag (e.g.: can0 RX FIFO interrupt is disabled and can1 is triggering RX interrupt, the delay in rx_poll() processing results in setting NAPIF_STATE_MISSED flag) leading to an IRQ storm. This patch fixes the issue by checking IRQ active and enabled before handling the IRQ on a particular channel. Fixes: dd3bd23eb438 ("can: rcar_canfd: Add Renesas R-Car CAN FD driver") Suggested-by: Marc Kleine-Budde Signed-off-by: Biju Das Link: https://lore.kernel.org/all/20221025155657.1426948-2-biju.das.jz@bp.renesas.com Cc: stable@vger.kernel.org [mkl: adjust commit message] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/rcar/rcar_canfd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index 567620d215f8..ea828c1bd3a1 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -1157,11 +1157,13 @@ static void rcar_canfd_handle_global_receive(struct rcar_canfd_global *gpriv, u3 { struct rcar_canfd_channel *priv = gpriv->ch[ch]; u32 ridx = ch + RCANFD_RFFIFO_IDX; - u32 sts; + u32 sts, cc; /* Handle Rx interrupts */ sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(gpriv, ridx)); - if (likely(sts & RCANFD_RFSTS_RFIF)) { + cc = rcar_canfd_read(priv->base, RCANFD_RFCC(gpriv, ridx)); + if (likely(sts & RCANFD_RFSTS_RFIF && + cc & RCANFD_RFCC_RFIE)) { if (napi_schedule_prep(&priv->napi)) { /* Disable Rx FIFO interrupts */ rcar_canfd_clear_bit(priv->base, -- cgit v1.2.3 From d887087c896881715c1a82f1d4f71fbfe5344ffd Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 25 Oct 2022 16:56:56 +0100 Subject: can: rcar_canfd: fix channel specific IRQ handling for RZ/G2L RZ/G2L has separate channel specific IRQs for transmit and error interrupts. But the IRQ handler processes both channels, even if there no interrupt occurred on one of the channels. This patch fixes the issue by passing a channel specific context parameter instead of global one for the IRQ register and the IRQ handler, it just handles the channel which is triggered the interrupt. Fixes: 76e9353a80e9 ("can: rcar_canfd: Add support for RZ/G2L family") Signed-off-by: Biju Das Link: https://lore.kernel.org/all/20221025155657.1426948-3-biju.das.jz@bp.renesas.com Cc: stable@vger.kernel.org [mkl: adjust commit message] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/rcar/rcar_canfd.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index ea828c1bd3a1..198da643ee6d 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -1246,11 +1246,9 @@ static void rcar_canfd_handle_channel_tx(struct rcar_canfd_global *gpriv, u32 ch static irqreturn_t rcar_canfd_channel_tx_interrupt(int irq, void *dev_id) { - struct rcar_canfd_global *gpriv = dev_id; - u32 ch; + struct rcar_canfd_channel *priv = dev_id; - for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) - rcar_canfd_handle_channel_tx(gpriv, ch); + rcar_canfd_handle_channel_tx(priv->gpriv, priv->channel); return IRQ_HANDLED; } @@ -1278,11 +1276,9 @@ static void rcar_canfd_handle_channel_err(struct rcar_canfd_global *gpriv, u32 c static irqreturn_t rcar_canfd_channel_err_interrupt(int irq, void *dev_id) { - struct rcar_canfd_global *gpriv = dev_id; - u32 ch; + struct rcar_canfd_channel *priv = dev_id; - for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) - rcar_canfd_handle_channel_err(gpriv, ch); + rcar_canfd_handle_channel_err(priv->gpriv, priv->channel); return IRQ_HANDLED; } @@ -1723,6 +1719,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, priv->ndev = ndev; priv->base = gpriv->base; priv->channel = ch; + priv->gpriv = gpriv; priv->can.clock.freq = fcan_freq; dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq); @@ -1751,7 +1748,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, } err = devm_request_irq(&pdev->dev, err_irq, rcar_canfd_channel_err_interrupt, 0, - irq_name, gpriv); + irq_name, priv); if (err) { dev_err(&pdev->dev, "devm_request_irq CH Err(%d) failed, error %d\n", err_irq, err); @@ -1765,7 +1762,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, } err = devm_request_irq(&pdev->dev, tx_irq, rcar_canfd_channel_tx_interrupt, 0, - irq_name, gpriv); + irq_name, priv); if (err) { dev_err(&pdev->dev, "devm_request_irq Tx (%d) failed, error %d\n", tx_irq, err); @@ -1791,7 +1788,6 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, priv->can.do_set_mode = rcar_canfd_do_set_mode; priv->can.do_get_berr_counter = rcar_canfd_get_berr_counter; - priv->gpriv = gpriv; SET_NETDEV_DEV(ndev, &pdev->dev); netif_napi_add_weight(ndev, &priv->napi, rcar_canfd_rx_poll, -- cgit v1.2.3 From 0e7ce23a917a9cc83ca3c779fbba836bca3bcf1e Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 25 Oct 2022 21:00:11 +0800 Subject: net: ehea: fix possible memory leak in ehea_register_port() If of_device_register() returns error, the of node and the name allocated in dev_set_name() is leaked, call put_device() to give up the reference that was set in device_initialize(), so that of node is put in logical_port_release() and the name is freed in kobject_cleanup(). Fixes: 1acf2318dd13 ("ehea: dynamic add / remove port") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221025130011.1071357-1-yangyingliang@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/ibm/ehea/ehea_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 294bdbbeacc3..b4aff59b3eb4 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -2900,6 +2900,7 @@ static struct device *ehea_register_port(struct ehea_port *port, ret = of_device_register(&port->ofdev); if (ret) { pr_err("failed to register device. ret=%d\n", ret); + put_device(&port->ofdev.dev); goto out; } -- cgit v1.2.3 From 99632e3dbeb25a0ff86c4af4bba2dcf638624423 Mon Sep 17 00:00:00 2001 From: Jilin Yuan Date: Wed, 19 Oct 2022 20:56:04 +0800 Subject: Drivers: hv: fix repeated words in comments Delete the redundant word 'of'. Signed-off-by: Jilin Yuan Reviewed-by: Michael Kelley Link: https://lore.kernel.org/r/20221019125604.52999-1-yuanjilin@cdjrlc.com Signed-off-by: Wei Liu --- drivers/hv/hv_balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index fdf6decacf06..6c127f061f06 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -905,7 +905,7 @@ static unsigned long handle_pg_range(unsigned long pg_start, * We have some residual hot add range * that needs to be hot added; hot add * it now. Hot add a multiple of - * of HA_CHUNK that fully covers the pages + * HA_CHUNK that fully covers the pages * we have. */ size = (has->end_pfn - has->ha_end_pfn); -- cgit v1.2.3 From 7f21735ffb2648a29e0fc79c4bdcb1b9ed8602cd Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 27 Oct 2022 17:19:18 +0800 Subject: rbd: fix possible memory leak in rbd_sysfs_init() If device_register() returns error in rbd_sysfs_init(), name of kobject which is allocated in dev_set_name() called in device_add() is leaked. As comment of device_add() says, it should call put_device() to drop the reference count that was set in device_initialize() when it fails, so the name can be freed in kobject_cleanup(). Fault injection test can trigger this problem: unreferenced object 0xffff88810173aa78 (size 8): comm "modprobe", pid 247, jiffies 4294714278 (age 31.789s) hex dump (first 8 bytes): 72 62 64 00 81 88 ff ff rbd..... backtrace: [<00000000f58fae56>] __kmalloc_node_track_caller+0x44/0x1b0 [<00000000bdd44fe7>] kstrdup+0x3a/0x70 [<00000000f7844d0b>] kstrdup_const+0x63/0x80 [<000000001b0a0eeb>] kvasprintf_const+0x10b/0x190 [<00000000a47bd894>] kobject_set_name_vargs+0x56/0x150 [<00000000d5edbf18>] dev_set_name+0xab/0xe0 [<00000000f5153e80>] device_add+0x106/0x1f20 Fixes: dfc5606dc513 ("rbd: replace the rbd sysfs interface") Signed-off-by: Yang Yingliang Reviewed-by: Alex Elder Link: https://lore.kernel.org/r/20221027091918.2294132-1-yangyingliang@huawei.com Signed-off-by: Jens Axboe --- drivers/block/rbd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index f9e39301c4af..04453f4a319c 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -7222,8 +7222,10 @@ static int __init rbd_sysfs_init(void) int ret; ret = device_register(&rbd_root_dev); - if (ret < 0) + if (ret < 0) { + put_device(&rbd_root_dev); return ret; + } ret = bus_register(&rbd_bus_type); if (ret < 0) -- cgit v1.2.3 From 9f172134dde7e4f5bf4b9139f23a1e741ec1c36e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 25 Oct 2022 16:42:01 -0700 Subject: net: bcmsysport: Indicate MAC is in charge of PHY PM Avoid the PHY library call unnecessarily into the suspend/resume functions by setting phydev->mac_managed_pm to true. The SYSTEMPORT driver essentially does exactly what mdio_bus_phy_resume() does by calling phy_resume(). Fixes: fba863b81604 ("net: phy: make PHY PM ops a no-op if MAC driver manages PHY PM") Signed-off-by: Florian Fainelli Link: https://lore.kernel.org/r/20221025234201.2549360-1-f.fainelli@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/broadcom/bcmsysport.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 867f14c30e09..425d6ccd5413 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1991,6 +1991,9 @@ static int bcm_sysport_open(struct net_device *dev) goto out_clk_disable; } + /* Indicate that the MAC is responsible for PHY PM */ + phydev->mac_managed_pm = true; + /* Reset house keeping link status */ priv->old_duplex = -1; priv->old_link = -1; -- cgit v1.2.3 From df3414b0a245f43476061fddd78cee7d6cff797f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Monin?= Date: Thu, 13 Oct 2022 16:26:48 +0200 Subject: USB: serial: option: add Sierra Wireless EM9191 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the AT and diag ports, similar to other qualcomm SDX55 modems. In QDL mode, the modem uses a different device ID and support is provided by qcserial in commit 11c52d250b34 ("USB: serial: qcserial: add EM9191 QDL support"). T: Bus=08 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=5000 MxCh= 0 D: Ver= 3.20 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 P: Vendor=1199 ProdID=90d3 Rev=00.06 S: Manufacturer=Sierra Wireless, Incorporated S: Product=Sierra Wireless EM9191 S: SerialNumber=xxxxxxxxxxxxxxxx C: #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=896mA I: If#=0x0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim I: If#=0x1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I: If#=0x3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) I: If#=0x4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=(none) Signed-off-by: Benoît Monin Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 697683e3fbff..37257a52287d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -581,6 +581,9 @@ static void option_instat_callback(struct urb *urb); #define OPPO_VENDOR_ID 0x22d9 #define OPPO_PRODUCT_R11 0x276c +/* Sierra Wireless products */ +#define SIERRA_VENDOR_ID 0x1199 +#define SIERRA_PRODUCT_EM9191 0x90d3 /* Device flags */ @@ -2176,6 +2179,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */ { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From ef3556ee16c68735ec69bd08df41d1cd83b14ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 27 Oct 2022 13:24:30 +0200 Subject: net: broadcom: bcm4908_enet: update TX stats after actual transmission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Queueing packets doesn't guarantee their transmission. Update TX stats after hardware confirms consuming submitted data. This also fixes a possible race and NULL dereference. bcm4908_enet_start_xmit() could try to access skb after freeing it in the bcm4908_enet_poll_tx(). Reported-by: Florian Fainelli Fixes: 4feffeadbcb2e ("net: broadcom: bcm4908enet: add BCM4908 controller driver") Signed-off-by: Rafał Miłecki Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20221027112430.8696-1-zajec5@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bcm4908_enet.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c index 93ccf549e2ed..a737b1913cf9 100644 --- a/drivers/net/ethernet/broadcom/bcm4908_enet.c +++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c @@ -561,8 +561,6 @@ static netdev_tx_t bcm4908_enet_start_xmit(struct sk_buff *skb, struct net_devic if (++ring->write_idx == ring->length - 1) ring->write_idx = 0; - enet->netdev->stats.tx_bytes += skb->len; - enet->netdev->stats.tx_packets++; return NETDEV_TX_OK; } @@ -635,6 +633,7 @@ static int bcm4908_enet_poll_tx(struct napi_struct *napi, int weight) struct bcm4908_enet_dma_ring_bd *buf_desc; struct bcm4908_enet_dma_ring_slot *slot; struct device *dev = enet->dev; + unsigned int bytes = 0; int handled = 0; while (handled < weight && tx_ring->read_idx != tx_ring->write_idx) { @@ -645,12 +644,17 @@ static int bcm4908_enet_poll_tx(struct napi_struct *napi, int weight) dma_unmap_single(dev, slot->dma_addr, slot->len, DMA_TO_DEVICE); dev_kfree_skb(slot->skb); - if (++tx_ring->read_idx == tx_ring->length) - tx_ring->read_idx = 0; handled++; + bytes += slot->len; + + if (++tx_ring->read_idx == tx_ring->length) + tx_ring->read_idx = 0; } + enet->netdev->stats.tx_packets += handled; + enet->netdev->stats.tx_bytes += bytes; + if (handled < weight) { napi_complete_done(napi, handled); bcm4908_enet_dma_ring_intrs_on(enet, tx_ring); -- cgit v1.2.3 From cf2010aa1c739bab067cbc90b690d28eaa0b47da Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 26 Oct 2022 09:54:05 +0800 Subject: netdevsim: fix memory leak in nsim_bus_dev_new() If device_register() failed in nsim_bus_dev_new(), the value of reference in nsim_bus_dev->dev is 1. obj->name in nsim_bus_dev->dev will not be released. unreferenced object 0xffff88810352c480 (size 16): comm "echo", pid 5691, jiffies 4294945921 (age 133.270s) hex dump (first 16 bytes): 6e 65 74 64 65 76 73 69 6d 31 00 00 00 00 00 00 netdevsim1...... backtrace: [<000000005e2e5e26>] __kmalloc_node_track_caller+0x3a/0xb0 [<0000000094ca4fc8>] kvasprintf+0xc3/0x160 [<00000000aad09bcc>] kvasprintf_const+0x55/0x180 [<000000009bac868d>] kobject_set_name_vargs+0x56/0x150 [<000000007c1a5d70>] dev_set_name+0xbb/0xf0 [<00000000ad0d126b>] device_add+0x1f8/0x1cb0 [<00000000c222ae24>] new_device_store+0x3b6/0x5e0 [<0000000043593421>] bus_attr_store+0x72/0xa0 [<00000000cbb1833a>] sysfs_kf_write+0x106/0x160 [<00000000d0dedb8a>] kernfs_fop_write_iter+0x3a8/0x5a0 [<00000000770b66e2>] vfs_write+0x8f0/0xc80 [<0000000078bb39be>] ksys_write+0x106/0x210 [<00000000005e55a4>] do_syscall_64+0x35/0x80 [<00000000eaa40bbc>] entry_SYSCALL_64_after_hwframe+0x46/0xb0 Fixes: 40e4fe4ce115 ("netdevsim: move device registration and related code to bus.c") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221026015405.128795-1-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/netdevsim/bus.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index b5f4df1a07a3..0052968e881e 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -117,6 +117,10 @@ static const struct attribute_group *nsim_bus_dev_attr_groups[] = { static void nsim_bus_dev_release(struct device *dev) { + struct nsim_bus_dev *nsim_bus_dev; + + nsim_bus_dev = container_of(dev, struct nsim_bus_dev, dev); + kfree(nsim_bus_dev); } static struct device_type nsim_bus_dev_type = { @@ -291,6 +295,8 @@ nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queu err_nsim_bus_dev_id_free: ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); + put_device(&nsim_bus_dev->dev); + nsim_bus_dev = NULL; err_nsim_bus_dev_free: kfree(nsim_bus_dev); return ERR_PTR(err); @@ -300,9 +306,8 @@ static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) { /* Disallow using nsim_bus_dev */ smp_store_release(&nsim_bus_dev->init, false); - device_unregister(&nsim_bus_dev->dev); ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); - kfree(nsim_bus_dev); + device_unregister(&nsim_bus_dev->dev); } static struct device_driver nsim_driver = { -- cgit v1.2.3 From 6b1da9f7126f05e857da6db24c6a04aa7974d644 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 26 Oct 2022 09:46:41 +0800 Subject: netdevsim: fix memory leak in nsim_drv_probe() when nsim_dev_resources_register() failed If some items in nsim_dev_resources_register() fail, memory leak will occur. The following is the memory leak information. unreferenced object 0xffff888074c02600 (size 128): comm "echo", pid 8159, jiffies 4294945184 (age 493.530s) hex dump (first 32 bytes): 40 47 ea 89 ff ff ff ff 01 00 00 00 00 00 00 00 @G.............. ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ backtrace: [<0000000011a31c98>] kmalloc_trace+0x22/0x60 [<0000000027384c69>] devl_resource_register+0x144/0x4e0 [<00000000a16db248>] nsim_drv_probe+0x37a/0x1260 [<000000007d1f448c>] really_probe+0x20b/0xb10 [<00000000c416848a>] __driver_probe_device+0x1b3/0x4a0 [<00000000077e0351>] driver_probe_device+0x49/0x140 [<0000000054f2465a>] __device_attach_driver+0x18c/0x2a0 [<000000008538f359>] bus_for_each_drv+0x151/0x1d0 [<0000000038e09747>] __device_attach+0x1c9/0x4e0 [<00000000dd86e533>] bus_probe_device+0x1d5/0x280 [<00000000839bea35>] device_add+0xae0/0x1cb0 [<000000009c2abf46>] new_device_store+0x3b6/0x5f0 [<00000000fb823d7f>] bus_attr_store+0x72/0xa0 [<000000007acc4295>] sysfs_kf_write+0x106/0x160 [<000000005f50cb4d>] kernfs_fop_write_iter+0x3a8/0x5a0 [<0000000075eb41bf>] vfs_write+0x8f0/0xc80 Fixes: 37923ed6b8ce ("netdevsim: Add simple FIB resource controller via devlink") Signed-off-by: Zhengchao Shao Signed-off-by: Jakub Kicinski --- drivers/net/netdevsim/dev.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 794fc0cc73b8..81c3e14af063 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -442,7 +442,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) ¶ms); if (err) { pr_err("Failed to register IPv4 top resource\n"); - goto out; + goto err_out; } err = devl_resource_register(devlink, "fib", (u64)-1, @@ -450,7 +450,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) NSIM_RESOURCE_IPV4, ¶ms); if (err) { pr_err("Failed to register IPv4 FIB resource\n"); - return err; + goto err_out; } err = devl_resource_register(devlink, "fib-rules", (u64)-1, @@ -458,7 +458,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) NSIM_RESOURCE_IPV4, ¶ms); if (err) { pr_err("Failed to register IPv4 FIB rules resource\n"); - return err; + goto err_out; } /* Resources for IPv6 */ @@ -468,7 +468,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) ¶ms); if (err) { pr_err("Failed to register IPv6 top resource\n"); - goto out; + goto err_out; } err = devl_resource_register(devlink, "fib", (u64)-1, @@ -476,7 +476,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) NSIM_RESOURCE_IPV6, ¶ms); if (err) { pr_err("Failed to register IPv6 FIB resource\n"); - return err; + goto err_out; } err = devl_resource_register(devlink, "fib-rules", (u64)-1, @@ -484,7 +484,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) NSIM_RESOURCE_IPV6, ¶ms); if (err) { pr_err("Failed to register IPv6 FIB rules resource\n"); - return err; + goto err_out; } /* Resources for nexthops */ @@ -492,8 +492,14 @@ static int nsim_dev_resources_register(struct devlink *devlink) NSIM_RESOURCE_NEXTHOPS, DEVLINK_RESOURCE_ID_PARENT_TOP, ¶ms); + if (err) { + pr_err("Failed to register NEXTHOPS resource\n"); + goto err_out; + } + return 0; -out: +err_out: + devl_resources_unregister(devlink); return err; } -- cgit v1.2.3 From a6aa8d0ce2cfba57ac0f23293fcb3be0b9f53fba Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 26 Oct 2022 09:46:42 +0800 Subject: netdevsim: remove dir in nsim_dev_debugfs_init() when creating ports dir failed Remove dir in nsim_dev_debugfs_init() when creating ports dir failed. Otherwise, the netdevsim device will not be created next time. Kernel reports an error: debugfs: Directory 'netdevsim1' with parent 'netdevsim' already present! Fixes: ab1d0cc004d7 ("netdevsim: change debugfs tree topology") Signed-off-by: Zhengchao Shao Signed-off-by: Jakub Kicinski --- drivers/net/netdevsim/dev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 81c3e14af063..a7880c7ce94c 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -309,8 +309,10 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) if (IS_ERR(nsim_dev->ddir)) return PTR_ERR(nsim_dev->ddir); nsim_dev->ports_ddir = debugfs_create_dir("ports", nsim_dev->ddir); - if (IS_ERR(nsim_dev->ports_ddir)) - return PTR_ERR(nsim_dev->ports_ddir); + if (IS_ERR(nsim_dev->ports_ddir)) { + err = PTR_ERR(nsim_dev->ports_ddir); + goto err_ddir; + } debugfs_create_bool("fw_update_status", 0600, nsim_dev->ddir, &nsim_dev->fw_update_status); debugfs_create_u32("fw_update_overwrite_mask", 0600, nsim_dev->ddir, @@ -346,7 +348,7 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) nsim_dev->nodes_ddir = debugfs_create_dir("rate_nodes", nsim_dev->ddir); if (IS_ERR(nsim_dev->nodes_ddir)) { err = PTR_ERR(nsim_dev->nodes_ddir); - goto err_out; + goto err_ports_ddir; } debugfs_create_bool("fail_trap_drop_counter_get", 0600, nsim_dev->ddir, @@ -354,8 +356,9 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) nsim_udp_tunnels_debugfs_create(nsim_dev); return 0; -err_out: +err_ports_ddir: debugfs_remove_recursive(nsim_dev->ports_ddir); +err_ddir: debugfs_remove_recursive(nsim_dev->ddir); return err; } -- cgit v1.2.3 From 888be6b279b7257b5f6e4c9527675bff0a335596 Mon Sep 17 00:00:00 2001 From: Hyong Youb Kim Date: Wed, 26 Oct 2022 14:51:39 +0100 Subject: net/mlx5e: Do not increment ESN when updating IPsec ESN state An offloaded SA stops receiving after about 2^32 + replay_window packets. For example, when SA reaches , all subsequent packets get dropped with SA-icv-failure (integrity_failed). To reproduce the bug: - ConnectX-6 Dx with crypto enabled (FW 22.30.1004) - ipsec.conf: nic-offload = yes replay-window = 32 esn = yes salifetime=24h - Run netperf for a long time to send more than 2^32 packets netperf -H -t TCP_STREAM -l 20000 When 2^32 + replay_window packets are received, the replay window moves from the 2nd half of subspace (overlap=1) to the 1st half (overlap=0). The driver then updates the 'esn' value in NIC (i.e. seq_hi) as follows. seq_hi = xfrm_replay_seqhi(seq_bottom) new esn in NIC = seq_hi + 1 The +1 increment is wrong, as seq_hi already contains the correct seq_hi. For example, when seq_hi=1, the driver actually tells NIC to use seq_hi=2 (esn). This incorrect esn value causes all subsequent packets to fail integrity checks (SA-icv-failure). So, do not increment. Fixes: cb01008390bb ("net/mlx5: IPSec, Add support for ESN") Signed-off-by: Hyong Youb Kim Acked-by: Leon Romanovsky Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-2-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 2a8fd7020622..a715601865d3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -101,7 +101,6 @@ static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry) struct xfrm_replay_state_esn *replay_esn; u32 seq_bottom = 0; u8 overlap; - u32 *esn; if (!(sa_entry->x->props.flags & XFRM_STATE_ESN)) { sa_entry->esn_state.trigger = 0; @@ -116,11 +115,9 @@ static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry) sa_entry->esn_state.esn = xfrm_replay_seqhi(sa_entry->x, htonl(seq_bottom)); - esn = &sa_entry->esn_state.esn; sa_entry->esn_state.trigger = 1; if (unlikely(overlap && seq_bottom < MLX5E_IPSEC_ESN_SCOPE_MID)) { - ++(*esn); sa_entry->esn_state.overlap = 0; return true; } else if (unlikely(!overlap && -- cgit v1.2.3 From 212b4d7251c169f87fa734e79bdec8dd413be5cf Mon Sep 17 00:00:00 2001 From: Moshe Shemesh Date: Wed, 26 Oct 2022 14:51:40 +0100 Subject: net/mlx5: Wait for firmware to enable CRS before pci_restore_state After firmware reset driver should verify firmware already enabled CRS and became responsive to pci config cycles before restoring pci state. Fix that by waiting till device_id is readable through PCI again. Fixes: eabe8e5e88f5 ("net/mlx5: Handle sync reset now event") Signed-off-by: Moshe Shemesh Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-3-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index e8896f368362..07c583996c29 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -358,6 +358,23 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev) err = -ETIMEDOUT; } + do { + err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, ®16); + if (err) + return err; + if (reg16 == dev_id) + break; + msleep(20); + } while (!time_after(jiffies, timeout)); + + if (reg16 == dev_id) { + mlx5_core_info(dev, "Firmware responds to PCI config cycles again\n"); + } else { + mlx5_core_err(dev, "Firmware is not responsive (0x%04x) after %llu ms\n", + reg16, mlx5_tout_ms(dev, PCI_TOGGLE)); + err = -ETIMEDOUT; + } + restore: list_for_each_entry(sdev, &bridge_bus->devices, bus_list) { pci_cfg_access_unlock(sdev); -- cgit v1.2.3 From 4ea9891d66410da5030dababb4b825d8e41cd7bb Mon Sep 17 00:00:00 2001 From: Rongwei Liu Date: Wed, 26 Oct 2022 14:51:41 +0100 Subject: net/mlx5: DR, Fix matcher disconnect error flow When 2nd flow rules arrives, it will merge together with the 1st one if matcher criteria is the same. If merge fails, driver will rollback the merge contents, and reject the 2nd rule. At rollback stage, matcher can't be disconnected unconditionally, otherise the 1st rule can't be hit anymore. Add logic to check if the matcher should be disconnected or not. Fixes: cc2295cd54e4 ("net/mlx5: DR, Improve steering for empty or RX/TX-only matchers") Signed-off-by: Rongwei Liu Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-4-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c index ddfaf7891188..91ff19f67695 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c @@ -1200,7 +1200,8 @@ free_rule: } remove_from_nic_tbl: - mlx5dr_matcher_remove_from_tbl_nic(dmn, nic_matcher); + if (!nic_matcher->rules) + mlx5dr_matcher_remove_from_tbl_nic(dmn, nic_matcher); free_hw_ste: mlx5dr_domain_nic_unlock(nic_dmn); -- cgit v1.2.3 From 19b43a432e3e47db656a8269a74b50aef826950c Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Wed, 26 Oct 2022 14:51:42 +0100 Subject: net/mlx5e: Extend SKB room check to include PTP-SQ When tx_port_ts is set, the driver diverts all UPD traffic over PTP port to a dedicated PTP-SQ. The SKBs are cached until the wire-CQE arrives. When the packet size is greater then MTU, the firmware might drop it and the packet won't be transmitted to the wire, hence the wire-CQE won't reach the driver. In this case the SKBs are accumulated in the SKB fifo. Add room check to consider the PTP-SQ SKB fifo, when the SKB fifo is full, driver stops the queue resulting in a TX timeout. Devlink TX-reporter can recover from it. Fixes: 1880bc4e4a96 ("net/mlx5e: Add TX port timestamp support") Signed-off-by: Aya Levin Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-5-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h | 9 +++++++++ drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h | 6 ++++++ drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 6 ++++++ 3 files changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h index 5bce554e131a..cc7efde88ac3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h @@ -6,6 +6,7 @@ #include "en.h" #include "en_stats.h" +#include "en/txrx.h" #include #define MLX5E_PTP_CHANNEL_IX 0 @@ -68,6 +69,14 @@ static inline bool mlx5e_use_ptpsq(struct sk_buff *skb) fk.ports.dst == htons(PTP_EV_PORT)); } +static inline bool mlx5e_ptpsq_fifo_has_room(struct mlx5e_txqsq *sq) +{ + if (!sq->ptpsq) + return true; + + return mlx5e_skb_fifo_has_room(&sq->ptpsq->skb_fifo); +} + int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params, u8 lag_port, struct mlx5e_ptp **cp); void mlx5e_ptp_close(struct mlx5e_ptp *c); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index 4456ad5cedf1..cb164b62f543 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -57,6 +57,12 @@ netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev); bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget); void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq); +static inline bool +mlx5e_skb_fifo_has_room(struct mlx5e_skb_fifo *fifo) +{ + return (*fifo->pc - *fifo->cc) < fifo->mask; +} + static inline bool mlx5e_wqc_has_room_for(struct mlx5_wq_cyc *wq, u16 cc, u16 pc, u16 n) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index bf2232a2a836..6adca01fbdc9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -392,6 +392,11 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb, if (unlikely(sq->ptpsq)) { mlx5e_skb_cb_hwtstamp_init(skb); mlx5e_skb_fifo_push(&sq->ptpsq->skb_fifo, skb); + if (!netif_tx_queue_stopped(sq->txq) && + !mlx5e_skb_fifo_has_room(&sq->ptpsq->skb_fifo)) { + netif_tx_stop_queue(sq->txq); + sq->stats->stopped++; + } skb_get(skb); } @@ -868,6 +873,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) if (netif_tx_queue_stopped(sq->txq) && mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) && + mlx5e_ptpsq_fifo_has_room(sq) && !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) { netif_tx_wake_queue(sq->txq); stats->wake++; -- cgit v1.2.3 From 8dc47c0527c1586e3ebe0efd323f1d8abb181c77 Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Wed, 26 Oct 2022 14:51:43 +0100 Subject: net/mlx5e: Update restore chain id for slow path packets Currently encap slow path rules just forward to software without setting the chain id miss register, so driver doesn't restore the chain, and packets hitting this rule will restart from tc chain 0 instead of continuing to the chain the encap rule was on. Fix this by setting the chain id miss register to the chain id mapping. Fixes: 8f1e0b97cc70 ("net/mlx5: E-Switch, Mark miss packets with new chain id mapping") Signed-off-by: Paul Blakey Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-6-saeed@kernel.org Signed-off-by: Jakub Kicinski --- .../net/ethernet/mellanox/mlx5/core/en/tc_priv.h | 2 + drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 62 +++++++++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h index 10c9a8a79d00..2e42d7c5451e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h @@ -96,6 +96,7 @@ struct mlx5e_tc_flow { struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS]; struct mlx5e_tc_flow *peer_flow; struct mlx5e_mod_hdr_handle *mh; /* attached mod header instance */ + struct mlx5e_mod_hdr_handle *slow_mh; /* attached mod header instance for slow path */ struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */ struct list_head hairpin; /* flows sharing the same hairpin */ struct list_head peer; /* flows with peer flow */ @@ -111,6 +112,7 @@ struct mlx5e_tc_flow { struct completion del_hw_done; struct mlx5_flow_attr *attr; struct list_head attrs; + u32 chain_mapping; }; struct mlx5_flow_handle * diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 70a7a61f9708..2cceace36c77 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1405,8 +1405,13 @@ mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw, struct mlx5e_tc_flow *flow, struct mlx5_flow_spec *spec) { + struct mlx5e_tc_mod_hdr_acts mod_acts = {}; + struct mlx5e_mod_hdr_handle *mh = NULL; struct mlx5_flow_attr *slow_attr; struct mlx5_flow_handle *rule; + bool fwd_and_modify_cap; + u32 chain_mapping = 0; + int err; slow_attr = mlx5_alloc_flow_attr(MLX5_FLOW_NAMESPACE_FDB); if (!slow_attr) @@ -1417,13 +1422,56 @@ mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw, slow_attr->esw_attr->split_count = 0; slow_attr->flags |= MLX5_ATTR_FLAG_SLOW_PATH; + fwd_and_modify_cap = MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_modify_header_fwd_to_table); + if (!fwd_and_modify_cap) + goto skip_restore; + + err = mlx5_chains_get_chain_mapping(esw_chains(esw), flow->attr->chain, &chain_mapping); + if (err) + goto err_get_chain; + + err = mlx5e_tc_match_to_reg_set(esw->dev, &mod_acts, MLX5_FLOW_NAMESPACE_FDB, + CHAIN_TO_REG, chain_mapping); + if (err) + goto err_reg_set; + + mh = mlx5e_mod_hdr_attach(esw->dev, get_mod_hdr_table(flow->priv, flow), + MLX5_FLOW_NAMESPACE_FDB, &mod_acts); + if (IS_ERR(mh)) { + err = PTR_ERR(mh); + goto err_attach; + } + + slow_attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; + slow_attr->modify_hdr = mlx5e_mod_hdr_get(mh); + +skip_restore: rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr); - if (!IS_ERR(rule)) - flow_flag_set(flow, SLOW); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + goto err_offload; + } + flow->slow_mh = mh; + flow->chain_mapping = chain_mapping; + flow_flag_set(flow, SLOW); + + mlx5e_mod_hdr_dealloc(&mod_acts); kfree(slow_attr); return rule; + +err_offload: + if (fwd_and_modify_cap) + mlx5e_mod_hdr_detach(esw->dev, get_mod_hdr_table(flow->priv, flow), mh); +err_attach: +err_reg_set: + if (fwd_and_modify_cap) + mlx5_chains_put_chain_mapping(esw_chains(esw), chain_mapping); +err_get_chain: + mlx5e_mod_hdr_dealloc(&mod_acts); + kfree(slow_attr); + return ERR_PTR(err); } void mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, @@ -1441,7 +1489,17 @@ void mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; slow_attr->esw_attr->split_count = 0; slow_attr->flags |= MLX5_ATTR_FLAG_SLOW_PATH; + if (flow->slow_mh) { + slow_attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; + slow_attr->modify_hdr = mlx5e_mod_hdr_get(flow->slow_mh); + } mlx5e_tc_unoffload_fdb_rules(esw, flow, slow_attr); + if (flow->slow_mh) { + mlx5e_mod_hdr_detach(esw->dev, get_mod_hdr_table(flow->priv, flow), flow->slow_mh); + mlx5_chains_put_chain_mapping(esw_chains(esw), flow->chain_mapping); + flow->chain_mapping = 0; + flow->slow_mh = NULL; + } flow_flag_clear(flow, SLOW); kfree(slow_attr); } -- cgit v1.2.3 From 0f3caaa2c6fbf9f892bd235c9dce9eb551f8d815 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Wed, 26 Oct 2022 14:51:44 +0100 Subject: net/mlx5: ASO, Create the ASO SQ with the correct timestamp format mlx5 SQs must select the timestamp format explicitly according to the active clock mode, select the current active timestamp mode so ASO SQ create will succeed. This fixes the following error prints when trying to create ipsec ASO SQ while the timestamp format is real time mode. mlx5_cmd_out_err:778:(pid 34874): CREATE_SQ(0x904) op_mod(0x0) failed, status bad parameter(0x3), syndrome (0xd61c0b), err(-22) mlx5_aso_create_sq:285:(pid 34874): Failed to open aso wq sq, err=-22 mlx5e_ipsec_init:436:(pid 34874): IPSec initialization failed, -22 Fixes: cdd04f4d4d71 ("net/mlx5: Add support to create SQ and CQ for ASO") Signed-off-by: Saeed Mahameed Reported-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-7-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c index baa8092f335e..c971ff04dd04 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c @@ -3,6 +3,7 @@ #include #include +#include "clock.h" #include "aso.h" #include "wq.h" @@ -179,6 +180,7 @@ static int create_aso_sq(struct mlx5_core_dev *mdev, int pdn, { void *in, *sqc, *wq; int inlen, err; + u8 ts_format; inlen = MLX5_ST_SZ_BYTES(create_sq_in) + sizeof(u64) * sq->wq_ctrl.buf.npages; @@ -195,6 +197,11 @@ static int create_aso_sq(struct mlx5_core_dev *mdev, int pdn, MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST); MLX5_SET(sqc, sqc, flush_in_error_en, 1); + ts_format = mlx5_is_real_time_sq(mdev) ? + MLX5_TIMESTAMP_FORMAT_REAL_TIME : + MLX5_TIMESTAMP_FORMAT_FREE_RUNNING; + MLX5_SET(sqc, sqc, ts_format, ts_format); + MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); MLX5_SET(wq, wq, uar_page, mdev->mlx5e_res.hw_objs.bfreg.index); MLX5_SET(wq, wq, log_wq_pg_sz, sq->wq_ctrl.buf.page_shift - -- cgit v1.2.3 From bacd22df95147ed673bec4692ab2d4d585935241 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 26 Oct 2022 14:51:45 +0100 Subject: net/mlx5: Fix possible use-after-free in async command interface mlx5_cmd_cleanup_async_ctx should return only after all its callback handlers were completed. Before this patch, the below race between mlx5_cmd_cleanup_async_ctx and mlx5_cmd_exec_cb_handler was possible and lead to a use-after-free: 1. mlx5_cmd_cleanup_async_ctx is called while num_inflight is 2 (i.e. elevated by 1, a single inflight callback). 2. mlx5_cmd_cleanup_async_ctx decreases num_inflight to 1. 3. mlx5_cmd_exec_cb_handler is called, decreases num_inflight to 0 and is about to call wake_up(). 4. mlx5_cmd_cleanup_async_ctx calls wait_event, which returns immediately as the condition (num_inflight == 0) holds. 5. mlx5_cmd_cleanup_async_ctx returns. 6. The caller of mlx5_cmd_cleanup_async_ctx frees the mlx5_async_ctx object. 7. mlx5_cmd_exec_cb_handler goes on and calls wake_up() on the freed object. Fix it by syncing using a completion object. Mark it completed when num_inflight reaches 0. Trace: BUG: KASAN: use-after-free in do_raw_spin_lock+0x23d/0x270 Read of size 4 at addr ffff888139cd12f4 by task swapper/5/0 CPU: 5 PID: 0 Comm: swapper/5 Not tainted 6.0.0-rc3_for_upstream_debug_2022_08_30_13_10 #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x57/0x7d print_report.cold+0x2d5/0x684 ? do_raw_spin_lock+0x23d/0x270 kasan_report+0xb1/0x1a0 ? do_raw_spin_lock+0x23d/0x270 do_raw_spin_lock+0x23d/0x270 ? rwlock_bug.part.0+0x90/0x90 ? __delete_object+0xb8/0x100 ? lock_downgrade+0x6e0/0x6e0 _raw_spin_lock_irqsave+0x43/0x60 ? __wake_up_common_lock+0xb9/0x140 __wake_up_common_lock+0xb9/0x140 ? __wake_up_common+0x650/0x650 ? destroy_tis_callback+0x53/0x70 [mlx5_core] ? kasan_set_track+0x21/0x30 ? destroy_tis_callback+0x53/0x70 [mlx5_core] ? kfree+0x1ba/0x520 ? do_raw_spin_unlock+0x54/0x220 mlx5_cmd_exec_cb_handler+0x136/0x1a0 [mlx5_core] ? mlx5_cmd_cleanup_async_ctx+0x220/0x220 [mlx5_core] ? mlx5_cmd_cleanup_async_ctx+0x220/0x220 [mlx5_core] mlx5_cmd_comp_handler+0x65a/0x12b0 [mlx5_core] ? dump_command+0xcc0/0xcc0 [mlx5_core] ? lockdep_hardirqs_on_prepare+0x400/0x400 ? cmd_comp_notifier+0x7e/0xb0 [mlx5_core] cmd_comp_notifier+0x7e/0xb0 [mlx5_core] atomic_notifier_call_chain+0xd7/0x1d0 mlx5_eq_async_int+0x3ce/0xa20 [mlx5_core] atomic_notifier_call_chain+0xd7/0x1d0 ? irq_release+0x140/0x140 [mlx5_core] irq_int_handler+0x19/0x30 [mlx5_core] __handle_irq_event_percpu+0x1f2/0x620 handle_irq_event+0xb2/0x1d0 handle_edge_irq+0x21e/0xb00 __common_interrupt+0x79/0x1a0 common_interrupt+0x78/0xa0 asm_common_interrupt+0x22/0x40 RIP: 0010:default_idle+0x42/0x60 Code: c1 83 e0 07 48 c1 e9 03 83 c0 03 0f b6 14 11 38 d0 7c 04 84 d2 75 14 8b 05 eb 47 22 02 85 c0 7e 07 0f 00 2d e0 9f 48 00 fb f4 48 c7 c7 80 08 7f 85 e8 d1 d3 3e fe eb de 66 66 2e 0f 1f 84 00 RSP: 0018:ffff888100dbfdf0 EFLAGS: 00000242 RAX: 0000000000000001 RBX: ffffffff84ecbd48 RCX: 1ffffffff0afe110 RDX: 0000000000000004 RSI: 0000000000000000 RDI: ffffffff835cc9bc RBP: 0000000000000005 R08: 0000000000000001 R09: ffff88881dec4ac3 R10: ffffed1103bd8958 R11: 0000017d0ca571c9 R12: 0000000000000005 R13: ffffffff84f024e0 R14: 0000000000000000 R15: dffffc0000000000 ? default_idle_call+0xcc/0x450 default_idle_call+0xec/0x450 do_idle+0x394/0x450 ? arch_cpu_idle_exit+0x40/0x40 ? do_idle+0x17/0x450 cpu_startup_entry+0x19/0x20 start_secondary+0x221/0x2b0 ? set_cpu_sibling_map+0x2070/0x2070 secondary_startup_64_no_verify+0xcd/0xdb Allocated by task 49502: kasan_save_stack+0x1e/0x40 __kasan_kmalloc+0x81/0xa0 kvmalloc_node+0x48/0xe0 mlx5e_bulk_async_init+0x35/0x110 [mlx5_core] mlx5e_tls_priv_tx_list_cleanup+0x84/0x3e0 [mlx5_core] mlx5e_ktls_cleanup_tx+0x38f/0x760 [mlx5_core] mlx5e_cleanup_nic_tx+0xa7/0x100 [mlx5_core] mlx5e_detach_netdev+0x1ca/0x2b0 [mlx5_core] mlx5e_suspend+0xdb/0x140 [mlx5_core] mlx5e_remove+0x89/0x190 [mlx5_core] auxiliary_bus_remove+0x52/0x70 device_release_driver_internal+0x40f/0x650 driver_detach+0xc1/0x180 bus_remove_driver+0x125/0x2f0 auxiliary_driver_unregister+0x16/0x50 mlx5e_cleanup+0x26/0x30 [mlx5_core] cleanup+0xc/0x4e [mlx5_core] __x64_sys_delete_module+0x2b5/0x450 do_syscall_64+0x3d/0x90 entry_SYSCALL_64_after_hwframe+0x46/0xb0 Freed by task 49502: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 kasan_set_free_info+0x20/0x30 ____kasan_slab_free+0x11d/0x1b0 kfree+0x1ba/0x520 mlx5e_tls_priv_tx_list_cleanup+0x2e7/0x3e0 [mlx5_core] mlx5e_ktls_cleanup_tx+0x38f/0x760 [mlx5_core] mlx5e_cleanup_nic_tx+0xa7/0x100 [mlx5_core] mlx5e_detach_netdev+0x1ca/0x2b0 [mlx5_core] mlx5e_suspend+0xdb/0x140 [mlx5_core] mlx5e_remove+0x89/0x190 [mlx5_core] auxiliary_bus_remove+0x52/0x70 device_release_driver_internal+0x40f/0x650 driver_detach+0xc1/0x180 bus_remove_driver+0x125/0x2f0 auxiliary_driver_unregister+0x16/0x50 mlx5e_cleanup+0x26/0x30 [mlx5_core] cleanup+0xc/0x4e [mlx5_core] __x64_sys_delete_module+0x2b5/0x450 do_syscall_64+0x3d/0x90 entry_SYSCALL_64_after_hwframe+0x46/0xb0 Fixes: e355477ed9e4 ("net/mlx5: Make mlx5_cmd_exec_cb() a safe API") Signed-off-by: Tariq Toukan Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-8-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 0377392848d9..46ba4c2faad2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -2004,7 +2004,7 @@ void mlx5_cmd_init_async_ctx(struct mlx5_core_dev *dev, ctx->dev = dev; /* Starts at 1 to avoid doing wake_up if we are not cleaning up */ atomic_set(&ctx->num_inflight, 1); - init_waitqueue_head(&ctx->wait); + init_completion(&ctx->inflight_done); } EXPORT_SYMBOL(mlx5_cmd_init_async_ctx); @@ -2018,8 +2018,8 @@ EXPORT_SYMBOL(mlx5_cmd_init_async_ctx); */ void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx) { - atomic_dec(&ctx->num_inflight); - wait_event(ctx->wait, atomic_read(&ctx->num_inflight) == 0); + if (!atomic_dec_and_test(&ctx->num_inflight)) + wait_for_completion(&ctx->inflight_done); } EXPORT_SYMBOL(mlx5_cmd_cleanup_async_ctx); @@ -2032,7 +2032,7 @@ static void mlx5_cmd_exec_cb_handler(int status, void *_work) status = cmd_status_err(ctx->dev, status, work->opcode, work->out); work->user_callback(status, work); if (atomic_dec_and_test(&ctx->num_inflight)) - wake_up(&ctx->wait); + complete(&ctx->inflight_done); } int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, @@ -2050,7 +2050,7 @@ int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, ret = cmd_exec(ctx->dev, in, in_size, out, out_size, mlx5_cmd_exec_cb_handler, work, false); if (ret && atomic_dec_and_test(&ctx->num_inflight)) - wake_up(&ctx->wait); + complete(&ctx->inflight_done); return ret; } -- cgit v1.2.3 From f382a2413dae8c855226a72600812a4b37432c48 Mon Sep 17 00:00:00 2001 From: Ariel Levkovich Date: Wed, 26 Oct 2022 14:51:46 +0100 Subject: net/mlx5e: TC, Reject forwarding from internal port to internal port Reject TC rules that forward from internal port to internal port as it is not supported. This include rules that are explicitly have internal port as the filter device as well as rules that apply on tunnel interfaces as the route device for the tunnel interface can be an internal port. Fixes: 27484f7170ed ("net/mlx5e: Offload tc rules that redirect to ovs internal port") Signed-off-by: Ariel Levkovich Reviewed-by: Maor Dickman Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-9-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 2cceace36c77..73f91e54e9d0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -4066,6 +4066,7 @@ parse_tc_fdb_actions(struct mlx5e_priv *priv, struct mlx5e_tc_flow_parse_attr *parse_attr; struct mlx5_flow_attr *attr = flow->attr; struct mlx5_esw_flow_attr *esw_attr; + struct net_device *filter_dev; int err; err = flow_action_supported(flow_action, extack); @@ -4074,6 +4075,7 @@ parse_tc_fdb_actions(struct mlx5e_priv *priv, esw_attr = attr->esw_attr; parse_attr = attr->parse_attr; + filter_dev = parse_attr->filter_dev; parse_state = &parse_attr->parse_state; mlx5e_tc_act_init_parse_state(parse_state, flow, flow_action, extack); parse_state->ct_priv = get_ct_priv(priv); @@ -4083,13 +4085,21 @@ parse_tc_fdb_actions(struct mlx5e_priv *priv, return err; /* Forward to/from internal port can only have 1 dest */ - if ((netif_is_ovs_master(parse_attr->filter_dev) || esw_attr->dest_int_port) && + if ((netif_is_ovs_master(filter_dev) || esw_attr->dest_int_port) && esw_attr->out_count > 1) { NL_SET_ERR_MSG_MOD(extack, "Rules with internal port can have only one destination"); return -EOPNOTSUPP; } + /* Forward from tunnel/internal port to internal port is not supported */ + if ((mlx5e_get_tc_tun(filter_dev) || netif_is_ovs_master(filter_dev)) && + esw_attr->dest_int_port) { + NL_SET_ERR_MSG_MOD(extack, + "Forwarding from tunnel/internal port to internal port is not supported"); + return -EOPNOTSUPP; + } + err = actions_prepare_mod_hdr_actions(priv, flow, attr, extack); if (err) return err; -- cgit v1.2.3 From 94d651739e17b0ee9b556e60f206fe538d06dc05 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Wed, 26 Oct 2022 14:51:47 +0100 Subject: net/mlx5e: TC, Fix cloned flow attr instance dests are not zeroed On multi table split the driver creates a new attr instance with data being copied from prev attr instance zeroing action flags. Also need to reset dests properties to avoid incorrect dests per attr. Fixes: 8300f225268b ("net/mlx5e: Create new flow attr for multi table actions") Signed-off-by: Roi Dayan Reviewed-by: Maor Dickman Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-10-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 73f91e54e9d0..dd6fea9e9a5b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3633,6 +3633,10 @@ mlx5e_clone_flow_attr_for_post_act(struct mlx5_flow_attr *attr, attr2->action = 0; attr2->flags = 0; attr2->parse_attr = parse_attr; + attr2->esw_attr->out_count = 0; + attr2->esw_attr->split_count = 0; + attr2->dest_chain = 0; + attr2->dest_ft = NULL; return attr2; } -- cgit v1.2.3 From 416ef713631937cf5452476a7f1041a3ae7b06c6 Mon Sep 17 00:00:00 2001 From: Roy Novich Date: Wed, 26 Oct 2022 14:51:48 +0100 Subject: net/mlx5: Update fw fatal reporter state on PCI handlers successful recover Update devlink health fw fatal reporter state to "healthy" is needed by strictly calling devlink_health_reporter_state_update() after recovery was done by PCI error handler. This is needed when fw_fatal reporter was triggered due to PCI error. Poll health is called and set reporter state to error. Health recovery failed (since EEH didn't re-enable the PCI). PCI handlers keep on recover flow and succeed later without devlink acknowledgment. Fix this by adding devlink state update at the end of the PCI handler recovery process. Fixes: 6181e5cb752e ("devlink: add support for reporter recovery completion") Signed-off-by: Roy Novich Reviewed-by: Moshe Shemesh Reviewed-by: Aya Levin Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-11-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 0b459d841c3a..283c4cc28944 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1872,6 +1872,10 @@ static void mlx5_pci_resume(struct pci_dev *pdev) err = mlx5_load_one(dev, false); + if (!err) + devlink_health_reporter_state_update(dev->priv.health.fw_fatal_reporter, + DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); + mlx5_pci_trace(dev, "Done, err = %d, device %s\n", err, !err ? "recovered" : "Failed"); } -- cgit v1.2.3 From aefb62a9988749703435e941704624949a80a2a9 Mon Sep 17 00:00:00 2001 From: Suresh Devarakonda Date: Wed, 26 Oct 2022 14:51:49 +0100 Subject: net/mlx5: Fix crash during sync firmware reset When setting Bluefield to DPU NIC mode using mlxconfig tool + sync firmware reset flow, we run into scenario where the host was not eswitch manager at the time of mlx5 driver load but becomes eswitch manager after the sync firmware reset flow. This results in null pointer access of mpfs structure during mac filter add. This change prevents null pointer access but mpfs table entries will not be added. Fixes: 5ec697446f46 ("net/mlx5: Add support for devlink reload action fw activate") Signed-off-by: Suresh Devarakonda Reviewed-by: Moshe Shemesh Reviewed-by: Bodong Wang Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-12-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c index 839a01da110f..8ff16318e32d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c @@ -122,7 +122,7 @@ void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev) { struct mlx5_mpfs *mpfs = dev->priv.mpfs; - if (!MLX5_ESWITCH_MANAGER(dev)) + if (!mpfs) return; WARN_ON(!hlist_empty(mpfs->hash)); @@ -137,7 +137,7 @@ int mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac) int err = 0; u32 index; - if (!MLX5_ESWITCH_MANAGER(dev)) + if (!mpfs) return 0; mutex_lock(&mpfs->lock); @@ -185,7 +185,7 @@ int mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac) int err = 0; u32 index; - if (!MLX5_ESWITCH_MANAGER(dev)) + if (!mpfs) return 0; mutex_lock(&mpfs->lock); -- cgit v1.2.3 From d3ecf037569c64490a5cae5a1ac4605f4bedc607 Mon Sep 17 00:00:00 2001 From: Raed Salem Date: Wed, 26 Oct 2022 14:51:50 +0100 Subject: net/mlx5e: Fix macsec coverity issue at rx sa update The cited commit at update rx sa operation passes object attributes to MACsec object create function without initializing/setting all attributes fields leaving some of them with garbage values, therefore violating the implicit assumption at create object function, which assumes that all input object attributes fields are set. Fix by initializing the object attributes struct to zero, thus leaving unset fields with the legal zero value. Fixes: aae3454e4d4c ("net/mlx5e: Add MACsec offload Rx command support") Signed-off-by: Raed Salem Reviewed-by: Lior Nahmanson Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-13-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 4331235b21ee..250c878ba2c9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -432,7 +432,7 @@ static int mlx5e_macsec_update_rx_sa(struct mlx5e_macsec *macsec, bool active) { struct mlx5_core_dev *mdev = macsec->mdev; - struct mlx5_macsec_obj_attrs attrs; + struct mlx5_macsec_obj_attrs attrs = {}; int err = 0; if (rx_sa->active != active) -- cgit v1.2.3 From 74573e38e933a6dbb11691bea535c54d683cd06e Mon Sep 17 00:00:00 2001 From: Raed Salem Date: Wed, 26 Oct 2022 14:51:51 +0100 Subject: net/mlx5e: Fix macsec rx security association (SA) update/delete The cited commit adds the support for update/delete MACsec Rx SA, naturally, these operations need to check if the SA in question exists to update/delete the SA and return error code otherwise, however they do just the opposite i.e. return with error if the SA exists Fix by change the check to return error in case the SA in question does not exist, adjust error message and code accordingly. Fixes: aae3454e4d4c ("net/mlx5e: Add MACsec offload Rx command support") Signed-off-by: Raed Salem Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-14-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 250c878ba2c9..6ae9fcdbda07 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -999,11 +999,11 @@ static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx) } rx_sa = rx_sc->rx_sa[assoc_num]; - if (rx_sa) { + if (!rx_sa) { netdev_err(ctx->netdev, - "MACsec offload rx_sc sci %lld rx_sa %d already exist\n", + "MACsec offload rx_sc sci %lld rx_sa %d doesn't exist\n", sci, assoc_num); - err = -EEXIST; + err = -EINVAL; goto out; } @@ -1055,11 +1055,11 @@ static int mlx5e_macsec_del_rxsa(struct macsec_context *ctx) } rx_sa = rx_sc->rx_sa[assoc_num]; - if (rx_sa) { + if (!rx_sa) { netdev_err(ctx->netdev, - "MACsec offload rx_sc sci %lld rx_sa %d already exist\n", + "MACsec offload rx_sc sci %lld rx_sa %d doesn't exist\n", sci, assoc_num); - err = -EEXIST; + err = -EINVAL; goto out; } -- cgit v1.2.3 From d550956458a83cf87cb8fe24862f3340065c62c1 Mon Sep 17 00:00:00 2001 From: Raed Salem Date: Wed, 26 Oct 2022 14:51:52 +0100 Subject: net/mlx5e: Fix wrong bitwise comparison usage in macsec_fs_rx_add_rule function The cited commit produces a sparse check error of type "sparse: error: restricted __be64 degrades to integer". The offending line wrongly did a bitwise operation between two different storage types one of 64 bit when the other smaller side is 16 bit which caused the above sparse error, furthermore bitwise operation usage here is wrong in the first place as the constant MACSEC_PORT_ES is not a bitwise field. Fix by using the right mask to get the lower 16 bit if the sci number, and use comparison operator '==' instead of bitwise '&' operator. Fixes: 3b20949cb21b ("net/mlx5e: Add MACsec RX steering rules") Signed-off-by: Raed Salem Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-15-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c index 13dc628b988a..1ac0cf04e811 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c @@ -1180,7 +1180,7 @@ macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs, rx_rule->rule[0] = rule; /* Rx crypto table without SCI rule */ - if (cpu_to_be64((__force u64)attrs->sci) & ntohs(MACSEC_PORT_ES)) { + if ((cpu_to_be64((__force u64)attrs->sci) & 0xFFFF) == ntohs(MACSEC_PORT_ES)) { memset(spec, 0, sizeof(struct mlx5_flow_spec)); memset(&dest, 0, sizeof(struct mlx5_flow_destination)); memset(&flow_act, 0, sizeof(flow_act)); -- cgit v1.2.3 From 12ba40ba3dc3a28ad579b7de2202ab6419da304a Mon Sep 17 00:00:00 2001 From: Raed Salem Date: Wed, 26 Oct 2022 14:51:53 +0100 Subject: net/mlx5e: Fix macsec sci endianness at rx sa update The cited commit at rx sa update operation passes the sci object attribute, in the wrong endianness and not as expected by the HW effectively create malformed hw sa context in case of update rx sa consequently, HW produces unexpected MACsec packets which uses this sa. Fix by passing sci to create macsec object with the correct endianness, while at it add __force u64 to prevent sparse check error of type "sparse: error: incorrect type in assignment". Fixes: aae3454e4d4c ("net/mlx5e: Add MACsec offload Rx command support") Signed-off-by: Raed Salem Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20221026135153.154807-16-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 6ae9fcdbda07..2ef36cb9555a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -444,7 +444,7 @@ static int mlx5e_macsec_update_rx_sa(struct mlx5e_macsec *macsec, return 0; } - attrs.sci = rx_sa->sci; + attrs.sci = cpu_to_be64((__force u64)rx_sa->sci); attrs.enc_key_id = rx_sa->enc_key_id; err = mlx5e_macsec_create_object(mdev, &attrs, false, &rx_sa->macsec_obj_id); if (err) -- cgit v1.2.3 From 3c6bf6bddc84888c0ce163b09dee0ddd23b5172a Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 24 Oct 2022 22:00:28 +0800 Subject: fbdev: cyber2000fb: fix missing pci_disable_device() Add missing pci_disable_device() in error path of probe() and remove() path. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Yang Yingliang Signed-off-by: Helge Deller --- drivers/video/fbdev/cyber2000fb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/video/fbdev/cyber2000fb.c b/drivers/video/fbdev/cyber2000fb.c index 585af90a68a5..31ff1da82c05 100644 --- a/drivers/video/fbdev/cyber2000fb.c +++ b/drivers/video/fbdev/cyber2000fb.c @@ -1796,6 +1796,7 @@ failed_ioremap: failed_regions: cyberpro_free_fb_info(cfb); failed_release: + pci_disable_device(dev); return err; } @@ -1812,6 +1813,7 @@ static void cyberpro_pci_remove(struct pci_dev *dev) int_cfb_info = NULL; pci_release_regions(dev); + pci_disable_device(dev); } } -- cgit v1.2.3 From 84ce1ca3fe9e1249bf21176ff162200f1c4e5ed1 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 27 Oct 2022 21:29:25 +0300 Subject: net: enetc: survive memory pressure without crashing Under memory pressure, enetc_refill_rx_ring() may fail, and when called during the enetc_open() -> enetc_setup_rxbdr() procedure, this is not checked for. An extreme case of memory pressure will result in exactly zero buffers being allocated for the RX ring, and in such a case it is expected that hardware drops all RX packets due to lack of buffers. This does not happen, because the reset-default value of the consumer and produces index is 0, and this makes the ENETC think that all buffers have been initialized and that it owns them (when in reality none were). The hardware guide explains this best: | Configure the receive ring producer index register RBaPIR with a value | of 0. The producer index is initially configured by software but owned | by hardware after the ring has been enabled. Hardware increments the | index when a frame is received which may consume one or more BDs. | Hardware is not allowed to increment the producer index to match the | consumer index since it is used to indicate an empty condition. The ring | can hold at most RBLENR[LENGTH]-1 received BDs. | | Configure the receive ring consumer index register RBaCIR. The | consumer index is owned by software and updated during operation of the | of the BD ring by software, to indicate that any receive data occupied | in the BD has been processed and it has been prepared for new data. | - If consumer index and producer index are initialized to the same | value, it indicates that all BDs in the ring have been prepared and | hardware owns all of the entries. | - If consumer index is initialized to producer index plus N, it would | indicate N BDs have been prepared. Note that hardware cannot start if | only a single buffer is prepared due to the restrictions described in | (2). | - Software may write consumer index to match producer index anytime | while the ring is operational to indicate all received BDs prior have | been processed and new BDs prepared for hardware. Normally, the value of rx_ring->rcir (consumer index) is brought in sync with the rx_ring->next_to_use software index, but this only happens if page allocation ever succeeded. When PI==CI==0, the hardware appears to receive frames and write them to DMA address 0x0 (?!), then set the READY bit in the BD. The enetc_clean_rx_ring() function (and its XDP derivative) is naturally not prepared to handle such a condition. It will attempt to process those frames using the rx_swbd structure associated with index i of the RX ring, but that structure is not fully initialized (enetc_new_page() does all of that). So what happens next is undefined behavior. To operate using no buffer, we must initialize the CI to PI + 1, which will block the hardware from advancing the CI any further, and drop everything. The issue was seen while adding support for zero-copy AF_XDP sockets, where buffer memory comes from user space, which can even decide to supply no buffers at all (example: "xdpsock --txonly"). However, the bug is present also with the network stack code, even though it would take a very determined person to trigger a page allocation failure at the perfect time (a series of ifup/ifdown under memory pressure should eventually reproduce it given enough retries). Fixes: d4fd0404c1c9 ("enetc: Introduce basic PF and VF ENETC ethernet drivers") Signed-off-by: Vladimir Oltean Reviewed-by: Claudiu Manoil Link: https://lore.kernel.org/r/20221027182925.3256653-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/enetc/enetc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 54bc92fc6bf0..f8c06c3f9464 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -2090,7 +2090,12 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) else enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, ENETC_RXB_DMA_SIZE); + /* Also prepare the consumer index in case page allocation never + * succeeds. In that case, hardware will never advance producer index + * to match consumer index, and will drop all frames. + */ enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0); + enetc_rxbdr_wr(hw, idx, ENETC_RBCIR, 1); /* enable Rx ints by setting pkt thr to 1 */ enetc_rxbdr_wr(hw, idx, ENETC_RBICR0, ENETC_RBICR0_ICEN | 0x1); -- cgit v1.2.3 From e37203511c1f2622398eafb7c94a00915bf8e1a1 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Thu, 20 Oct 2022 11:46:40 -0400 Subject: drm/amd/display: Update DSC capabilitie for DCN314 dcn314 has 4 DSC - conflicted hardware document updated and confirmed. Tested-by: Mark Broadworth Reviewed-by: Charlene Liu Acked-by: Rodrigo Siqueira Signed-off-by: Leo Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index 92eb56873eee..85e2d87a8e44 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -847,7 +847,7 @@ static const struct resource_caps res_cap_dcn314 = { .num_ddc = 5, .num_vmid = 16, .num_mpc_3dlut = 2, - .num_dsc = 3, + .num_dsc = 4, }; static const struct dc_plane_cap plane_cap = { -- cgit v1.2.3 From d1bc26cb5cd51fd1e7984423b665bf8abfd69256 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Thu, 20 Oct 2022 11:46:41 -0400 Subject: drm/amd/display: Ignore Cable ID Feature Ignore cable ID for DP2 receivers that does not support the feature. Tested-by: Mark Broadworth Reviewed-by: Roman Li Acked-by: Rodrigo Siqueira Signed-off-by: Fangzhi Zuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c053cb79cd06..589bee9acf16 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1549,6 +1549,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm; + /* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */ + adev->dm.dc->debug.ignore_cable_id = true; + r = dm_dmub_hw_init(adev); if (r) { DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); -- cgit v1.2.3 From c0459bddd1955df35c9331757671e64e3ea0a77a Mon Sep 17 00:00:00 2001 From: Alan Liu Date: Thu, 20 Oct 2022 11:46:42 -0400 Subject: drm/amd/display: Implement secure display on DCN21 [Why] Porting secure display feature from DCN10 to DCN21. Support single display for now and will extend to multiple displays. [How] - use workqueue to offload works for dmub or dmcu firmware - after receiving ROI update from userspace, set skip_frame_cnt to 1 - refactor amdgpu_dm_crtc_handle_crc_window_irq() - disable PSR before activating secure_display on a crtc - check if secure_display is activated before enabling psr - only work for single display for now. Tested-by: Mark Broadworth Reviewed-by: Wayne Lin Acked-by: Rodrigo Siqueira Signed-off-by: Alan Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 151 ++++++++++----------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 17 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 3 + .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 55 +++++--- .../amd/display/amdgpu_dm/amdgpu_dm_irq_params.h | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 115 ++++++++-------- drivers/gpu/drm/amd/display/dc/dc_stream.h | 8 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 14 ++ drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 14 -- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 26 ++++ 11 files changed, 223 insertions(+), 189 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 589bee9acf16..72aede3fcf9b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7840,6 +7840,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, */ if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 && acrtc_attach->dm_irq_params.allow_psr_entry && +#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY + !amdgpu_dm_crc_window_is_activated(acrtc_state->base.crtc) && +#endif !acrtc_state->stream->link->psr_settings.psr_allow_active) amdgpu_dm_psr_enable(acrtc_state->stream); } else { @@ -8301,8 +8304,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) if (amdgpu_dm_crc_window_is_activated(crtc)) { spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); - acrtc->dm_irq_params.crc_window.update_win = true; - acrtc->dm_irq_params.crc_window.skip_frame_cnt = 2; + acrtc->dm_irq_params.window_param.update_win = true; + acrtc->dm_irq_params.window_param.skip_frame_cnt = 2; spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock); crc_rd_wrk->crtc = crtc; spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index 8a441a22c46e..a857f6454753 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -89,13 +89,13 @@ static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.crc_window.x_start = 0; - acrtc->dm_irq_params.crc_window.y_start = 0; - acrtc->dm_irq_params.crc_window.x_end = 0; - acrtc->dm_irq_params.crc_window.y_end = 0; - acrtc->dm_irq_params.crc_window.activated = false; - acrtc->dm_irq_params.crc_window.update_win = false; - acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; + acrtc->dm_irq_params.window_param.roi.x_start = 0; + acrtc->dm_irq_params.window_param.roi.y_start = 0; + acrtc->dm_irq_params.window_param.roi.x_end = 0; + acrtc->dm_irq_params.window_param.roi.y_end = 0; + acrtc->dm_irq_params.window_param.activated = false; + acrtc->dm_irq_params.window_param.update_win = false; + acrtc->dm_irq_params.window_param.skip_frame_cnt = 0; spin_unlock_irq(&drm_dev->event_lock); } @@ -135,6 +135,22 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work) } } +static void +amdgpu_dm_forward_crc_window(struct work_struct *work) +{ + struct crc_fw_work *crc_fw_wrk; + struct amdgpu_display_manager *dm; + + crc_fw_wrk = container_of(work, struct crc_fw_work, forward_roi_work); + dm = crc_fw_wrk->dm; + + mutex_lock(&dm->dc_lock); + dc_stream_forward_crc_window(dm->dc, &crc_fw_wrk->roi, crc_fw_wrk->stream, crc_fw_wrk->is_stop_cmd); + mutex_unlock(&dm->dc_lock); + + kfree(crc_fw_wrk); +} + bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc) { struct drm_device *drm_dev = crtc->dev; @@ -142,7 +158,7 @@ bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc) bool ret = false; spin_lock_irq(&drm_dev->event_lock); - ret = acrtc->dm_irq_params.crc_window.activated; + ret = acrtc->dm_irq_params.window_param.activated; spin_unlock_irq(&drm_dev->event_lock); return ret; @@ -187,9 +203,11 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc, if (adev->dm.crc_rd_wrk) { flush_work(&adev->dm.crc_rd_wrk->notify_ta_work); spin_lock_irq(&adev->dm.crc_rd_wrk->crc_rd_work_lock); + if (adev->dm.crc_rd_wrk->crtc == crtc) { - dc_stream_stop_dmcu_crc_win_update(stream_state->ctx->dc, - dm_crtc_state->stream); + /* stop ROI update on this crtc */ + dc_stream_forward_crc_window(stream_state->ctx->dc, + NULL, stream_state, true); adev->dm.crc_rd_wrk->crtc = NULL; } spin_unlock_irq(&adev->dm.crc_rd_wrk->crc_rd_work_lock); @@ -439,14 +457,9 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) enum amdgpu_dm_pipe_crc_source cur_crc_src; struct amdgpu_crtc *acrtc = NULL; struct amdgpu_device *adev = NULL; - struct crc_rd_work *crc_rd_wrk = NULL; - struct crc_params *crc_window = NULL, tmp_window; + struct crc_rd_work *crc_rd_wrk; + struct crc_fw_work *crc_fw_wrk; unsigned long flags1, flags2; - struct crtc_position position; - uint32_t v_blank; - uint32_t v_back_porch; - uint32_t crc_window_latch_up_line; - struct dc_crtc_timing *timing_out; if (crtc == NULL) return; @@ -458,74 +471,52 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) spin_lock_irqsave(&drm_dev->event_lock, flags1); stream_state = acrtc->dm_irq_params.stream; cur_crc_src = acrtc->dm_irq_params.crc_src; - timing_out = &stream_state->timing; /* Early return if CRC capture is not enabled. */ if (!amdgpu_dm_is_valid_crc_source(cur_crc_src)) goto cleanup; - if (dm_is_crc_source_crtc(cur_crc_src)) { - if (acrtc->dm_irq_params.crc_window.activated) { - if (acrtc->dm_irq_params.crc_window.update_win) { - if (acrtc->dm_irq_params.crc_window.skip_frame_cnt) { - acrtc->dm_irq_params.crc_window.skip_frame_cnt -= 1; - goto cleanup; - } - crc_window = &tmp_window; - - tmp_window.windowa_x_start = - acrtc->dm_irq_params.crc_window.x_start; - tmp_window.windowa_y_start = - acrtc->dm_irq_params.crc_window.y_start; - tmp_window.windowa_x_end = - acrtc->dm_irq_params.crc_window.x_end; - tmp_window.windowa_y_end = - acrtc->dm_irq_params.crc_window.y_end; - tmp_window.windowb_x_start = - acrtc->dm_irq_params.crc_window.x_start; - tmp_window.windowb_y_start = - acrtc->dm_irq_params.crc_window.y_start; - tmp_window.windowb_x_end = - acrtc->dm_irq_params.crc_window.x_end; - tmp_window.windowb_y_end = - acrtc->dm_irq_params.crc_window.y_end; - - dc_stream_forward_dmcu_crc_window(stream_state->ctx->dc, - stream_state, crc_window); - - acrtc->dm_irq_params.crc_window.update_win = false; - - dc_stream_get_crtc_position(stream_state->ctx->dc, &stream_state, 1, - &position.vertical_count, - &position.nominal_vcount); - - v_blank = timing_out->v_total - timing_out->v_border_top - - timing_out->v_addressable - timing_out->v_border_bottom; - - v_back_porch = v_blank - timing_out->v_front_porch - - timing_out->v_sync_width; - - crc_window_latch_up_line = v_back_porch + timing_out->v_sync_width; - - /* take 3 lines margin*/ - if ((position.vertical_count + 3) >= crc_window_latch_up_line) - acrtc->dm_irq_params.crc_window.skip_frame_cnt = 1; - else - acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; - } else { - if (acrtc->dm_irq_params.crc_window.skip_frame_cnt == 0) { - if (adev->dm.crc_rd_wrk) { - crc_rd_wrk = adev->dm.crc_rd_wrk; - spin_lock_irqsave(&crc_rd_wrk->crc_rd_work_lock, flags2); - crc_rd_wrk->phy_inst = - stream_state->link->link_enc_hw_inst; - spin_unlock_irqrestore(&crc_rd_wrk->crc_rd_work_lock, flags2); - schedule_work(&crc_rd_wrk->notify_ta_work); - } - } else { - acrtc->dm_irq_params.crc_window.skip_frame_cnt -= 1; - } - } + if (!dm_is_crc_source_crtc(cur_crc_src)) + goto cleanup; + + if (!acrtc->dm_irq_params.window_param.activated) + goto cleanup; + + if (acrtc->dm_irq_params.window_param.update_win) { + if (acrtc->dm_irq_params.window_param.skip_frame_cnt) { + acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1; + goto cleanup; + } + + /* prepare work for dmub to update ROI */ + crc_fw_wrk = kzalloc(sizeof(*crc_fw_wrk), GFP_ATOMIC); + if (!crc_fw_wrk) + goto cleanup; + + INIT_WORK(&crc_fw_wrk->forward_roi_work, amdgpu_dm_forward_crc_window); + crc_fw_wrk->dm = &adev->dm; + crc_fw_wrk->stream = stream_state; + crc_fw_wrk->roi.x_start = acrtc->dm_irq_params.window_param.roi.x_start; + crc_fw_wrk->roi.y_start = acrtc->dm_irq_params.window_param.roi.y_start; + crc_fw_wrk->roi.x_end = acrtc->dm_irq_params.window_param.roi.x_end; + crc_fw_wrk->roi.y_end = acrtc->dm_irq_params.window_param.roi.y_end; + schedule_work(&crc_fw_wrk->forward_roi_work); + + acrtc->dm_irq_params.window_param.update_win = false; + acrtc->dm_irq_params.window_param.skip_frame_cnt = 1; + + } else { + if (acrtc->dm_irq_params.window_param.skip_frame_cnt) { + acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1; + goto cleanup; + } + + if (adev->dm.crc_rd_wrk) { + crc_rd_wrk = adev->dm.crc_rd_wrk; + spin_lock_irqsave(&crc_rd_wrk->crc_rd_work_lock, flags2); + crc_rd_wrk->phy_inst = stream_state->link->link_enc_hw_inst; + spin_unlock_irqrestore(&crc_rd_wrk->crc_rd_work_lock, flags2); + schedule_work(&crc_rd_wrk->notify_ta_work); } } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h index f07850db60a6..16bfc2dc35ab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h @@ -40,11 +40,8 @@ enum amdgpu_dm_pipe_crc_source { }; #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY -struct crc_window_parm { - uint16_t x_start; - uint16_t y_start; - uint16_t x_end; - uint16_t y_end; +struct crc_window_param { + struct crc_region roi; /* CRC windwo is activated or not*/ bool activated; /* Update crc window during vertical blank or not */ @@ -53,6 +50,7 @@ struct crc_window_parm { int skip_frame_cnt; }; +/* read_work for driver to call PSP to read */ struct crc_rd_work { struct work_struct notify_ta_work; /* To protect crc_rd_work carried fields*/ @@ -60,6 +58,15 @@ struct crc_rd_work { struct drm_crtc *crtc; uint8_t phy_inst; }; + +/* forward_work for driver to forward ROI to dmu */ +struct crc_fw_work { + struct work_struct forward_roi_work; + struct amdgpu_display_manager *dm; + struct dc_stream_state *stream; + struct crc_region roi; + bool is_stop_cmd; +}; #endif static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source source) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 594fe8a4d02b..3675b39e297a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -127,6 +127,9 @@ static void vblank_control_worker(struct work_struct *work) amdgpu_dm_psr_disable(vblank_work->stream); } else if (vblank_work->stream->link->psr_settings.psr_feature_enabled && !vblank_work->stream->link->psr_settings.psr_allow_active && +#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY + !amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base) && +#endif vblank_work->acrtc->dm_irq_params.allow_psr_entry) { amdgpu_dm_psr_enable(vblank_work->stream); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 0c717d7b12e5..8f5b98df26db 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -38,6 +38,10 @@ #include "link_hwss.h" #include "dc/dc_dmub_srv.h" +#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY +#include "amdgpu_dm_psr.h" +#endif + struct dmub_debugfs_trace_header { uint32_t entry_count; uint32_t reserved[3]; @@ -3081,8 +3085,8 @@ static int crc_win_x_start_set(void *data, u64 val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.crc_window.x_start = (uint16_t) val; - acrtc->dm_irq_params.crc_window.update_win = false; + acrtc->dm_irq_params.window_param.roi.x_start = (uint16_t) val; + acrtc->dm_irq_params.window_param.update_win = false; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3098,7 +3102,7 @@ static int crc_win_x_start_get(void *data, u64 *val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - *val = acrtc->dm_irq_params.crc_window.x_start; + *val = acrtc->dm_irq_params.window_param.roi.x_start; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3118,8 +3122,8 @@ static int crc_win_y_start_set(void *data, u64 val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.crc_window.y_start = (uint16_t) val; - acrtc->dm_irq_params.crc_window.update_win = false; + acrtc->dm_irq_params.window_param.roi.y_start = (uint16_t) val; + acrtc->dm_irq_params.window_param.update_win = false; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3135,7 +3139,7 @@ static int crc_win_y_start_get(void *data, u64 *val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - *val = acrtc->dm_irq_params.crc_window.y_start; + *val = acrtc->dm_irq_params.window_param.roi.y_start; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3154,8 +3158,8 @@ static int crc_win_x_end_set(void *data, u64 val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.crc_window.x_end = (uint16_t) val; - acrtc->dm_irq_params.crc_window.update_win = false; + acrtc->dm_irq_params.window_param.roi.x_end = (uint16_t) val; + acrtc->dm_irq_params.window_param.update_win = false; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3171,7 +3175,7 @@ static int crc_win_x_end_get(void *data, u64 *val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - *val = acrtc->dm_irq_params.crc_window.x_end; + *val = acrtc->dm_irq_params.window_param.roi.x_end; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3190,8 +3194,8 @@ static int crc_win_y_end_set(void *data, u64 val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.crc_window.y_end = (uint16_t) val; - acrtc->dm_irq_params.crc_window.update_win = false; + acrtc->dm_irq_params.window_param.roi.y_end = (uint16_t) val; + acrtc->dm_irq_params.window_param.update_win = false; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3207,7 +3211,7 @@ static int crc_win_y_end_get(void *data, u64 *val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - *val = acrtc->dm_irq_params.crc_window.y_end; + *val = acrtc->dm_irq_params.window_param.roi.y_end; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3230,31 +3234,38 @@ static int crc_win_update_set(void *data, u64 val) return 0; if (val) { + new_acrtc = to_amdgpu_crtc(new_crtc); + mutex_lock(&adev->dm.dc_lock); + /* PSR may write to OTG CRC window control register, + * so close it before starting secure_display. + */ + amdgpu_dm_psr_disable(new_acrtc->dm_irq_params.stream); + spin_lock_irq(&adev_to_drm(adev)->event_lock); spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock); if (crc_rd_wrk->crtc) { old_crtc = crc_rd_wrk->crtc; old_acrtc = to_amdgpu_crtc(old_crtc); } - new_acrtc = to_amdgpu_crtc(new_crtc); if (old_crtc && old_crtc != new_crtc) { - old_acrtc->dm_irq_params.crc_window.activated = false; - old_acrtc->dm_irq_params.crc_window.update_win = false; - old_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; + old_acrtc->dm_irq_params.window_param.activated = false; + old_acrtc->dm_irq_params.window_param.update_win = false; + old_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0; - new_acrtc->dm_irq_params.crc_window.activated = true; - new_acrtc->dm_irq_params.crc_window.update_win = true; - new_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; + new_acrtc->dm_irq_params.window_param.activated = true; + new_acrtc->dm_irq_params.window_param.update_win = true; + new_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0; crc_rd_wrk->crtc = new_crtc; } else { - new_acrtc->dm_irq_params.crc_window.activated = true; - new_acrtc->dm_irq_params.crc_window.update_win = true; - new_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; + new_acrtc->dm_irq_params.window_param.activated = true; + new_acrtc->dm_irq_params.window_param.update_win = true; + new_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0; crc_rd_wrk->crtc = new_crtc; } spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock); spin_unlock_irq(&adev_to_drm(adev)->event_lock); + mutex_unlock(&adev->dm.dc_lock); } return 0; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h index 79b5f9999fec..5c9303241aeb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h @@ -39,7 +39,7 @@ struct dm_irq_params { #ifdef CONFIG_DEBUG_FS enum amdgpu_dm_pipe_crc_source crc_src; #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY - struct crc_window_parm crc_window; + struct crc_window_param window_param; #endif #endif }; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 56629197a6a1..58352de24061 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -491,86 +491,79 @@ bool dc_stream_get_crtc_position(struct dc *dc, } #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) -bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream, - struct crc_params *crc_window) +static inline void +dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv, + struct crc_region *roi, struct otg_phy_mux *mux_mapping, bool is_stop) { - int i; - struct dmcu *dmcu = dc->res_pool->dmcu; - struct pipe_ctx *pipe; - struct crc_region tmp_win, *crc_win; - struct otg_phy_mux mapping_tmp, *mux_mapping; - - /*crc window can't be null*/ - if (!crc_window) - return false; - - if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) { - crc_win = &tmp_win; - mux_mapping = &mapping_tmp; - /*set crc window*/ - tmp_win.x_start = crc_window->windowa_x_start; - tmp_win.y_start = crc_window->windowa_y_start; - tmp_win.x_end = crc_window->windowa_x_end; - tmp_win.y_end = crc_window->windowa_y_end; - - for (i = 0; i < MAX_PIPES; i++) { - pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe) - break; - } - - /* Stream not found */ - if (i == MAX_PIPES) - return false; - + union dmub_rb_cmd cmd = {0}; - /*set mux routing info*/ - mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst; - mapping_tmp.otg_output_num = pipe->stream_res.tg->inst; + cmd.secure_display.roi_info.phy_id = mux_mapping->phy_output_num; + cmd.secure_display.roi_info.otg_id = mux_mapping->otg_output_num; - dmcu->funcs->forward_crc_window(dmcu, crc_win, mux_mapping); + if (is_stop) { + cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY; + cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_STOP_UPDATE; } else { - DC_LOG_DC("dmcu is not initialized"); - return false; + cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY; + cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY; + cmd.secure_display.roi_info.x_start = roi->x_start; + cmd.secure_display.roi_info.y_start = roi->y_start; + cmd.secure_display.roi_info.x_end = roi->x_end; + cmd.secure_display.roi_info.y_end = roi->y_end; } - return true; + dc_dmub_srv_cmd_queue(dmub_srv, &cmd); + dc_dmub_srv_cmd_execute(dmub_srv); } -bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc, struct dc_stream_state *stream) +static inline void +dc_stream_forward_dmcu_crc_window(struct dmcu *dmcu, + struct crc_region *roi, struct otg_phy_mux *mux_mapping, bool is_stop) { - int i; - struct dmcu *dmcu = dc->res_pool->dmcu; - struct pipe_ctx *pipe; - struct otg_phy_mux mapping_tmp, *mux_mapping; + if (is_stop) + dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping); + else + dmcu->funcs->forward_crc_window(dmcu, roi, mux_mapping); +} - if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) { - mux_mapping = &mapping_tmp; +bool +dc_stream_forward_crc_window(struct dc *dc, + struct crc_region *roi, struct dc_stream_state *stream, bool is_stop) +{ + struct dmcu *dmcu; + struct dc_dmub_srv *dmub_srv; + struct otg_phy_mux mux_mapping; + struct pipe_ctx *pipe; + int i; - for (i = 0; i < MAX_PIPES; i++) { - pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe) - break; - } + for (i = 0; i < MAX_PIPES; i++) { + pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe) + break; + } - /* Stream not found */ - if (i == MAX_PIPES) - return false; + /* Stream not found */ + if (i == MAX_PIPES) + return false; + mux_mapping.phy_output_num = stream->link->link_enc_hw_inst; + mux_mapping.otg_output_num = pipe->stream_res.tg->inst; - /*set mux routing info*/ - mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst; - mapping_tmp.otg_output_num = pipe->stream_res.tg->inst; + dmcu = dc->res_pool->dmcu; + dmub_srv = dc->ctx->dmub_srv; - dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping); - } else { - DC_LOG_DC("dmcu is not initialized"); + /* forward to dmub */ + if (dmub_srv) + dc_stream_forward_dmub_crc_window(dmub_srv, roi, &mux_mapping, is_stop); + /* forward to dmcu */ + else if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) + dc_stream_forward_dmcu_crc_window(dmcu, roi, &mux_mapping, is_stop); + else return false; - } return true; } -#endif +#endif /* CONFIG_DRM_AMD_SECURE_DISPLAY */ /** * dc_stream_configure_crc() - Configure CRC capture for the given stream. diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 73dccd485895..26f8f18e675c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -521,10 +521,10 @@ bool dc_stream_get_crtc_position(struct dc *dc, unsigned int *nom_v_pos); #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) -bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream, - struct crc_params *crc_window); -bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc, - struct dc_stream_state *stream); +bool dc_stream_forward_crc_window(struct dc *dc, + struct crc_region *roi, + struct dc_stream_state *stream, + bool is_stop); #endif bool dc_stream_configure_crc(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index ad9041472cca..27dd4304ce69 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -993,4 +993,18 @@ struct display_endpoint_id { enum display_endpoint_type ep_type; }; +#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) +struct crc_region { + uint16_t x_start; + uint16_t y_start; + uint16_t x_end; + uint16_t y_end; +}; + +struct otg_phy_mux { + uint8_t phy_output_num; + uint8_t otg_output_num; +}; +#endif + #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 8df2765cce78..9a2432608ddf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -56,20 +56,6 @@ struct dmcu { bool auto_load_dmcu; }; -#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) -struct crc_region { - uint16_t x_start; - uint16_t y_start; - uint16_t x_end; - uint16_t y_end; -}; - -struct otg_phy_mux { - uint8_t phy_output_num; - uint8_t otg_output_num; -}; -#endif - struct dmcu_funcs { bool (*dmcu_init)(struct dmcu *dmcu); bool (*load_iram)(struct dmcu *dmcu, diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 7a8f61517424..dc7c4d74cb5d 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -729,6 +729,10 @@ enum dmub_cmd_type { /** * Command type used for all VBIOS interface commands. */ + /** + * Command type used for all SECURE_DISPLAY commands. + */ + DMUB_CMD__SECURE_DISPLAY = 85, /** * Command type used to set DPIA HPD interrupt state @@ -3143,6 +3147,24 @@ struct dmub_rb_cmd_get_usbc_cable_id { } data; }; +enum dmub_cmd_secure_display_type { + DMUB_CMD__SECURE_DISPLAY_TEST_CMD = 0, + DMUB_CMD__SECURE_DISPLAY_CRC_STOP_UPDATE, + DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY +}; + +struct dmub_rb_cmd_secure_display { + struct dmub_cmd_header header; + struct dmub_cmd_roi_info { + uint16_t x_start; + uint16_t x_end; + uint16_t y_start; + uint16_t y_end; + uint8_t otg_id; + uint8_t phy_id; + } roi_info; +}; + /** * union dmub_rb_cmd - DMUB inbox command. */ @@ -3347,6 +3369,10 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__QUERY_HPD_STATE command. */ struct dmub_rb_cmd_query_hpd_state query_hpd; + /** + * Definition of a DMUB_CMD__SECURE_DISPLAY command. + */ + struct dmub_rb_cmd_secure_display secure_display; /** * Definition of a DMUB_CMD__DPIA_HPD_INT_ENABLE command. */ -- cgit v1.2.3 From 62fa035b5605a993fa3b4526af8b6ed145e3ce1b Mon Sep 17 00:00:00 2001 From: Alan Liu Date: Thu, 20 Oct 2022 11:46:43 -0400 Subject: drm/amd/display: Drop struct crc_region and reuse struct rect [Why] reuse struct rect rather than adding a new struct. [How] - Userspace keeps inputting x_start, y_start, x_end, y_end - We translate data to x, y, width, height in code flow to store - translate back to x_start, y_start, x_end, y_end before programming HW Tested-by: Mark Broadworth Reviewed-by: Wayne Lin Acked-by: Rodrigo Siqueira Signed-off-by: Alan Liu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 20 +++++++++++--------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 7 +++++-- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 16 ++++++++-------- drivers/gpu/drm/amd/display/dc/core/dc.c | 20 ++++++++++---------- drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 7 ------- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 14 ++++++++++---- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 2 +- 8 files changed, 46 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index a857f6454753..fb077e9af99f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -89,10 +89,10 @@ static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.window_param.roi.x_start = 0; - acrtc->dm_irq_params.window_param.roi.y_start = 0; - acrtc->dm_irq_params.window_param.roi.x_end = 0; - acrtc->dm_irq_params.window_param.roi.y_end = 0; + acrtc->dm_irq_params.window_param.x_start = 0; + acrtc->dm_irq_params.window_param.y_start = 0; + acrtc->dm_irq_params.window_param.x_end = 0; + acrtc->dm_irq_params.window_param.y_end = 0; acrtc->dm_irq_params.window_param.activated = false; acrtc->dm_irq_params.window_param.update_win = false; acrtc->dm_irq_params.window_param.skip_frame_cnt = 0; @@ -145,7 +145,7 @@ amdgpu_dm_forward_crc_window(struct work_struct *work) dm = crc_fw_wrk->dm; mutex_lock(&dm->dc_lock); - dc_stream_forward_crc_window(dm->dc, &crc_fw_wrk->roi, crc_fw_wrk->stream, crc_fw_wrk->is_stop_cmd); + dc_stream_forward_crc_window(dm->dc, &crc_fw_wrk->rect, crc_fw_wrk->stream, crc_fw_wrk->is_stop_cmd); mutex_unlock(&dm->dc_lock); kfree(crc_fw_wrk); @@ -496,10 +496,12 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) INIT_WORK(&crc_fw_wrk->forward_roi_work, amdgpu_dm_forward_crc_window); crc_fw_wrk->dm = &adev->dm; crc_fw_wrk->stream = stream_state; - crc_fw_wrk->roi.x_start = acrtc->dm_irq_params.window_param.roi.x_start; - crc_fw_wrk->roi.y_start = acrtc->dm_irq_params.window_param.roi.y_start; - crc_fw_wrk->roi.x_end = acrtc->dm_irq_params.window_param.roi.x_end; - crc_fw_wrk->roi.y_end = acrtc->dm_irq_params.window_param.roi.y_end; + crc_fw_wrk->rect.x = acrtc->dm_irq_params.window_param.x_start; + crc_fw_wrk->rect.y = acrtc->dm_irq_params.window_param.y_start; + crc_fw_wrk->rect.width = acrtc->dm_irq_params.window_param.x_end - + acrtc->dm_irq_params.window_param.x_start; + crc_fw_wrk->rect.height = acrtc->dm_irq_params.window_param.y_end - + acrtc->dm_irq_params.window_param.y_start; schedule_work(&crc_fw_wrk->forward_roi_work); acrtc->dm_irq_params.window_param.update_win = false; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h index 16bfc2dc35ab..71bce608d751 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h @@ -41,7 +41,10 @@ enum amdgpu_dm_pipe_crc_source { #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY struct crc_window_param { - struct crc_region roi; + uint16_t x_start; + uint16_t y_start; + uint16_t x_end; + uint16_t y_end; /* CRC windwo is activated or not*/ bool activated; /* Update crc window during vertical blank or not */ @@ -64,7 +67,7 @@ struct crc_fw_work { struct work_struct forward_roi_work; struct amdgpu_display_manager *dm; struct dc_stream_state *stream; - struct crc_region roi; + struct rect rect; bool is_stop_cmd; }; #endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 8f5b98df26db..2c43cdd2e707 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -3085,7 +3085,7 @@ static int crc_win_x_start_set(void *data, u64 val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.window_param.roi.x_start = (uint16_t) val; + acrtc->dm_irq_params.window_param.x_start = (uint16_t) val; acrtc->dm_irq_params.window_param.update_win = false; spin_unlock_irq(&drm_dev->event_lock); @@ -3102,7 +3102,7 @@ static int crc_win_x_start_get(void *data, u64 *val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - *val = acrtc->dm_irq_params.window_param.roi.x_start; + *val = acrtc->dm_irq_params.window_param.x_start; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3122,7 +3122,7 @@ static int crc_win_y_start_set(void *data, u64 val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.window_param.roi.y_start = (uint16_t) val; + acrtc->dm_irq_params.window_param.y_start = (uint16_t) val; acrtc->dm_irq_params.window_param.update_win = false; spin_unlock_irq(&drm_dev->event_lock); @@ -3139,7 +3139,7 @@ static int crc_win_y_start_get(void *data, u64 *val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - *val = acrtc->dm_irq_params.window_param.roi.y_start; + *val = acrtc->dm_irq_params.window_param.y_start; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3158,7 +3158,7 @@ static int crc_win_x_end_set(void *data, u64 val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.window_param.roi.x_end = (uint16_t) val; + acrtc->dm_irq_params.window_param.x_end = (uint16_t) val; acrtc->dm_irq_params.window_param.update_win = false; spin_unlock_irq(&drm_dev->event_lock); @@ -3175,7 +3175,7 @@ static int crc_win_x_end_get(void *data, u64 *val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - *val = acrtc->dm_irq_params.window_param.roi.x_end; + *val = acrtc->dm_irq_params.window_param.x_end; spin_unlock_irq(&drm_dev->event_lock); return 0; @@ -3194,7 +3194,7 @@ static int crc_win_y_end_set(void *data, u64 val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - acrtc->dm_irq_params.window_param.roi.y_end = (uint16_t) val; + acrtc->dm_irq_params.window_param.y_end = (uint16_t) val; acrtc->dm_irq_params.window_param.update_win = false; spin_unlock_irq(&drm_dev->event_lock); @@ -3211,7 +3211,7 @@ static int crc_win_y_end_get(void *data, u64 *val) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); spin_lock_irq(&drm_dev->event_lock); - *val = acrtc->dm_irq_params.window_param.roi.y_end; + *val = acrtc->dm_irq_params.window_param.y_end; spin_unlock_irq(&drm_dev->event_lock); return 0; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 58352de24061..20c16ca935f7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -493,7 +493,7 @@ bool dc_stream_get_crtc_position(struct dc *dc, #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) static inline void dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv, - struct crc_region *roi, struct otg_phy_mux *mux_mapping, bool is_stop) + struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop) { union dmub_rb_cmd cmd = {0}; @@ -506,10 +506,10 @@ dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv, } else { cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY; cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY; - cmd.secure_display.roi_info.x_start = roi->x_start; - cmd.secure_display.roi_info.y_start = roi->y_start; - cmd.secure_display.roi_info.x_end = roi->x_end; - cmd.secure_display.roi_info.y_end = roi->y_end; + cmd.secure_display.roi_info.x_start = rect->x; + cmd.secure_display.roi_info.y_start = rect->y; + cmd.secure_display.roi_info.x_end = rect->x + rect->width; + cmd.secure_display.roi_info.y_end = rect->y + rect->height; } dc_dmub_srv_cmd_queue(dmub_srv, &cmd); @@ -518,17 +518,17 @@ dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv, static inline void dc_stream_forward_dmcu_crc_window(struct dmcu *dmcu, - struct crc_region *roi, struct otg_phy_mux *mux_mapping, bool is_stop) + struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop) { if (is_stop) dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping); else - dmcu->funcs->forward_crc_window(dmcu, roi, mux_mapping); + dmcu->funcs->forward_crc_window(dmcu, rect, mux_mapping); } bool dc_stream_forward_crc_window(struct dc *dc, - struct crc_region *roi, struct dc_stream_state *stream, bool is_stop) + struct rect *rect, struct dc_stream_state *stream, bool is_stop) { struct dmcu *dmcu; struct dc_dmub_srv *dmub_srv; @@ -554,10 +554,10 @@ dc_stream_forward_crc_window(struct dc *dc, /* forward to dmub */ if (dmub_srv) - dc_stream_forward_dmub_crc_window(dmub_srv, roi, &mux_mapping, is_stop); + dc_stream_forward_dmub_crc_window(dmub_srv, rect, &mux_mapping, is_stop); /* forward to dmcu */ else if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) - dc_stream_forward_dmcu_crc_window(dmcu, roi, &mux_mapping, is_stop); + dc_stream_forward_dmcu_crc_window(dmcu, rect, &mux_mapping, is_stop); else return false; diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 26f8f18e675c..4d30ae0ca721 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -522,7 +522,7 @@ bool dc_stream_get_crtc_position(struct dc *dc, #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) bool dc_stream_forward_crc_window(struct dc *dc, - struct crc_region *roi, + struct rect *rect, struct dc_stream_state *stream, bool is_stop); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 27dd4304ce69..dc78e2404b48 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -994,13 +994,6 @@ struct display_endpoint_id { }; #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) -struct crc_region { - uint16_t x_start; - uint16_t y_start; - uint16_t x_end; - uint16_t y_end; -}; - struct otg_phy_mux { uint8_t phy_output_num; uint8_t otg_output_num; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index fbb19e253f50..d3cc5ec46956 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -927,19 +927,20 @@ static bool dcn10_recv_edid_cea_ack(struct dmcu *dmcu, int *offset) #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) static void dcn10_forward_crc_window(struct dmcu *dmcu, - struct crc_region *crc_win, + struct rect *rect, struct otg_phy_mux *mux_mapping) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); unsigned int dmcu_max_retry_on_wait_reg_ready = 801; unsigned int dmcu_wait_reg_ready_interval = 100; unsigned int crc_start = 0, crc_end = 0, otg_phy_mux = 0; + int x_start, y_start, x_end, y_end; /* If microcontroller is not running, do nothing */ if (dmcu->dmcu_state != DMCU_RUNNING) return; - if (!crc_win) + if (!rect) return; /* waitDMCUReadyForCmd */ @@ -947,9 +948,14 @@ static void dcn10_forward_crc_window(struct dmcu *dmcu, dmcu_wait_reg_ready_interval, dmcu_max_retry_on_wait_reg_ready); + x_start = rect->x; + y_start = rect->y; + x_end = x_start + rect->width; + y_end = y_start + rect->height; + /* build up nitification data */ - crc_start = (((unsigned int) crc_win->x_start) << 16) | crc_win->y_start; - crc_end = (((unsigned int) crc_win->x_end) << 16) | crc_win->y_end; + crc_start = (((unsigned int) x_start) << 16) | y_start; + crc_end = (((unsigned int) x_end) << 16) | y_end; otg_phy_mux = (((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 9a2432608ddf..de3113ecbc77 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -86,7 +86,7 @@ struct dmcu_funcs { bool (*recv_edid_cea_ack)(struct dmcu *dmcu, int *offset); #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) void (*forward_crc_window)(struct dmcu *dmcu, - struct crc_region *crc_win, + struct rect *rect, struct otg_phy_mux *mux_mapping); void (*stop_crc_win_update)(struct dmcu *dmcu, struct otg_phy_mux *mux_mapping); -- cgit v1.2.3 From f7f697403f2067ddbeff3344a4c2d20ff44ace79 Mon Sep 17 00:00:00 2001 From: Jun Lei Date: Thu, 20 Oct 2022 11:46:44 -0400 Subject: drm/amd/display: Limit dcn32 to 1950Mhz display clock [why] Hardware team recommends we limit dispclock to 1950Mhz for all DCN3.2.x [how] Limit to 1950 when initializing clocks. Tested-by: Mark Broadworth Reviewed-by: Alvin Lee Acked-by: Rodrigo Siqueira Signed-off-by: Jun Lei Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index 1c612ccf1944..fd0313468fdb 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -157,6 +157,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); unsigned int num_levels; struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk; + unsigned int i; memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks)); clk_mgr_base->clks.p_state_change_support = true; @@ -205,18 +206,17 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) clk_mgr->dpm_present = true; if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) { - unsigned int i; - for (i = 0; i < num_levels; i++) if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz)) clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz = khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz); } + for (i = 0; i < num_levels; i++) + if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz > 1950) + clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz = 1950; if (clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz) { - unsigned int i; - for (i = 0; i < num_levels; i++) if (clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz)) -- cgit v1.2.3 From 1fb695d9e67d86c28f888b22d246c4333afa8a71 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 20 Oct 2022 11:46:45 -0400 Subject: drm/amd/display: Document part of the DMUB cmd Add a simple documentation in the dmub_cmd. Tested-by: Mark Broadworth Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index dc7c4d74cb5d..bc9344af1995 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -729,6 +729,7 @@ enum dmub_cmd_type { /** * Command type used for all VBIOS interface commands. */ + /** * Command type used for all SECURE_DISPLAY commands. */ @@ -3147,14 +3148,23 @@ struct dmub_rb_cmd_get_usbc_cable_id { } data; }; +/** + * Command type of a DMUB_CMD__SECURE_DISPLAY command + */ enum dmub_cmd_secure_display_type { - DMUB_CMD__SECURE_DISPLAY_TEST_CMD = 0, + DMUB_CMD__SECURE_DISPLAY_TEST_CMD = 0, /* test command to only check if inbox message works */ DMUB_CMD__SECURE_DISPLAY_CRC_STOP_UPDATE, DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY }; +/** + * Definition of a DMUB_CMD__SECURE_DISPLAY command + */ struct dmub_rb_cmd_secure_display { struct dmub_cmd_header header; + /** + * Data passed from driver to dmub firmware. + */ struct dmub_cmd_roi_info { uint16_t x_start; uint16_t x_end; @@ -3373,6 +3383,7 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__SECURE_DISPLAY command. */ struct dmub_rb_cmd_secure_display secure_display; + /** * Definition of a DMUB_CMD__DPIA_HPD_INT_ENABLE command. */ -- cgit v1.2.3 From 5384d0e2b0e6afc717a523420a4b30e96dc9a99b Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Thu, 20 Oct 2022 11:46:46 -0400 Subject: drm/amd/display: 3.2.208 DC version 3.2.208 brings along the following: * Add more kernel doc * Enable secure display on DCN21 * Limit dcn32 to 1950Mhz display clock * PSR code refactor * Rework audio stream sequence * Generic bug fixes Tested-by: Mark Broadworth Acked-by: Rodrigo Siqueira Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e4e41f2e5054..3450aca538b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.207" +#define DC_VER "3.2.208" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From 4fd8575dc59c2e725c38f55f8167be9df1040ef9 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 20 Oct 2022 11:46:47 -0400 Subject: drm/amd/display: Update latencies on DCN321 Update DF related latencies based on new measurements. Tested-by: Mark Broadworth Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Dillon Varone Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index dd90f241e906..7352f7514410 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -119,15 +119,15 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_21_soc = { }, }, .num_states = 1, - .sr_exit_time_us = 12.36, - .sr_enter_plus_exit_time_us = 16.72, + .sr_exit_time_us = 19.95, + .sr_enter_plus_exit_time_us = 24.36, .sr_exit_z8_time_us = 285.0, .sr_enter_plus_exit_z8_time_us = 320, .writeback_latency_us = 12.0, .round_trip_ping_latency_dcfclk_cycles = 263, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, + .urgent_latency_pixel_data_only_us = 9.35, + .urgent_latency_pixel_mixed_with_vm_data_us = 9.35, + .urgent_latency_vm_data_only_us = 9.35, .fclk_change_latency_us = 20, .usr_retraining_latency_us = 2, .smn_latency_us = 2, -- cgit v1.2.3 From 33151fb787692edf8275120435c8cc41bfe0cf63 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 20 Oct 2022 11:46:48 -0400 Subject: drm/amd/display: Set memclk levels to be at least 1 for dcn32 [Why] Cannot report 0 memclk levels even when SMU does not provide any. [How] When memclk levels reported by SMU is 0, set levels to 1. Tested-by: Mark Broadworth Reviewed-by: Martin Leung Acked-by: Rodrigo Siqueira Signed-off-by: Dillon Varone Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index fd0313468fdb..6f77d8e538ab 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -669,6 +669,9 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) &clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz, &num_entries_per_clk->num_memclk_levels); + /* memclk must have at least one level */ + num_entries_per_clk->num_memclk_levels = num_entries_per_clk->num_memclk_levels ? num_entries_per_clk->num_memclk_levels : 1; + dcn32_init_single_clock(clk_mgr, PPCLK_FCLK, &clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz, &num_entries_per_clk->num_fclk_levels); -- cgit v1.2.3 From 3442f4e0e55555d14b099c17382453fdfd2508d5 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 20 Oct 2022 11:46:49 -0400 Subject: drm/amd/display: Remove optimization for VRR updates Optimization caused unexpected regression, so remove for now. Tested-by: Mark Broadworth Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 20c16ca935f7..f6776ccf7a0e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -401,9 +401,6 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, { int i; - if (memcmp(adjust, &stream->adjust, sizeof(struct dc_crtc_timing_adjust)) == 0) - return true; - stream->adjust.v_total_max = adjust->v_total_max; stream->adjust.v_total_mid = adjust->v_total_mid; stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; -- cgit v1.2.3 From 35fe1915eebde4546cea5fd4e86e76f47d7b5dae Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 20 Oct 2022 11:46:50 -0400 Subject: drm/amd/display: Fix HDCP 1.X 1A-04 failing [Why] On some linux based OS, the hotplug->HDCP start takes longer than 4seconds (by ~100ms) This is due to the HDCP delay (3 sec) so we only have 1 second to hotplug->stream enablement, which is not enough for certain OS configs. [How] Change the Delay to 0 seconds. From testing it seems like 0 Seconds can pass 1.x and 2.x compliances Tested-by: Mark Broadworth Reviewed-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 6202e31c7e3a..a7fd98f57f94 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -495,7 +495,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) link->dp.mst_enabled = config->mst_enabled; link->dp.usb4_enabled = config->usb4_enabled; display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION; - link->adjust.auth_delay = 3; + link->adjust.auth_delay = 0; link->adjust.hdcp1.disable = 0; conn_state = aconnector->base.state; -- cgit v1.2.3 From 6894534b56059f68a96a3fcf357e15671de0d24e Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 20 Oct 2022 11:46:51 -0400 Subject: drm/amd/display: Enable timing sync on DCN32 Missed enabling timing sync on DCN32 because DCN32 has a different DML param. Tested-by: Mark Broadworth Reviewed-by: Martin Leung Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index ec2eae99b892..602e885ed52c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -1228,6 +1228,7 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.src.dcc = false; pipes[pipe_cnt].pipe.src.dcc_rate = 1; pipes[pipe_cnt].pipe.dest.synchronized_vblank_all_planes = synchronized_vblank; + pipes[pipe_cnt].pipe.dest.synchronize_timings = synchronized_vblank; pipes[pipe_cnt].pipe.dest.hblank_start = timing->h_total - timing->h_front_porch; pipes[pipe_cnt].pipe.dest.hblank_end = pipes[pipe_cnt].pipe.dest.hblank_start - timing->h_addressable -- cgit v1.2.3 From c3575dd201895aa5cbb50712e3879a650cde9eb4 Mon Sep 17 00:00:00 2001 From: Max Tseng Date: Thu, 20 Oct 2022 11:46:52 -0400 Subject: drm/amd/display: cursor update command incomplete Missing send cursor_rect width & Height into DMUB. PSR-SU would use these information. But missing these assignment in last refactor commit Tested-by: Mark Broadworth Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Max Tseng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index 4996d2810edb..938dba5249d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -623,6 +623,10 @@ void hubp2_cursor_set_attributes( hubp->att.size.bits.width = attr->width; hubp->att.size.bits.height = attr->height; hubp->att.cur_ctl.bits.mode = attr->color_format; + + hubp->cur_rect.w = attr->width; + hubp->cur_rect.h = attr->height; + hubp->att.cur_ctl.bits.pitch = hw_pitch; hubp->att.cur_ctl.bits.line_per_chunk = lpc; hubp->att.cur_ctl.bits.cur_2x_magnify = attr->attribute_flags.bits.ENABLE_MAGNIFICATION; -- cgit v1.2.3 From 6bf20b9ba7863ecfa14f5b4171f719256b787b34 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Thu, 20 Oct 2022 11:46:53 -0400 Subject: drm/amd/display: Fix SDR visual confirm Apply SDR visual confirm to RGB10 and FP16 formats as well when needed. Tested-by: Mark Broadworth Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 7c2e3b8dc26a..471078fc3900 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -366,6 +366,7 @@ void get_hdr_visual_confirm_color( struct tg_color *color) { uint32_t color_value = MAX_TG_COLOR_VALUE; + bool is_sdr = false; /* Determine the overscan color based on the top-most (desktop) plane's context */ struct pipe_ctx *top_pipe_ctx = pipe_ctx; @@ -382,7 +383,8 @@ void get_hdr_visual_confirm_color( /* FreeSync 2 ARGB2101010 - set border color to pink */ color->color_r_cr = color_value; color->color_b_cb = color_value; - } + } else + is_sdr = true; break; case PIXEL_FORMAT_FP16: if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { @@ -391,14 +393,19 @@ void get_hdr_visual_confirm_color( } else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { /* FreeSync 2 HDR - set border color to green */ color->color_g_y = color_value; - } + } else + is_sdr = true; break; default: + is_sdr = true; + break; + } + + if (is_sdr) { /* SDR - set border color to Gray */ color->color_r_cr = color_value/2; color->color_b_cb = color_value/2; color->color_g_y = color_value/2; - break; } } -- cgit v1.2.3 From 203ccaf586446b578909de1b763278033fb74b51 Mon Sep 17 00:00:00 2001 From: Haiyi Zhou Date: Thu, 20 Oct 2022 11:46:54 -0400 Subject: drm/amd/display: wait for vblank during pipe programming [WHY] Skipping vblank during global sync update request can result in underflow on certain displays. [HOW] Roll back to the previous behavior where DC waits for vblank during pipe programming. Fixes: 5d3e14421410 ("drm/amd/display: do not wait for vblank during pipe programming") Tested-by: Mark Broadworth Reviewed-by: Martin Leung Acked-by: Rodrigo Siqueira Signed-off-by: Haiyi Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 1ac0ed5be605..feff834d5410 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1640,10 +1640,8 @@ static void dcn20_program_pipe( pipe_ctx->pipe_dlg_param.vupdate_width); if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { - pipe_ctx->stream_res.tg->funcs->wait_for_state( - pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); - pipe_ctx->stream_res.tg->funcs->wait_for_state( - pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); } pipe_ctx->stream_res.tg->funcs->set_vtg_params( -- cgit v1.2.3 From 1e8fd864afdc7a52df375e888a03b8472fc24f5d Mon Sep 17 00:00:00 2001 From: zhikzhai Date: Thu, 20 Oct 2022 11:46:55 -0400 Subject: drm/amd/display: skip commit minimal transition state [WHY] Now dynamic ODM will now be disabled when MPO is required safe transitions to avoid underflow, but we are triggering the way of minimal transition too often. Commit state of dc with no check will do pipeline setup which may re-initialize the component with no need such as audio. [HOW] Just do the minimal transition when all of pipes are in use, otherwise return true to skip. Tested-by: Mark Broadworth Reviewed-by: Dillon Varone Acked-by: Rodrigo Siqueira Signed-off-by: zhikzhai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f6776ccf7a0e..945b5210fba4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3738,10 +3738,32 @@ static bool commit_minimal_transition_state(struct dc *dc, bool temp_subvp_policy; enum dc_status ret = DC_ERROR_UNEXPECTED; unsigned int i, j; + unsigned int pipe_in_use = 0; if (!transition_context) return false; + /* check current pipes in use*/ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i]; + + if (pipe->plane_state) + pipe_in_use++; + } + + /* When the OS add a new surface if we have been used all of pipes with odm combine + * and mpc split feature, it need use commit_minimal_transition_state to transition safely. + * After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need + * call it again. Otherwise return true to skip. + * + * Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially + * enter/exit MPO when DCN still have enough resources. + */ + if (pipe_in_use != dc->res_pool->pipe_count) { + dc_release_state(transition_context); + return true; + } + if (!dc->config.is_vmin_only_asic) { tmp_mpc_policy = dc->debug.pipe_split_policy; dc->debug.pipe_split_policy = MPC_SPLIT_AVOID; -- cgit v1.2.3 From b1a98cf89a695d36c414653634ea7ba91b6e701f Mon Sep 17 00:00:00 2001 From: Ma Hanghong Date: Thu, 20 Oct 2022 11:46:56 -0400 Subject: drm/amd/display: Wrong colorimetry workaround [Why] For FreeSync HDR, native color space flag in AMD VSIF(BT.709) should be used when intepreting content and color space flag in VSC or AVI infoFrame should be ignored. However, it turned out some userspace application still use color flag in VSC or AVI infoFrame which is incorrect. [How] Transfer function is used when building the VSC and AVI infoFrame. Set colorimetry to BT.709 when all the following match: 1. Pixel format is YCbCr; 2. In FreeSync 2 HDR, color is COLOR_SPACE_2020_YCBCR; 3. Transfer function is TRANSFER_FUNC_GAMMA_22; Tested-by: Mark Broadworth Reviewed-by: Krunoslav Kovac Acked-by: Rodrigo Siqueira Signed-off-by: Ma Hanghong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ++++- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 6 ++++++ drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h | 3 ++- drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c | 6 +++++- 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 72aede3fcf9b..d14e57b19066 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5697,6 +5697,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false; int mode_refresh; int preferred_refresh = 0; + enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN; #if defined(CONFIG_DRM_AMD_DC_DCN) struct dsc_dec_dpcd_caps dsc_caps; #endif @@ -5820,7 +5821,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) stream->use_vsc_sdp_for_colorimetry = true; } - mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space); + if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) + tf = TRANSFER_FUNC_GAMMA_22; + mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf); aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ba2d4347f722..d99f1c4b9584 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -3015,6 +3015,12 @@ static void set_avi_info_frame( hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; } + if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR && + stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { + hdmi_info.bits.EC0_EC2 = 0; + hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; + } + /* TODO: un-hardcode aspect ratio */ aspect = stream->timing.aspect_ratio; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h index 1d8b746b02f2..edf5845f6a1f 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h @@ -35,7 +35,8 @@ struct mod_vrr_params; void mod_build_vsc_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet, - enum dc_color_space cs); + enum dc_color_space cs, + enum color_transfer_func tf); void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet); diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 27ceba9d6d65..69691058ab89 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -132,7 +132,8 @@ enum ColorimetryYCCDP { void mod_build_vsc_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet, - enum dc_color_space cs) + enum dc_color_space cs, + enum color_transfer_func tf) { unsigned int vsc_packet_revision = vsc_packet_undefined; unsigned int i; @@ -382,6 +383,9 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, colorimetryFormat = ColorimetryYCC_DP_AdobeYCC; else if (cs == COLOR_SPACE_2020_YCBCR) colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr; + + if (cs == COLOR_SPACE_2020_YCBCR && tf == TRANSFER_FUNC_GAMMA_22) + colorimetryFormat = ColorimetryYCC_DP_ITU709; break; default: -- cgit v1.2.3 From 1682bd1a6b5fb094e914d9b73b711821fd84dcbd Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 20 Oct 2022 11:46:57 -0400 Subject: drm/amd/display: Expand kernel doc for DC This commit adds extra documentation for elements related to FAMs. Tested-by: Mark Broadworth Reviewed-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 19 +++++++++++++--- drivers/gpu/drm/amd/display/dc/dc_stream.h | 11 ++++++++++ drivers/gpu/drm/amd/display/dc/dml/dc_features.h | 7 ++++++ .../drm/amd/display/dc/dml/display_mode_enums.h | 25 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/dml/display_mode_vba.h | 9 ++++++++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 7 ++++++ drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 7 ++++++ 7 files changed, 82 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3450aca538b5..44f8db160520 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -494,9 +494,12 @@ enum dcn_zstate_support_state { DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY, DCN_ZSTATE_SUPPORT_DISALLOW, }; -/* - * For any clocks that may differ per pipe - * only the max is stored in this structure + +/** + * dc_clocks - DC pipe clocks + * + * For any clocks that may differ per pipe only the max is stored in this + * structure */ struct dc_clocks { int dispclk_khz; @@ -523,6 +526,16 @@ struct dc_clocks { bool prev_p_state_change_support; bool fclk_prev_p_state_change_support; int num_ways; + + /** + * @fw_based_mclk_switching + * + * DC has a mechanism that leverage the variable refresh rate to switch + * memory clock in cases that we have a large latency to achieve the + * memory clock change and a short vblank window. DC has some + * requirements to enable this feature, and this field describes if the + * system support or not such a feature. + */ bool fw_based_mclk_switching; bool fw_based_mclk_switching_shut_down; int prev_num_ways; diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 4d30ae0ca721..f4dfd3a49b68 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -201,7 +201,18 @@ struct dc_stream_state { bool use_vsc_sdp_for_colorimetry; bool ignore_msa_timing_param; + /** + * @allow_freesync: + * + * It say if Freesync is enabled or not. + */ bool allow_freesync; + + /** + * @vrr_active_variable: + * + * It describes if VRR is in use. + */ bool vrr_active_variable; bool freesync_on_desktop; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h index 74e86732e301..2cbdd75429ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h @@ -29,6 +29,13 @@ #define DC__PRESENT 1 #define DC__PRESENT__1 1 #define DC__NUM_DPP 4 + +/** + * @DC__VOLTAGE_STATES: + * + * Define the maximum amount of states supported by the ASIC. Every ASIC has a + * specific number of states; this macro defines the maximum number of states. + */ #define DC__VOLTAGE_STATES 20 #define DC__NUM_DPP__4 1 #define DC__NUM_DPP__0_PRESENT 1 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index f394b3f3922a..0bffae95f3a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -105,14 +105,39 @@ enum source_macro_tile_size { enum cursor_bpp { dm_cur_2bit = 0, dm_cur_32bit = 1, dm_cur_64bit = 2 }; + +/** + * @enum clock_change_support - It represents possible reasons to change the DRAM clock. + * + * DC may change the DRAM clock during its execution, and this enum tracks all + * the available methods. Note that every ASIC has their specific way to deal + * with these clock switch. + */ enum clock_change_support { + /** + * @dm_dram_clock_change_uninitialized: If you see this, we might have + * a code initialization issue + */ dm_dram_clock_change_uninitialized = 0, + + /** + * @dm_dram_clock_change_vactive: Support DRAM switch in VActive + */ dm_dram_clock_change_vactive, + + /** + * @dm_dram_clock_change_vblank: Support DRAM switch in VBlank + */ dm_dram_clock_change_vblank, + dm_dram_clock_change_vactive_w_mall_full_frame, dm_dram_clock_change_vactive_w_mall_sub_vp, dm_dram_clock_change_vblank_w_mall_full_frame, dm_dram_clock_change_vblank_w_mall_sub_vp, + + /** + * @dm_dram_clock_change_unsupported: Do not support DRAM switch + */ dm_dram_clock_change_unsupported }; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 630f3395e90a..d46aa4817e70 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -419,6 +419,15 @@ struct vba_vars_st { double MinPixelChunkSizeBytes; unsigned int DCCMetaBufferSizeBytes; // Pipe/Plane Parameters + + /** @VoltageLevel: + * Every ASIC has a fixed number of DPM states, and some devices might + * have some particular voltage configuration that does not map + * directly to the DPM states. This field tells how many states the + * target device supports; even though this field combines the DPM and + * special SOC voltages, it mostly matches the total number of DPM + * states. + */ int VoltageLevel; double FabricClock; double DRAMSpeed; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 9498105c98ab..295845d49cb9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -115,6 +115,13 @@ struct resource_funcs { int vlevel); void (*update_soc_for_wm_a)( struct dc *dc, struct dc_state *context); + + /** + * @populate_dml_pipes - Populate pipe data struct + * + * Returns: + * Total of pipes available in the specific ASIC. + */ int (*populate_dml_pipes)( struct dc *dc, struct dc_state *context, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index cd2be729846b..a819f0f97c5f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -35,6 +35,13 @@ ******************************************************************************/ #define MAX_AUDIOS 7 + +/** + * @MAX_PIPES: + * + * Every ASIC support a fixed number of pipes; MAX_PIPES defines a large number + * to be used inside loops and for determining array sizes. + */ #define MAX_PIPES 6 #define MAX_DIG_LINK_ENCODERS 7 #define MAX_DWB_PIPES 1 -- cgit v1.2.3 From 61708a47e84bc458fae9fbc8a9070fb62a9bcf6d Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 20 Oct 2022 11:46:58 -0400 Subject: drm/amd/display: Add DEC/CRB basic doc Add a kernel-doc to the DE-Tile function hook. Tested-by: Mark Broadworth Reviewed-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 15 +++++++++++++++ 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c index 9fbb72369c10..a88a71460521 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c @@ -41,6 +41,10 @@ #define FN(reg_name, field_name) \ hubbub2->shifts->field_name, hubbub2->masks->field_name +/** + * @DCN32_CRB_SEGMENT_SIZE_KB: Maximum Configurable Return Buffer size for + * DCN32 + */ #define DCN32_CRB_SEGMENT_SIZE_KB 64 static void dcn32_init_crb(struct hubbub *hubbub) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index e7571c6f5ead..58f758fcbce1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -167,6 +167,21 @@ struct hubbub_funcs { void (*force_pstate_change_control)(struct hubbub *hubbub, bool force, bool allow); void (*init_watermarks)(struct hubbub *hubbub); + + /** + * @program_det_size: + * + * DE-Tile buffers (DET) is a memory that is used to convert the tiled + * data into linear, which the rest of the display can use to generate + * the graphics output. One of the main features of this component is + * that each pipe has a configurable DET buffer which means that when a + * pipe is not enabled, the device can assign the memory to other + * enabled pipes to try to be more efficient. + * + * DET logic is handled by dchubbub. Some ASICs provide a feature named + * Configurable Return Buffer (CRB) segments which can be allocated to + * compressed or detiled buffers. + */ void (*program_det_size)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_in_kbyte); void (*program_compbuf_size)(struct hubbub *hubbub, unsigned compbuf_size_kb, bool safe_to_increase); void (*init_crb)(struct hubbub *hubbub); -- cgit v1.2.3 From a6126e14cfb200ecb915c66bccbfc077c704c1fa Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 20 Oct 2022 11:46:59 -0400 Subject: drm/amd/display: Add basic ODM description Add kernel-doc to some of the ODM-related functions. Tested-by: Mark Broadworth Reviewed-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 3 +++ drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 5 +++++ 3 files changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 8224b9bf01d1..d0199ec045cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1454,6 +1454,22 @@ enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ return result; } +/** + * dcn20_split_stream_for_odm - Check if stream can be splited for ODM + * + * @dc: DC object with resource pool info required for pipe split + * @res_ctx: Persistent state of resources + * @prev_odm_pipe: Reference to the previous ODM pipe + * @next_odm_pipe: Reference to the next ODM pipe + * + * This function takes a logically active pipe and a logically free pipe and + * halves all the scaling parameters that need to be halved while populating + * the free pipe with the required resources and configuring the next/previous + * ODM pipe pointers. + * + * Return: + * Return true if split stream for ODM is possible, otherwise, return false. + */ bool dcn20_split_stream_for_odm( const struct dc *dc, struct resource_context *res_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 6b3e6de374bd..42db4b7b79fd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -243,6 +243,9 @@ struct stream_encoder_funcs { uint32_t hubp_requestor_id, enum dynamic_metadata_mode dmdata_mode); + /** + * @dp_set_odm_combine: Sets up DP stream encoder for ODM. + */ void (*dp_set_odm_combine)( struct stream_encoder *enc, bool odm_combine); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 25a1df45b264..65f18f9dad34 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -301,6 +301,11 @@ struct timing_generator_funcs { void (*get_dsc_status)(struct timing_generator *optc, uint32_t *dsc_mode); void (*set_odm_bypass)(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing); + + /** + * @set_odm_combine: Set up the ODM block to read from the correct + * OPP(s) and turn on/off ODM memory. + */ void (*set_odm_combine)(struct timing_generator *optc, int *opp_id, int opp_cnt, struct dc_crtc_timing *timing); void (*set_h_timing_div_manual_mode)(struct timing_generator *optc, bool manual_mode); -- cgit v1.2.3 From fa0fc4fb09b4306ce77093987ee7b84ead697182 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 20 Oct 2022 11:47:00 -0400 Subject: drm/amd/display: Add kernel doc to some of the dc fields Add kernel-doc to some important elements from DC struct that might help to understand DC sequence. Tested-by: Mark Broadworth Reviewed-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 ++- drivers/gpu/drm/amd/display/dc/dc_link.h | 8 +++++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 38 +++++++++++++++++------ 3 files changed, 40 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d99f1c4b9584..7caf3139fabc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2562,9 +2562,12 @@ enum dc_status resource_map_pool_resources( /** * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state - * Is a shallow copy. Increments refcounts on existing streams and planes. + * * @dc: copy out of dc->current_state * @dst_ctx: copy into this + * + * This function makes a shallow copy of the current DC state and increments + * refcounts on existing streams and planes. */ void dc_resource_state_copy_construct_current( const struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 17f080f8af6c..edb4532eaa39 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -166,6 +166,14 @@ struct dc_link { enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */ bool is_hpd_filter_disabled; bool dp_ss_off; + + /** + * @link_state_valid: + * + * If there is no link and local sink, this variable should be set to + * false. Otherwise, it should be set to true; usually, the function + * core_link_enable_stream sets this field to true. + */ bool link_state_valid; bool aux_access_disabled; bool sync_lt_in_progress; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 295845d49cb9..fe34cfde22a6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -514,29 +514,47 @@ struct bw_context { union bw_output bw; struct display_mode_lib dml; }; + /** - * struct dc_state - The full description of a state requested by a user - * - * @streams: Stream properties - * @stream_status: The planes on a given stream - * @res_ctx: Persistent state of resources - * @bw_ctx: The output from bandwidth and watermark calculations and the DML - * @pp_display_cfg: PowerPlay clocks and settings - * @dcn_bw_vars: non-stack memory to support bandwidth calculations - * + * struct dc_state - The full description of a state requested by users */ struct dc_state { + /** + * @streams: Stream state properties + */ struct dc_stream_state *streams[MAX_PIPES]; + + /** + * @stream_status: Planes status on a given stream + */ struct dc_stream_status stream_status[MAX_PIPES]; + + /** + * @stream_count: Total of streams in use + */ uint8_t stream_count; uint8_t stream_mask; + /** + * @res_ctx: Persistent state of resources + */ struct resource_context res_ctx; + /** + * @bw_ctx: The output from bandwidth and watermark calculations and the DML + */ struct bw_context bw_ctx; - /* Note: these are big structures, do *not* put on stack! */ + /** + * @pp_display_cfg: PowerPlay clocks and settings + * Note: this is a big struct, do *not* put on stack! + */ struct dm_pp_display_configuration pp_display_cfg; + + /** + * @dcn_bw_vars: non-stack memory to support bandwidth calculations + * Note: this is a big struct, do *not* put on stack! + */ struct dcn_bw_internal_vars dcn_bw_vars; struct clk_mgr *clk_mgr; -- cgit v1.2.3 From 6a0114e0e31cdf391b96ab347618baa9201c12ad Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 20 Oct 2022 11:47:01 -0400 Subject: drm/amd/display: Add kernel doc for commit sequence Add basic kernel-doc that describes some of the struct and functions that are part of the DC commit sequence.. Tested-by: Mark Broadworth Reviewed-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 63 +++++++++++++++++++---- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 ++++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 16 +++++- 3 files changed, 79 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 945b5210fba4..2858917a66be 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1714,8 +1714,13 @@ void dc_z10_save_init(struct dc *dc) dc->hwss.z10_save_init(dc); } -/* - * Applies given context to HW and copy it into current context. +/** + * dc_commit_state_no_check - Apply context to the hardware + * + * @dc: DC object with the current status to be updated + * @context: New state that will become the current status at the end of this function + * + * Applies given context to the hardware and copy it into current context. * It's up to the user to release the src context afterwards. */ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) @@ -3651,10 +3656,24 @@ static void commit_planes_for_stream(struct dc *dc, } } -/* Determines if the incoming context requires a applying transition state with unnecessary - * pipe splitting and ODM disabled, due to hardware limitations. In a case where - * the OPP associated with an MPCC might change due to plane additions, this function +/** + * could_mpcc_tree_change_for_active_pipes - Check if an OPP associated with MPCC might change + * + * @dc: Used to get the current state status + * @stream: Target stream, which we want to remove the attached planes + * @surface_count: Number of surface update + * @is_plane_addition: [in] Fill out with true if it is a plane addition case + * + * DCN32x and newer support a feature named Dynamic ODM which can conflict with + * the MPO if used simultaneously in some specific configurations (e.g., + * 4k@144). This function checks if the incoming context requires applying a + * transition state with unnecessary pipe splitting and ODM disabled to + * circumvent our hardware limitations to prevent this edge case. If the OPP + * associated with an MPCC might change due to plane additions, this function * returns true. + * + * Return: + * Return true if OPP and MPCC might change, otherwise, return false. */ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, struct dc_stream_state *stream, @@ -3729,6 +3748,24 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, return force_minimal_pipe_splitting; } +/** + * commit_minimal_transition_state - Create a transition pipe split state + * + * @dc: Used to get the current state status + * @transition_base_context: New transition state + * + * In some specific configurations, such as pipe split on multi-display with + * MPO and/or Dynamic ODM, removing a plane may cause unsupported pipe + * programming when moving to new planes. To mitigate those types of problems, + * this function adds a transition state that minimizes pipe usage before + * programming the new configuration. When adding a new plane, the current + * state requires the least pipes, so it is applied without splitting. When + * removing a plane, the new state requires the least pipes, so it is applied + * without splitting. + * + * Return: + * Return false if something is wrong in the transition state. + */ static bool commit_minimal_transition_state(struct dc *dc, struct dc_state *transition_base_context) { @@ -3742,6 +3779,10 @@ static bool commit_minimal_transition_state(struct dc *dc, if (!transition_context) return false; + /* Setup: + * Store the current ODM and MPC config in some temp variables to be + * restored after we commit the transition state. + */ /* check current pipes in use*/ for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -3777,7 +3818,7 @@ static bool commit_minimal_transition_state(struct dc *dc, dc_resource_state_copy_construct(transition_base_context, transition_context); - //commit minimal state + /* commit minimal state */ if (dc->res_pool->funcs->validate_bandwidth(dc, transition_context, false)) { for (i = 0; i < transition_context->stream_count; i++) { struct dc_stream_status *stream_status = &transition_context->stream_status[i]; @@ -3795,10 +3836,12 @@ static bool commit_minimal_transition_state(struct dc *dc, ret = dc_commit_state_no_check(dc, transition_context); } - /*always release as dc_commit_state_no_check retains in good case*/ + /* always release as dc_commit_state_no_check retains in good case */ dc_release_state(transition_context); - /*restore previous pipe split and odm policy*/ + /* TearDown: + * Restore original configuration for ODM and MPO. + */ if (!dc->config.is_vmin_only_asic) dc->debug.pipe_split_policy = tmp_mpc_policy; @@ -3806,12 +3849,12 @@ static bool commit_minimal_transition_state(struct dc *dc, dc->debug.force_disable_subvp = temp_subvp_policy; if (ret != DC_OK) { - /*this should never happen*/ + /* this should never happen */ BREAK_TO_DEBUGGER(); return false; } - /*force full surface update*/ + /* force full surface update */ for (i = 0; i < dc->current_state->stream_count; i++) { for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) { dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7caf3139fabc..da164685547d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1768,6 +1768,17 @@ bool dc_remove_plane_from_context( return true; } +/** + * dc_rem_all_planes_for_stream - Remove planes attached to the target stream. + * + * @dc: Current dc state. + * @stream: Target stream, which we want to remove the attached plans. + * @context: New context. + * + * Return: + * Return true if DC was able to remove all planes from the target + * stream, otherwise, return false. + */ bool dc_rem_all_planes_for_stream( const struct dc *dc, struct dc_stream_state *stream, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index fe34cfde22a6..85495ef026f5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -420,7 +420,10 @@ struct pipe_ctx { struct pll_settings pll_settings; - /* link config records software decision for what link config should be + /** + * @link_config: + * + * link config records software decision for what link config should be * enabled given current link capability and stream during hw resource * mapping. This is to decouple the dependency on link capability during * dc commit or update. @@ -542,6 +545,10 @@ struct dc_state { /** * @bw_ctx: The output from bandwidth and watermark calculations and the DML + * + * Each context must have its own instance of VBA, and in order to + * initialize and obtain IP and SOC, the base DML instance from DC is + * initially copied into every context. */ struct bw_context bw_ctx; @@ -559,6 +566,13 @@ struct dc_state { struct clk_mgr *clk_mgr; + /** + * @refcount: refcount reference + * + * Notice that dc_state is used around the code to capture the current + * context, so we need to pass it everywhere. That's why we want to use + * kref in this struct. + */ struct kref refcount; struct { -- cgit v1.2.3 From 887e8cec55f20c39e14e04eb5f8a013ba75312ce Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Mon, 24 Oct 2022 12:47:47 +0800 Subject: drm/amdgpu: set fb_modifiers_not_supported in vkms This patch to fix the gdm3 start failure with virual display: /usr/libexec/gdm-x-session[1711]: (II) AMDGPU(0): Setting screen physical size to 270 x 203 /usr/libexec/gdm-x-session[1711]: (EE) AMDGPU(0): Failed to make import prime FD as pixmap: 22 /usr/libexec/gdm-x-session[1711]: (EE) AMDGPU(0): failed to set mode: Invalid argument /usr/libexec/gdm-x-session[1711]: (WW) AMDGPU(0): Failed to set mode on CRTC 0 /usr/libexec/gdm-x-session[1711]: (EE) AMDGPU(0): Failed to enable any CRTC gnome-shell[1840]: Running GNOME Shell (using mutter 42.2) as a X11 window and compositing manager /usr/libexec/gdm-x-session[1711]: (EE) AMDGPU(0): failed to set mode: Invalid argument vkms doesn't have modifiers support, set fb_modifiers_not_supported to bring the gdm back. Signed-off-by: Yifan Zhang Acked-by: Guchun Chen Reviewed-by: Tim Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index f4b5301ea2a0..500a1dc4fe02 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -500,6 +500,8 @@ static int amdgpu_vkms_sw_init(void *handle) adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true; + r = amdgpu_display_modeset_create_props(adev); if (r) return r; -- cgit v1.2.3 From 9552b19edcf640103e4b6ad2ab0b46ae8d92b6be Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Thu, 20 Oct 2022 11:47:02 -0400 Subject: drm/amd/display: 3.2.209 DC version 3.2.209 brings along the following: * Improve color manipulation * Add corrections to DML and some flag configuration * Updates for DCN32x * Expand kernel-doc Tested-by: Mark Broadworth Acked-by: Rodrigo Siqueira Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 44f8db160520..c43bafa289e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.208" +#define DC_VER "3.2.209" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From e366f36958f60c431a7430c8c421c9db0ec6738d Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 18 Oct 2022 16:27:59 -0400 Subject: drm/amd/display: Rework comments on dc file The file dc.c has multiple comments that do not follow the kernel-doc or are made in a distracting way. This commit alleviates part of this issue by reorganizing some comments inside the dc file. Signed-off-by: Rodrigo Siqueira Reviewed-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 161 ++++++++++++------------------- drivers/gpu/drm/amd/display/dc/dc.h | 32 ++---- 2 files changed, 70 insertions(+), 123 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2858917a66be..d446e6098948 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -135,9 +135,7 @@ static const char DC_BUILD_ID[] = "production-build"; * one or two (in the pipe-split case). */ -/******************************************************************************* - * Private functions - ******************************************************************************/ +/* Private functions */ static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new) { @@ -421,18 +419,14 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, } /** - ***************************************************************************** - * Function: dc_stream_get_last_vrr_vtotal + * dc_stream_get_last_used_drr_vtotal - dc_stream_get_last_vrr_vtotal * - * @brief - * Looks up the pipe context of dc_stream_state and gets the - * last VTOTAL used by DRR (Dynamic Refresh Rate) + * @dc: [in] dc reference + * @stream: [in] Initial dc stream state + * @adjust: [in] Updated parameters for vertical_total_min and * - * @param [in] dc: dc reference - * @param [in] stream: Initial dc stream state - * @param [in] adjust: Updated parameters for vertical_total_min and - * vertical_total_max - ***************************************************************************** + * Looks up the pipe context of dc_stream_state and gets the last VTOTAL used + * by DRR (Dynamic Refresh Rate) */ bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, struct dc_stream_state *stream, @@ -1209,9 +1203,7 @@ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context) PERF_TRACE(); } -/******************************************************************************* - * Public functions - ******************************************************************************/ +/* Public functions */ struct dc *dc_create(const struct dc_init_data *init_params) { @@ -4552,21 +4544,17 @@ void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc) dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down = true; } -/* - ***************************************************************************** - * Function: dc_is_dmub_outbox_supported - +/** + * dc_is_dmub_outbox_supported - Check if DMUB firmware support outbox notification * - * @brief - * Checks whether DMUB FW supports outbox notifications, if supported - * DM should register outbox interrupt prior to actually enabling interrupts - * via dc_enable_dmub_outbox + * @dc: [in] dc structure * - * @param - * [in] dc: dc structure + * Checks whether DMUB FW supports outbox notifications, if supported DM + * should register outbox interrupt prior to actually enabling interrupts + * via dc_enable_dmub_outbox * - * @return - * True if DMUB FW supports outbox notifications, False otherwise - ***************************************************************************** + * Return: + * True if DMUB FW supports outbox notifications, False otherwise */ bool dc_is_dmub_outbox_supported(struct dc *dc) { @@ -4584,21 +4572,17 @@ bool dc_is_dmub_outbox_supported(struct dc *dc) return dc->debug.enable_dmub_aux_for_legacy_ddc; } -/* - ***************************************************************************** - * Function: dc_enable_dmub_notifications +/** + * dc_enable_dmub_notifications - Check if dmub fw supports outbox * - * @brief - * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox - * notifications. All DMs shall switch to dc_is_dmub_outbox_supported. - * This API shall be removed after switching. + * @dc: [in] dc structure * - * @param - * [in] dc: dc structure + * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox + * notifications. All DMs shall switch to dc_is_dmub_outbox_supported. This + * API shall be removed after switching. * - * @return - * True if DMUB FW supports outbox notifications, False otherwise - ***************************************************************************** + * Return: + * True if DMUB FW supports outbox notifications, False otherwise */ bool dc_enable_dmub_notifications(struct dc *dc) { @@ -4606,18 +4590,11 @@ bool dc_enable_dmub_notifications(struct dc *dc) } /** - ***************************************************************************** - * Function: dc_enable_dmub_outbox + * dc_enable_dmub_outbox - Enables DMUB unsolicited notification * - * @brief - * Enables DMUB unsolicited notifications to x86 via outbox + * dc: [in] dc structure * - * @param - * [in] dc: dc structure - * - * @return - * None - ***************************************************************************** + * Enables DMUB unsolicited notifications to x86 via outbox. */ void dc_enable_dmub_outbox(struct dc *dc) { @@ -4718,21 +4695,17 @@ uint8_t get_link_index_from_dpia_port_index(const struct dc *dc, } /** - ***************************************************************************** - * Function: dc_process_dmub_set_config_async + * dc_process_dmub_set_config_async - Submits set_config command * - * @brief - * Submits set_config command to dmub via inbox message + * @dc: [in] dc structure + * @link_index: [in] link_index: link index + * @payload: [in] aux payload + * @notify: [out] set_config immediate reply * - * @param - * [in] dc: dc structure - * [in] link_index: link index - * [in] payload: aux payload - * [out] notify: set_config immediate reply + * Submits set_config command to dmub via inbox message. * - * @return - * True if successful, False if failure - ***************************************************************************** + * Return: + * True if successful, False if failure */ bool dc_process_dmub_set_config_async(struct dc *dc, uint32_t link_index, @@ -4768,21 +4741,17 @@ bool dc_process_dmub_set_config_async(struct dc *dc, } /** - ***************************************************************************** - * Function: dc_process_dmub_set_mst_slots + * dc_process_dmub_set_mst_slots - Submits MST solt allocation * - * @brief - * Submits mst slot allocation command to dmub via inbox message + * @dc: [in] dc structure + * @link_index: [in] link index + * @mst_alloc_slots: [in] mst slots to be allotted + * @mst_slots_in_use: [out] mst slots in use returned in failure case * - * @param - * [in] dc: dc structure - * [in] link_index: link index - * [in] mst_alloc_slots: mst slots to be allotted - * [out] mst_slots_in_use: mst slots in use returned in failure case + * Submits mst slot allocation command to dmub via inbox message * - * @return - * DC_OK if successful, DC_ERROR if failure - ***************************************************************************** + * Return: + * DC_OK if successful, DC_ERROR if failure */ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, uint32_t link_index, @@ -4822,19 +4791,12 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, } /** - ***************************************************************************** - * Function: dc_process_dmub_dpia_hpd_int_enable - * - * @brief - * Submits dpia hpd int enable command to dmub via inbox message + * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption * - * @param - * [in] dc: dc structure - * [in] hpd_int_enable: 1 for hpd int enable, 0 to disable + * @dc [in]: dc structure + * @hpd_int_enable [in]: 1 for hpd int enable, 0 to disable * - * @return - * None - ***************************************************************************** + * Submits dpia hpd int enable command to dmub via inbox message */ void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc, uint32_t hpd_int_enable) @@ -4863,16 +4825,13 @@ void dc_disable_accelerated_mode(struct dc *dc) /** - ***************************************************************************** - * dc_notify_vsync_int_state() - notifies vsync enable/disable state + * dc_notify_vsync_int_state - notifies vsync enable/disable state * @dc: dc structure - * @stream: stream where vsync int state changed - * @enable: whether vsync is enabled or disabled + * @stream: stream where vsync int state changed + * @enable: whether vsync is enabled or disabled * - * Called when vsync is enabled/disabled - * Will notify DMUB to start/stop ABM interrupts after steady state is reached - * - ***************************************************************************** + * Called when vsync is enabled/disabled Will notify DMUB to start/stop ABM + * interrupts after steady state is reached. */ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable) { @@ -4914,14 +4873,18 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause) pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst); } -/* - * dc_extended_blank_supported: Decide whether extended blank is supported + +/** + * dc_extended_blank_supported 0 Decide whether extended blank is supported * - * Extended blank is a freesync optimization feature to be enabled in the future. - * During the extra vblank period gained from freesync, we have the ability to enter z9/z10. + * @dc: [in] Current DC state * - * @param [in] dc: Current DC state - * @return: Indicate whether extended blank is supported (true or false) + * Extended blank is a freesync optimization feature to be enabled in the + * future. During the extra vblank period gained from freesync, we have the + * ability to enter z9/z10. + * + * Return: + * Indicate whether extended blank is supported (true or false) */ bool dc_extended_blank_supported(struct dc *dc) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c43bafa289e6..2a6406440032 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -56,9 +56,7 @@ struct dmub_notification; #define MIN_VIEWPORT_SIZE 12 #define MAX_NUM_EDP 2 -/******************************************************************************* - * Display Core Interfaces - ******************************************************************************/ +/* Display Core Interfaces */ struct dc_versions { const char *dc_ver; struct dmcu_version dmcu_version; @@ -1000,9 +998,7 @@ void dc_init_callbacks(struct dc *dc, void dc_deinit_callbacks(struct dc *dc); void dc_destroy(struct dc **dc); -/******************************************************************************* - * Surface Interfaces - ******************************************************************************/ +/* Surface Interfaces */ enum { TRANSFER_FUNC_POINTS = 1025 @@ -1363,9 +1359,7 @@ struct dc_state *dc_copy_state(struct dc_state *src_ctx); void dc_retain_state(struct dc_state *context); void dc_release_state(struct dc_state *context); -/******************************************************************************* - * Link Interfaces - ******************************************************************************/ +/* Link Interfaces */ struct dpcd_caps { union dpcd_rev dpcd_rev; @@ -1467,9 +1461,7 @@ struct hdcp_caps { uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane); -/******************************************************************************* - * Sink Interfaces - A sink corresponds to a display output device - ******************************************************************************/ +/* Sink Interfaces - A sink corresponds to a display output device */ struct dc_container_id { // 128bit GUID in binary form @@ -1552,9 +1544,7 @@ struct dc_cursor { }; -/******************************************************************************* - * Interrupt interfaces - ******************************************************************************/ +/* Interrupt interfaces */ enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, @@ -1566,9 +1556,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index( void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable); -/******************************************************************************* - * Power Interfaces - ******************************************************************************/ +/* Power Interfaces */ void dc_set_power_state( struct dc *dc, @@ -1641,14 +1629,10 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc, uint32_t hpd_int_enable); -/******************************************************************************* - * DSC Interfaces - ******************************************************************************/ +/* DSC Interfaces */ #include "dc_dsc.h" -/******************************************************************************* - * Disable acc mode Interfaces - ******************************************************************************/ +/* Disable acc mode Interfaces */ void dc_disable_accelerated_mode(struct dc *dc); #endif /* DC_INTERFACE_H_ */ -- cgit v1.2.3 From 5468c36d628524effbb89a9503eb1a2318804759 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Thu, 20 Oct 2022 16:06:26 -0400 Subject: drm/amd/display: Filter Invalid 420 Modes for HDMI TMDS [Why] Invalidate unsupported 420 modes on HDMI TMDS. HDMI TMDS does not support ODM. Any modes that are horizontally wider than 4096, cannot be supported via TMDS. So they must be filtered out and should not pass validation. [How] Create fake plane for the new stream, and validate global state by going through dml validation routine. Tested-by: Mark Broadworth Acked-by: Rodrigo Siqueira Signed-off-by: Fangzhi Zuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 67 +++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d14e57b19066..9f2bf3488a78 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6156,6 +6156,70 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector) create_eml_sink(aconnector); } +static enum dc_status dm_validate_stream_and_context(struct dc *dc, + struct dc_stream_state *stream) +{ + enum dc_status dc_result = DC_ERROR_UNEXPECTED; + struct dc_plane_state *dc_plane_state = NULL; + struct dc_state *dc_state = NULL; + + if (!stream) + goto cleanup; + + dc_plane_state = dc_create_plane_state(dc); + if (!dc_plane_state) + goto cleanup; + + dc_state = dc_create_state(dc); + if (!dc_state) + goto cleanup; + + /* populate stream to plane */ + dc_plane_state->src_rect.height = stream->src.height; + dc_plane_state->src_rect.width = stream->src.width; + dc_plane_state->dst_rect.height = stream->src.height; + dc_plane_state->dst_rect.width = stream->src.width; + dc_plane_state->clip_rect.height = stream->src.height; + dc_plane_state->clip_rect.width = stream->src.width; + dc_plane_state->plane_size.surface_pitch = ((stream->src.width + 255) / 256) * 256; + dc_plane_state->plane_size.surface_size.height = stream->src.height; + dc_plane_state->plane_size.surface_size.width = stream->src.width; + dc_plane_state->plane_size.chroma_size.height = stream->src.height; + dc_plane_state->plane_size.chroma_size.width = stream->src.width; + dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN; + dc_plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; + dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN; + dc_plane_state->rotation = ROTATION_ANGLE_0; + dc_plane_state->is_tiling_rotated = false; + dc_plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_LINEAR_GENERAL; + + dc_result = dc_validate_stream(dc, stream); + if (dc_result == DC_OK) + dc_result = dc_validate_plane(dc, dc_plane_state); + + if (dc_result == DC_OK) + dc_result = dc_add_stream_to_ctx(dc, dc_state, stream); + + if (dc_result == DC_OK && !dc_add_plane_to_context( + dc, + stream, + dc_plane_state, + dc_state)) + dc_result = DC_FAIL_ATTACH_SURFACES; + + if (dc_result == DC_OK) + dc_result = dc_validate_global_state(dc, dc_state, true); + +cleanup: + if (dc_state) + dc_release_state(dc_state); + + if (dc_plane_state) + dc_plane_state_release(dc_plane_state); + + return dc_result; +} + struct dc_stream_state * create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, const struct drm_display_mode *drm_mode, @@ -6182,6 +6246,9 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream); + if (dc_result == DC_OK) + dc_result = dm_validate_stream_and_context(adev->dm.dc, stream); + if (dc_result != DC_OK) { DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d (%s)\n", drm_mode->hdisplay, -- cgit v1.2.3 From 3f1a02ebeeebe3b8937391646cead0752144f1cb Mon Sep 17 00:00:00 2001 From: Paulo Miguel Almeida Date: Tue, 25 Oct 2022 22:12:00 +1300 Subject: drm/amdkfd: remove unused kfd_pm4_headers_diq header file kfd_pm4_headers_diq.h header is a leftover from the old H/W debugger module support added on commit fbeb661bfa895dc ("drm/amdkfd: Add skeleton H/W debugger module support"). That implementation was removed after a while and the last file that included that header was removed on commit 5bdd3eb253544b1 ("drm/amdkfd: Remove unused old debugger implementation"). This patch removes the unused header file kfd_pm4_headers_diq.h Signed-off-by: Paulo Miguel Almeida Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h | 291 ----------------------- 1 file changed, 291 deletions(-) delete mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h b/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h deleted file mode 100644 index f9cd28690151..000000000000 --- a/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h +++ /dev/null @@ -1,291 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR MIT */ -/* - * Copyright 2014-2022 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef KFD_PM4_HEADERS_DIQ_H_ -#define KFD_PM4_HEADERS_DIQ_H_ - -/*--------------------_INDIRECT_BUFFER-------------------- */ - -#ifndef _PM4__INDIRECT_BUFFER_DEFINED -#define _PM4__INDIRECT_BUFFER_DEFINED -enum _INDIRECT_BUFFER_cache_policy_enum { - cache_policy___indirect_buffer__lru = 0, - cache_policy___indirect_buffer__stream = 1, - cache_policy___indirect_buffer__bypass = 2 -}; - -enum { - IT_INDIRECT_BUFFER_PASID = 0x5C -}; - -struct pm4__indirect_buffer_pasid { - union { - union PM4_MES_TYPE_3_HEADER header; /* header */ - unsigned int ordinal1; - }; - - union { - struct { - unsigned int reserved1:2; - unsigned int ib_base_lo:30; - } bitfields2; - unsigned int ordinal2; - }; - - union { - struct { - unsigned int ib_base_hi:16; - unsigned int reserved2:16; - } bitfields3; - unsigned int ordinal3; - }; - - union { - unsigned int control; - unsigned int ordinal4; - }; - - union { - struct { - unsigned int pasid:10; - unsigned int reserved4:22; - } bitfields5; - unsigned int ordinal5; - }; - -}; - -#endif - -/*--------------------_RELEASE_MEM-------------------- */ - -#ifndef _PM4__RELEASE_MEM_DEFINED -#define _PM4__RELEASE_MEM_DEFINED -enum _RELEASE_MEM_event_index_enum { - event_index___release_mem__end_of_pipe = 5, - event_index___release_mem__shader_done = 6 -}; - -enum _RELEASE_MEM_cache_policy_enum { - cache_policy___release_mem__lru = 0, - cache_policy___release_mem__stream = 1, - cache_policy___release_mem__bypass = 2 -}; - -enum _RELEASE_MEM_dst_sel_enum { - dst_sel___release_mem__memory_controller = 0, - dst_sel___release_mem__tc_l2 = 1, - dst_sel___release_mem__queue_write_pointer_register = 2, - dst_sel___release_mem__queue_write_pointer_poll_mask_bit = 3 -}; - -enum _RELEASE_MEM_int_sel_enum { - int_sel___release_mem__none = 0, - int_sel___release_mem__send_interrupt_only = 1, - int_sel___release_mem__send_interrupt_after_write_confirm = 2, - int_sel___release_mem__send_data_after_write_confirm = 3 -}; - -enum _RELEASE_MEM_data_sel_enum { - data_sel___release_mem__none = 0, - data_sel___release_mem__send_32_bit_low = 1, - data_sel___release_mem__send_64_bit_data = 2, - data_sel___release_mem__send_gpu_clock_counter = 3, - data_sel___release_mem__send_cp_perfcounter_hi_lo = 4, - data_sel___release_mem__store_gds_data_to_memory = 5 -}; - -struct pm4__release_mem { - union { - union PM4_MES_TYPE_3_HEADER header; /*header */ - unsigned int ordinal1; - }; - - union { - struct { - unsigned int event_type:6; - unsigned int reserved1:2; - enum _RELEASE_MEM_event_index_enum event_index:4; - unsigned int tcl1_vol_action_ena:1; - unsigned int tc_vol_action_ena:1; - unsigned int reserved2:1; - unsigned int tc_wb_action_ena:1; - unsigned int tcl1_action_ena:1; - unsigned int tc_action_ena:1; - unsigned int reserved3:6; - unsigned int atc:1; - enum _RELEASE_MEM_cache_policy_enum cache_policy:2; - unsigned int reserved4:5; - } bitfields2; - unsigned int ordinal2; - }; - - union { - struct { - unsigned int reserved5:16; - enum _RELEASE_MEM_dst_sel_enum dst_sel:2; - unsigned int reserved6:6; - enum _RELEASE_MEM_int_sel_enum int_sel:3; - unsigned int reserved7:2; - enum _RELEASE_MEM_data_sel_enum data_sel:3; - } bitfields3; - unsigned int ordinal3; - }; - - union { - struct { - unsigned int reserved8:2; - unsigned int address_lo_32b:30; - } bitfields4; - struct { - unsigned int reserved9:3; - unsigned int address_lo_64b:29; - } bitfields5; - unsigned int ordinal4; - }; - - unsigned int address_hi; - - unsigned int data_lo; - - unsigned int data_hi; - -}; -#endif - - -/*--------------------_SET_CONFIG_REG-------------------- */ - -#ifndef _PM4__SET_CONFIG_REG_DEFINED -#define _PM4__SET_CONFIG_REG_DEFINED - -struct pm4__set_config_reg { - union { - union PM4_MES_TYPE_3_HEADER header; /*header */ - unsigned int ordinal1; - }; - - union { - struct { - unsigned int reg_offset:16; - unsigned int reserved1:7; - unsigned int vmid_shift:5; - unsigned int insert_vmid:1; - unsigned int reserved2:3; - } bitfields2; - unsigned int ordinal2; - }; - - unsigned int reg_data[1]; /*1..N of these fields */ - -}; -#endif - -/*--------------------_WAIT_REG_MEM-------------------- */ - -#ifndef _PM4__WAIT_REG_MEM_DEFINED -#define _PM4__WAIT_REG_MEM_DEFINED -enum _WAIT_REG_MEM_function_enum { - function___wait_reg_mem__always_pass = 0, - function___wait_reg_mem__less_than_ref_value = 1, - function___wait_reg_mem__less_than_equal_to_the_ref_value = 2, - function___wait_reg_mem__equal_to_the_reference_value = 3, - function___wait_reg_mem__not_equal_reference_value = 4, - function___wait_reg_mem__greater_than_or_equal_reference_value = 5, - function___wait_reg_mem__greater_than_reference_value = 6, - function___wait_reg_mem__reserved = 7 -}; - -enum _WAIT_REG_MEM_mem_space_enum { - mem_space___wait_reg_mem__register_space = 0, - mem_space___wait_reg_mem__memory_space = 1 -}; - -enum _WAIT_REG_MEM_operation_enum { - operation___wait_reg_mem__wait_reg_mem = 0, - operation___wait_reg_mem__wr_wait_wr_reg = 1 -}; - -struct pm4__wait_reg_mem { - union { - union PM4_MES_TYPE_3_HEADER header; /*header */ - unsigned int ordinal1; - }; - - union { - struct { - enum _WAIT_REG_MEM_function_enum function:3; - unsigned int reserved1:1; - enum _WAIT_REG_MEM_mem_space_enum mem_space:2; - enum _WAIT_REG_MEM_operation_enum operation:2; - unsigned int reserved2:24; - } bitfields2; - unsigned int ordinal2; - }; - - union { - struct { - unsigned int reserved3:2; - unsigned int memory_poll_addr_lo:30; - } bitfields3; - struct { - unsigned int register_poll_addr:16; - unsigned int reserved4:16; - } bitfields4; - struct { - unsigned int register_write_addr:16; - unsigned int reserved5:16; - } bitfields5; - unsigned int ordinal3; - }; - - union { - struct { - unsigned int poll_address_hi:16; - unsigned int reserved6:16; - } bitfields6; - struct { - unsigned int register_write_addr:16; - unsigned int reserved7:16; - } bitfields7; - unsigned int ordinal4; - }; - - unsigned int reference; - - unsigned int mask; - - union { - struct { - unsigned int poll_interval:16; - unsigned int reserved8:16; - } bitfields8; - unsigned int ordinal7; - }; - -}; -#endif - - -#endif /* KFD_PM4_HEADERS_DIQ_H_ */ -- cgit v1.2.3 From 2513574853f388008b81a900d56c2f75e7f35be2 Mon Sep 17 00:00:00 2001 From: Paulo Miguel Almeida Date: Tue, 25 Oct 2022 21:20:19 +1300 Subject: drm/amdkfd: remove unused struct cdit_header struct cdit_header was never used across any of the amd drivers nor this is exposed to UAPI so it can be removed. This patch removes struct cdit_header and refactor code accordingly Signed-off-by: Paulo Miguel Almeida Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_crat.h | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h index 482ba84a728d..22893ff7b9a1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h @@ -29,11 +29,10 @@ #pragma pack(1) /* - * 4CC signature values for the CRAT and CDIT ACPI tables + * 4CC signature value for the CRAT ACPI table */ #define CRAT_SIGNATURE "CRAT" -#define CDIT_SIGNATURE "CDIT" /* * Component Resource Association Table (CRAT) @@ -292,27 +291,6 @@ struct crat_subtype_generic { uint32_t flags; }; -/* - * Component Locality Distance Information Table (CDIT) - */ -#define CDIT_OEMID_LENGTH 6 -#define CDIT_OEMTABLEID_LENGTH 8 - -struct cdit_header { - uint32_t signature; - uint32_t length; - uint8_t revision; - uint8_t checksum; - uint8_t oem_id[CDIT_OEMID_LENGTH]; - uint8_t oem_table_id[CDIT_OEMTABLEID_LENGTH]; - uint32_t oem_revision; - uint32_t creator_id; - uint32_t creator_revision; - uint32_t total_entries; - uint16_t num_domains; - uint8_t entry[1]; -}; - #pragma pack() struct kfd_dev; -- cgit v1.2.3 From cbe4d43ea5e903ae3e8555cc39047b0ed027738a Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Mon, 17 Oct 2022 18:22:13 +0800 Subject: drm/amdgpu: add RAS page retirement functions for MCA Define page retirement functions for MCA platform. v2: remove page retirement handling from MCA poison handler, let MCA notifier do page retirement. v3: remove specific poison handler for MCA to simplify code. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 53 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 2 ++ 2 files changed, 55 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index aad3c8b4c810..3c83129f4090 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -22,6 +22,59 @@ */ #include "amdgpu.h" +#include "umc_v6_7.h" + +static int amdgpu_umc_convert_error_address(struct amdgpu_device *adev, + struct ras_err_data *err_data, uint64_t err_addr, + uint32_t ch_inst, uint32_t umc_inst) +{ + switch (adev->ip_versions[UMC_HWIP][0]) { + case IP_VERSION(6, 7, 0): + umc_v6_7_convert_error_address(adev, + err_data, err_addr, ch_inst, umc_inst); + break; + default: + dev_warn(adev->dev, + "UMC address to Physical address translation is not supported\n"); + return AMDGPU_RAS_FAIL; + } + + return AMDGPU_RAS_SUCCESS; +} + +int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev, + uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst) +{ + struct ras_err_data err_data = {0, 0, 0, NULL}; + int ret = AMDGPU_RAS_FAIL; + + err_data.err_addr = + kcalloc(adev->umc.max_ras_err_cnt_per_query, + sizeof(struct eeprom_table_record), GFP_KERNEL); + if (!err_data.err_addr) { + dev_warn(adev->dev, + "Failed to alloc memory for umc error record in MCA notifier!\n"); + return AMDGPU_RAS_FAIL; + } + + /* + * Translate UMC channel address to Physical address + */ + ret = amdgpu_umc_convert_error_address(adev, &err_data, err_addr, + ch_inst, umc_inst); + if (ret) + goto out; + + if (amdgpu_bad_page_threshold != 0) { + amdgpu_ras_add_bad_pages(adev, err_data.err_addr, + err_data.err_addr_cnt); + amdgpu_ras_save_bad_pages(adev); + } + +out: + kfree(err_data.err_addr); + return ret; +} static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, void *ras_error_status, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index 3629d8f292ef..659a10de29c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -98,4 +98,6 @@ void amdgpu_umc_fill_error_record(struct ras_err_data *err_data, int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev, void *ras_error_status, struct amdgpu_iv_entry *entry); +int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev, + uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst); #endif -- cgit v1.2.3 From 24b822928b5139b85ee9a818a65e343b7e3bb4fe Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Mon, 17 Oct 2022 18:26:17 +0800 Subject: drm/amdgpu: use page retirement API in MCA notifier Make the code more readable. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 36 +++------------------------------ 1 file changed, 3 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 21a47f2bb87b..28463b47ce33 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -36,7 +36,6 @@ #include "ivsrcid/nbio/irqsrcs_nbif_7_4.h" #include "atom.h" #include "amdgpu_reset.h" -#include "umc_v6_7.h" #ifdef CONFIG_X86_MCE_AMD #include @@ -2849,7 +2848,6 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb, struct amdgpu_device *adev = NULL; uint32_t gpu_id = 0; uint32_t umc_inst = 0, ch_inst = 0; - struct ras_err_data err_data = {0, 0, 0, NULL}; /* * If the error was generated in UMC_V2, which belongs to GPU UMCs, @@ -2888,38 +2886,10 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb, dev_info(adev->dev, "Uncorrectable error detected in UMC inst: %d, chan_idx: %d", umc_inst, ch_inst); - err_data.err_addr = - kcalloc(adev->umc.max_ras_err_cnt_per_query, - sizeof(struct eeprom_table_record), GFP_KERNEL); - if (!err_data.err_addr) { - dev_warn(adev->dev, - "Failed to alloc memory for umc error record in mca notifier!\n"); - return NOTIFY_DONE; - } - - /* - * Translate UMC channel address to Physical address - */ - switch (adev->ip_versions[UMC_HWIP][0]) { - case IP_VERSION(6, 7, 0): - umc_v6_7_convert_error_address(adev, - &err_data, m->addr, ch_inst, umc_inst); - break; - default: - dev_warn(adev->dev, - "UMC address to Physical address translation is not supported\n"); - kfree(err_data.err_addr); + if (!amdgpu_umc_page_retirement_mca(adev, m->addr, ch_inst, umc_inst)) + return NOTIFY_OK; + else return NOTIFY_DONE; - } - - if (amdgpu_bad_page_threshold != 0) { - amdgpu_ras_add_bad_pages(adev, err_data.err_addr, - err_data.err_addr_cnt); - amdgpu_ras_save_bad_pages(adev); - } - - kfree(err_data.err_addr); - return NOTIFY_OK; } static struct notifier_block amdgpu_bad_page_nb = { -- cgit v1.2.3 From ae45a18b80d9d0d29f0ecfc52fb4e7831671b299 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Mon, 17 Oct 2022 18:31:20 +0800 Subject: drm/amdgpu: add RAS poison handling for MCA For MCA poison, if unmap queue fails, only gpu reset should be triggered without page retirement handling, MCA notifier will do it. v2: handle MCA poison consumption in umc_poison_handler directly. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 3c83129f4090..758942150c09 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -169,19 +169,28 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev, void *ras_error_status, bool reset) { - int ret; - struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; - struct ras_common_if head = { - .block = AMDGPU_RAS_BLOCK__UMC, - }; - struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head); + int ret = AMDGPU_RAS_SUCCESS; - ret = - amdgpu_umc_do_page_retirement(adev, ras_error_status, NULL, reset); + if (!adev->gmc.xgmi.connected_to_cpu) { + struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; + struct ras_common_if head = { + .block = AMDGPU_RAS_BLOCK__UMC, + }; + struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head); - if (ret == AMDGPU_RAS_SUCCESS && obj) { - obj->err_data.ue_count += err_data->ue_count; - obj->err_data.ce_count += err_data->ce_count; + ret = + amdgpu_umc_do_page_retirement(adev, ras_error_status, NULL, reset); + + if (ret == AMDGPU_RAS_SUCCESS && obj) { + obj->err_data.ue_count += err_data->ue_count; + obj->err_data.ce_count += err_data->ce_count; + } + } else if (reset) { + /* MCA poison handler is only responsible for GPU reset, + * let MCA notifier do page retirement. + */ + kgd2kfd_set_sram_ecc_flag(adev->kfd.dev); + amdgpu_ras_reset_gpu(adev); } return ret; -- cgit v1.2.3 From 1ed0e176902483e67cd02530d387a7551b0e99a4 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Tue, 18 Oct 2022 10:31:09 +0800 Subject: drm/amdgpu: remove ras_error_status parameter for UMC poison handler Make the code simpler. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 4 +--- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 3 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 13 +++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 4 +--- 4 files changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 0561812aa0a4..37db39ba8718 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -753,9 +753,7 @@ bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev) void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset) { - struct ras_err_data err_data = {0, 0, 0, NULL}; - - amdgpu_umc_poison_handler(adev, &err_data, reset); + amdgpu_umc_poison_handler(adev, reset); } bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 28463b47ce33..693bce07eb46 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1561,7 +1561,6 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager * { bool poison_stat = false; struct amdgpu_device *adev = obj->adev; - struct ras_err_data err_data = {0, 0, 0, NULL}; struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, obj->head.block, 0); @@ -1584,7 +1583,7 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager * } if (!adev->gmc.xgmi.connected_to_cpu) - amdgpu_umc_poison_handler(adev, &err_data, false); + amdgpu_umc_poison_handler(adev, false); if (block_obj->hw_ops->handle_poison_consumption) poison_stat = block_obj->hw_ops->handle_poison_consumption(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 758942150c09..f76c19fc0392 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -165,25 +165,22 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, return AMDGPU_RAS_SUCCESS; } -int amdgpu_umc_poison_handler(struct amdgpu_device *adev, - void *ras_error_status, - bool reset) +int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset) { int ret = AMDGPU_RAS_SUCCESS; if (!adev->gmc.xgmi.connected_to_cpu) { - struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; + struct ras_err_data err_data = {0, 0, 0, NULL}; struct ras_common_if head = { .block = AMDGPU_RAS_BLOCK__UMC, }; struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head); - ret = - amdgpu_umc_do_page_retirement(adev, ras_error_status, NULL, reset); + ret = amdgpu_umc_do_page_retirement(adev, &err_data, NULL, reset); if (ret == AMDGPU_RAS_SUCCESS && obj) { - obj->err_data.ue_count += err_data->ue_count; - obj->err_data.ce_count += err_data->ce_count; + obj->err_data.ue_count += err_data.ue_count; + obj->err_data.ce_count += err_data.ce_count; } } else if (reset) { /* MCA poison handler is only responsible for GPU reset, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index 659a10de29c9..a6951160f13a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -83,9 +83,7 @@ struct amdgpu_umc { }; int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block); -int amdgpu_umc_poison_handler(struct amdgpu_device *adev, - void *ras_error_status, - bool reset); +int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset); int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry); -- cgit v1.2.3 From 7117007edad2299f2f093cdcfa813beb646d913e Mon Sep 17 00:00:00 2001 From: Alan Liu Date: Mon, 24 Oct 2022 14:15:30 +0800 Subject: drm/amdgpu: Move the mutex_lock to protect the return status of securedisplay command buffer [Why] Before we call psp_securedisplay_invoke(), we call psp_prep_securedisplay_cmd_buf() to prepare and initialize the command buffer. However, we didn't use the mutex_lock to protect the status of command buffer. So when multiple threads are using the command buffer, after thread A return from psp_securedisplay_invoke() and the command buffer status is set to SUCCESS, another thread B may call psp_prep_securedisplay_cmd_buf() and initialize the status to FAILURE again, and cause Thread A to get a failure return status. [How] Move the mutex_lock out of psp_securedisplay_invoke() to its caller to cover psp_prep_securedisplay_cmd_buf() and the code checking the return status of command buffer. Signed-off-by: Alan Liu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 9 +++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c | 4 ++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 4 ++++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index effa7df3ddbf..7bbf869f4f0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1938,10 +1938,15 @@ static int psp_securedisplay_initialize(struct psp_context *psp) } else return ret; + mutex_lock(&psp->securedisplay_context.mutex); + psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, TA_SECUREDISPLAY_COMMAND__QUERY_TA); ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA); + + mutex_unlock(&psp->securedisplay_context.mutex); + if (ret) { psp_securedisplay_terminate(psp); /* free securedisplay shared memory */ @@ -1990,12 +1995,8 @@ int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id) ta_cmd_id != TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC) return -EINVAL; - mutex_lock(&psp->securedisplay_context.mutex); - ret = psp_ta_invoke(psp, ta_cmd_id, &psp->securedisplay_context.context); - mutex_unlock(&psp->securedisplay_context.mutex); - return ret; } /* SECUREDISPLAY end */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c index cc7597a15fe9..2c1d82fc4c34 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c @@ -121,6 +121,7 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u switch (op) { case 1: + mutex_lock(&psp->securedisplay_context.mutex); psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, TA_SECUREDISPLAY_COMMAND__QUERY_TA); ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA); @@ -131,8 +132,10 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u else psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); } + mutex_unlock(&psp->securedisplay_context.mutex); break; case 2: + mutex_lock(&psp->securedisplay_context.mutex); psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC); securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_id; @@ -146,6 +149,7 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); } } + mutex_unlock(&psp->securedisplay_context.mutex); break; default: dev_err(adev->dev, "Invalid input: %s\n", str); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index fb077e9af99f..66df2394d7e4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -123,6 +123,8 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work) phy_id = crc_rd_wrk->phy_inst; spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock); + mutex_lock(&psp->securedisplay_context.mutex); + psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC); securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = @@ -133,6 +135,8 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work) psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); } } + + mutex_unlock(&psp->securedisplay_context.mutex); } static void -- cgit v1.2.3 From 1d522b51e3ab3d65628a5e92c3176df10eab67d4 Mon Sep 17 00:00:00 2001 From: Graham Sider Date: Tue, 25 Oct 2022 14:42:13 -0400 Subject: drm/amdgpu: correct MES debugfs versions Use mes.sched_version, mes.kiq_version for debugfs as mes.ucode_fw_version does not contain correct versioning information. Signed-off-by: Graham Sider Reviewed-by: Jack Xiao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index bf1ff8f0e712..4e42dcb1950f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -337,12 +337,14 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, fw_info->feature = adev->psp.cap_feature_version; break; case AMDGPU_INFO_FW_MES_KIQ: - fw_info->ver = adev->mes.ucode_fw_version[0]; - fw_info->feature = 0; + fw_info->ver = adev->mes.kiq_version & AMDGPU_MES_VERSION_MASK; + fw_info->feature = (adev->mes.kiq_version & AMDGPU_MES_FEAT_VERSION_MASK) + >> AMDGPU_MES_FEAT_VERSION_SHIFT; break; case AMDGPU_INFO_FW_MES: - fw_info->ver = adev->mes.ucode_fw_version[1]; - fw_info->feature = 0; + fw_info->ver = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK; + fw_info->feature = (adev->mes.sched_version & AMDGPU_MES_FEAT_VERSION_MASK) + >> AMDGPU_MES_FEAT_VERSION_SHIFT; break; case AMDGPU_INFO_FW_IMU: fw_info->ver = adev->gfx.imu_fw_version; -- cgit v1.2.3 From 6040517e4a29d3828160c571681eec9ffe10043f Mon Sep 17 00:00:00 2001 From: Graham Sider Date: Tue, 25 Oct 2022 14:47:05 -0400 Subject: drm/amdgpu: remove deprecated MES version vars MES scheduler and kiq versions are stored in mes.sched_version and mes.kiq_version, respectively, which are read from a register after their queues are initialized. Remove mes.ucode_fw_version and mes.data_fw_version which tried to read this versioning info from the firmware headers (which don't contain this information). Signed-off-by: Graham Sider Reviewed-by: Jack Xiao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 2 -- drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 4 ---- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 4 ---- 3 files changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index ad980f4b66e1..97c05d08a551 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -91,14 +91,12 @@ struct amdgpu_mes { struct amdgpu_bo *ucode_fw_obj[AMDGPU_MAX_MES_PIPES]; uint64_t ucode_fw_gpu_addr[AMDGPU_MAX_MES_PIPES]; uint32_t *ucode_fw_ptr[AMDGPU_MAX_MES_PIPES]; - uint32_t ucode_fw_version[AMDGPU_MAX_MES_PIPES]; uint64_t uc_start_addr[AMDGPU_MAX_MES_PIPES]; /* mes ucode data */ struct amdgpu_bo *data_fw_obj[AMDGPU_MAX_MES_PIPES]; uint64_t data_fw_gpu_addr[AMDGPU_MAX_MES_PIPES]; uint32_t *data_fw_ptr[AMDGPU_MAX_MES_PIPES]; - uint32_t data_fw_version[AMDGPU_MAX_MES_PIPES]; uint64_t data_start_addr[AMDGPU_MAX_MES_PIPES]; /* eop gpu obj */ diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c index 067d10073a56..1abdf8b7ab50 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c @@ -415,10 +415,6 @@ static int mes_v10_1_init_microcode(struct amdgpu_device *adev, mes_hdr = (const struct mes_firmware_header_v1_0 *) adev->mes.fw[pipe]->data; - adev->mes.ucode_fw_version[pipe] = - le32_to_cpu(mes_hdr->mes_ucode_version); - adev->mes.ucode_fw_version[pipe] = - le32_to_cpu(mes_hdr->mes_ucode_data_version); adev->mes.uc_start_addr[pipe] = le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) | ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32); diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index f141fadd2d86..8ca3417fcfe5 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -485,10 +485,6 @@ static int mes_v11_0_init_microcode(struct amdgpu_device *adev, mes_hdr = (const struct mes_firmware_header_v1_0 *) adev->mes.fw[pipe]->data; - adev->mes.ucode_fw_version[pipe] = - le32_to_cpu(mes_hdr->mes_ucode_version); - adev->mes.ucode_fw_version[pipe] = - le32_to_cpu(mes_hdr->mes_ucode_data_version); adev->mes.uc_start_addr[pipe] = le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) | ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32); -- cgit v1.2.3 From 64a9f19a5addffe585e872945c0544fed24f83a8 Mon Sep 17 00:00:00 2001 From: Ao Zhong Date: Wed, 26 Oct 2022 13:02:19 +0200 Subject: drm/amd/display: move remaining FPU code to dml folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the process of enabling DCN support for arm64, I found that the dcn10_resource_construct_fp function in dcn10/dcn10_resource.c still needs to use FPU. This will cause compilation to fail on ARM64 platforms because -mgeneral-regs-only is enabled by default to disable the hardware FPU. So move dcn10_resource_construct_fp from dcn10 folder to dml/dcn10 folder to enable hardware FPU for that function. Reviewed-by: Rodrigo Siqueira Acked-by: Christian König Signed-off-by: Ao Zhong Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 44 +--------------------- .../gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c | 36 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h | 2 + 3 files changed, 40 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 56d30baf12df..6bfac8088ab0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1295,47 +1295,6 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) return value; } -/* - * Some architectures don't support soft-float (e.g. aarch64), on those - * this function has to be called with hardfloat enabled, make sure not - * to inline it so whatever fp stuff is done stays inside - */ -static noinline void dcn10_resource_construct_fp( - struct dc *dc) -{ - if (dc->ctx->dce_version == DCN_VERSION_1_01) { - struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc; - struct dcn_ip_params *dcn_ip = dc->dcn_ip; - struct display_mode_lib *dml = &dc->dml; - - dml->ip.max_num_dpp = 3; - /* TODO how to handle 23.84? */ - dcn_soc->dram_clock_change_latency = 23; - dcn_ip->max_num_dpp = 3; - } - if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc->urgent_latency = 3; - dc->debug.disable_dmcu = true; - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; - } - - - dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; - ASSERT(dc->dcn_soc->number_of_channels < 3); - if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/ - dc->dcn_soc->number_of_channels = 2; - - if (dc->dcn_soc->number_of_channels == 1) { - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f; - dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f; - dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f; - dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f; - if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f; - } - } -} - static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks) { int i; @@ -1510,8 +1469,9 @@ static bool dcn10_resource_construct( memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults)); memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults)); - /* Other architectures we build for build this with soft-float */ + DC_FP_START(); dcn10_resource_construct_fp(dc); + DC_FP_END(); if (!dc->config.is_vmin_only_asic) if (ASICREV_IS_RAVEN2(dc->ctx->asic_id.hw_internal_rev)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c index 99644d896222..c5e84190c17a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c @@ -27,6 +27,8 @@ #include "dcn10/dcn10_resource.h" #include "dcn10_fpu.h" +#include "resource.h" +#include "amdgpu_dm/dc_fpu.h" /** * DOC: DCN10 FPU manipulation Overview @@ -121,3 +123,37 @@ struct _vcs_dpi_soc_bounding_box_st dcn1_0_soc = { .writeback_dram_clock_change_latency_us = 23.0, .return_bus_width_bytes = 64, }; + +void dcn10_resource_construct_fp(struct dc *dc) +{ + dc_assert_fp_enabled(); + if (dc->ctx->dce_version == DCN_VERSION_1_01) { + struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc; + struct dcn_ip_params *dcn_ip = dc->dcn_ip; + struct display_mode_lib *dml = &dc->dml; + + dml->ip.max_num_dpp = 3; + /* TODO how to handle 23.84? */ + dcn_soc->dram_clock_change_latency = 23; + dcn_ip->max_num_dpp = 3; + } + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc->urgent_latency = 3; + dc->debug.disable_dmcu = true; + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; + } + + dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc->number_of_channels < 3); + if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc->number_of_channels = 2; + + if (dc->dcn_soc->number_of_channels == 1) { + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f; + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h index e74ed4b4ce5b..63219ecd8478 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h @@ -27,4 +27,6 @@ #ifndef __DCN10_FPU_H__ #define __DCN10_FPU_H__ +void dcn10_resource_construct_fp(struct dc *dc); + #endif /* __DCN20_FPU_H__ */ -- cgit v1.2.3 From 58ddbecb14c792b7fe0d92ae5e25c9179d62ff25 Mon Sep 17 00:00:00 2001 From: Ao Zhong Date: Tue, 25 Oct 2022 23:17:49 +0200 Subject: drm/amd/display: move remaining FPU code to dml folder pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; these two operations in dcn32/dcn32_resource.c still need to use FPU, This will cause compilation to fail on ARM64 platforms because -mgeneral-regs-only is enabled by default to disable the hardware FPU. Therefore, imitate the dcn31_zero_pipe_dcc_fraction function in dml/dcn31/dcn31_fpu.c, declare the dcn32_zero_pipe_dcc_fraction function in dcn32_fpu.c, and move above two operations into this function. Reviewed-by: Rodrigo Siqueira Signed-off-by: Ao Zhong Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 5 +++-- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 8 ++++++++ drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index a88dd7b3d1c1..287b7fa9bf41 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -1918,8 +1918,9 @@ int dcn32_populate_dml_pipes_from_context( timing = &pipe->stream->timing; pipes[pipe_cnt].pipe.src.gpuvm = true; - pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; - pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; + DC_FP_START(); + dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt); + DC_FP_END(); pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index d8e68f13c288..b6cd10f3181c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -2506,3 +2506,11 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa } } +void dcn32_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes, + int pipe_cnt) +{ + dc_assert_fp_enabled(); + + pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; + pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h index 3a3dc2ce4c73..ab010e7e840b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h @@ -73,4 +73,7 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc, void dcn32_patch_dpm_table(struct clk_bw_params *bw_params); +void dcn32_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes, + int pipe_cnt); + #endif -- cgit v1.2.3 From d232afb1f3417ae8194ccf19ad3a8360e70e104e Mon Sep 17 00:00:00 2001 From: gehao Date: Wed, 26 Oct 2022 17:54:05 +0800 Subject: drm/amd/display: prevent memory leak In dce6(0,1,4)_create_resource_pool and dce80_create_resource_pool the allocated memory should be released if construct pool fails. Reviewed-by: Rodrigo Siqueira Signed-off-by: gehao Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c | 3 +++ drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 ++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c index fc6aa098bda0..8db9f7514466 100644 --- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c @@ -1128,6 +1128,7 @@ struct resource_pool *dce60_create_resource_pool( if (dce60_construct(num_virtual_links, dc, pool)) return &pool->base; + kfree(pool); BREAK_TO_DEBUGGER(); return NULL; } @@ -1325,6 +1326,7 @@ struct resource_pool *dce61_create_resource_pool( if (dce61_construct(num_virtual_links, dc, pool)) return &pool->base; + kfree(pool); BREAK_TO_DEBUGGER(); return NULL; } @@ -1518,6 +1520,7 @@ struct resource_pool *dce64_create_resource_pool( if (dce64_construct(num_virtual_links, dc, pool)) return &pool->base; + kfree(pool); BREAK_TO_DEBUGGER(); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index b28025960050..5825e6f412bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -1137,6 +1137,7 @@ struct resource_pool *dce80_create_resource_pool( if (dce80_construct(num_virtual_links, dc, pool)) return &pool->base; + kfree(pool); BREAK_TO_DEBUGGER(); return NULL; } @@ -1336,6 +1337,7 @@ struct resource_pool *dce81_create_resource_pool( if (dce81_construct(num_virtual_links, dc, pool)) return &pool->base; + kfree(pool); BREAK_TO_DEBUGGER(); return NULL; } -- cgit v1.2.3 From 9682069a03c1ff031a67d80e7a58cf2b11d7f758 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 26 Oct 2022 10:00:54 +0800 Subject: drm/amdkfd: Fix NULL pointer dereference in svm_migrate_to_ram() ./drivers/gpu/drm/amd/amdkfd/kfd_migrate.c:985:58-62: ERROR: p is NULL but dereferenced. Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=2549 Reported-by: Abaci Robot Signed-off-by: Yang Li Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index d4e6de2a6bf6..3723e90e3a90 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -973,12 +973,10 @@ out_unlock_prange: out_unlock_svms: mutex_unlock(&p->svms.lock); out_unref_process: + pr_debug("CPU fault svms 0x%p address 0x%lx done\n", &p->svms, addr); kfd_unref_process(p); out_mmput: mmput(mm); - - pr_debug("CPU fault svms 0x%p address 0x%lx done\n", &p->svms, addr); - return r ? VM_FAULT_SIGBUS : 0; } -- cgit v1.2.3 From bf7d777289d106963fd2080d298e6b88b7263b66 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Tue, 25 Oct 2022 18:07:44 +0800 Subject: drm/amdgpu: Optimize RAS TA initialization and TA unload funcs 1. Save TA unload psp response status 2. Add RAS TA loading status check for initializaiton 3. Drop RAS context teardown to allow RAS TA to be reloaded Reviewed-by: Hawking Zhang Signed-off-by: Candice Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 7bbf869f4f0d..b8d07e863ed8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -988,6 +988,8 @@ int psp_ta_unload(struct psp_context *psp, struct ta_context *context) ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + context->resp_status = cmd->resp.status; + release_psp_cmd_buf(psp); return ret; @@ -1560,6 +1562,11 @@ static int psp_ras_initialize(struct psp_context *psp) if (amdgpu_sriov_vf(adev)) return 0; + if (psp->ras_context.context.initialized) { + dev_warn(adev->dev, "RAS WARN: TA has already been loaded\n"); + return 0; + } + if (!adev->psp.ras_context.context.bin_desc.size_bytes || !adev->psp.ras_context.context.bin_desc.start_addr) { dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); @@ -1610,7 +1617,7 @@ static int psp_ras_initialize(struct psp_context *psp) psp->ras_context.context.mem_context.shared_mem_size = PSP_RAS_SHARED_MEM_SIZE; psp->ras_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; - if (!psp->ras_context.context.initialized) { + if (!psp->ras_context.context.mem_context.shared_buf) { ret = psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context); if (ret) return ret; @@ -1631,7 +1638,6 @@ static int psp_ras_initialize(struct psp_context *psp) else { if (ras_cmd->ras_status) dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); - amdgpu_ras_fini(psp->adev); } return ret; -- cgit v1.2.3 From 896b7addf2dc24908ad87f8ebeff83b2a83b8e04 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Tue, 25 Oct 2022 18:32:15 +0800 Subject: drm/amdgpu: Optimize TA load/unload/invoke debugfs interfaces 1. Add a function pointer structure ta_funcs to psp context 2. Make the interfaces generic to all TAs 3. Leverage exisitng TA context and remove unused functions 4. Fix return code bugs v2: Add comments for ta funcs macros and correct typo Reviewed-by: Hawking Zhang Signed-off-by: Candice Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 38 +---- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 12 +- drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c | 217 ++++++++++++++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h | 5 + 4 files changed, 168 insertions(+), 104 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index b8d07e863ed8..2fcb5bfbef89 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1071,42 +1071,6 @@ int psp_ta_init_shared_buf(struct psp_context *psp, &mem_ctx->shared_buf); } -static void psp_prep_ta_invoke_indirect_cmd_buf(struct psp_gfx_cmd_resp *cmd, - uint32_t ta_cmd_id, - struct ta_context *context) -{ - cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; - cmd->cmd.cmd_invoke_cmd.session_id = context->session_id; - cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; - - cmd->cmd.cmd_invoke_cmd.buf.num_desc = 1; - cmd->cmd.cmd_invoke_cmd.buf.total_size = context->mem_context.shared_mem_size; - cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_size = context->mem_context.shared_mem_size; - cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_phy_addr_lo = - lower_32_bits(context->mem_context.shared_mc_addr); - cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_phy_addr_hi = - upper_32_bits(context->mem_context.shared_mc_addr); -} - -int psp_ta_invoke_indirect(struct psp_context *psp, - uint32_t ta_cmd_id, - struct ta_context *context) -{ - int ret; - struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_invoke_indirect_cmd_buf(cmd, ta_cmd_id, context); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, - psp->fence_buf_mc_addr); - - context->resp_status = cmd->resp.status; - - release_psp_cmd_buf(psp); - - return ret; -} - static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, uint32_t ta_cmd_id, uint32_t session_id) @@ -1549,7 +1513,7 @@ int psp_ras_terminate(struct psp_context *psp) return ret; } -static int psp_ras_initialize(struct psp_context *psp) +int psp_ras_initialize(struct psp_context *psp) { int ret; uint32_t boot_cfg = 0xFF; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 58ce3ebb446c..cbd4194a2883 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -136,6 +136,12 @@ struct psp_funcs int (*vbflash_stat)(struct psp_context *psp); }; +struct ta_funcs { + int (*fn_ta_initialize)(struct psp_context *psp); + int (*fn_ta_invoke)(struct psp_context *psp, uint32_t ta_cmd_id); + int (*fn_ta_terminate)(struct psp_context *psp); +}; + #define AMDGPU_XGMI_MAX_CONNECTED_NODES 64 struct psp_xgmi_node_info { uint64_t node_id; @@ -309,6 +315,7 @@ struct psp_context struct psp_gfx_cmd_resp *cmd; const struct psp_funcs *funcs; + const struct ta_funcs *ta_funcs; /* firmware buffer */ struct amdgpu_bo *fw_pri_bo; @@ -463,9 +470,6 @@ int psp_ta_load(struct psp_context *psp, struct ta_context *context); int psp_ta_invoke(struct psp_context *psp, uint32_t ta_cmd_id, struct ta_context *context); -int psp_ta_invoke_indirect(struct psp_context *psp, - uint32_t ta_cmd_id, - struct ta_context *context); int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta); int psp_xgmi_terminate(struct psp_context *psp); @@ -479,7 +483,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp, int psp_xgmi_set_topology_info(struct psp_context *psp, int number_devices, struct psp_xgmi_topology_info *topology); - +int psp_ras_initialize(struct psp_context *psp); int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id); int psp_ras_enable_features(struct psp_context *psp, union ta_ras_cmd_input *info, bool enable); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c index 0988e00612e5..468a67b302d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c @@ -41,30 +41,46 @@ static uint32_t get_bin_version(const uint8_t *bin) return hdr->ucode_version; } -static void prep_ta_mem_context(struct psp_context *psp, - struct ta_context *context, +static int prep_ta_mem_context(struct ta_mem_context *mem_context, uint8_t *shared_buf, uint32_t shared_buf_len) { - context->mem_context.shared_mem_size = PAGE_ALIGN(shared_buf_len); - psp_ta_init_shared_buf(psp, &context->mem_context); + if (mem_context->shared_mem_size < shared_buf_len) + return -EINVAL; + memset(mem_context->shared_buf, 0, mem_context->shared_mem_size); + memcpy((void *)mem_context->shared_buf, shared_buf, shared_buf_len); - memcpy((void *)context->mem_context.shared_buf, shared_buf, shared_buf_len); + return 0; } static bool is_ta_type_valid(enum ta_type_id ta_type) { - bool ret = false; + switch (ta_type) { + case TA_TYPE_RAS: + return true; + default: + return false; + } +} + +static const struct ta_funcs ras_ta_funcs = { + .fn_ta_initialize = psp_ras_initialize, + .fn_ta_invoke = psp_ras_invoke, + .fn_ta_terminate = psp_ras_terminate +}; +static void set_ta_context_funcs(struct psp_context *psp, + enum ta_type_id ta_type, + struct ta_context **pcontext) +{ switch (ta_type) { case TA_TYPE_RAS: - ret = true; + *pcontext = &psp->ras_context.context; + psp->ta_funcs = &ras_ta_funcs; break; default: break; } - - return ret; } static const struct file_operations ta_load_debugfs_fops = { @@ -85,8 +101,7 @@ static const struct file_operations ta_invoke_debugfs_fops = { .owner = THIS_MODULE }; - -/** +/* * DOC: AMDGPU TA debugfs interfaces * * Three debugfs interfaces can be opened by a program to @@ -111,15 +126,18 @@ static const struct file_operations ta_invoke_debugfs_fops = { * * - For TA invoke debugfs interface: * Transmit buffer: + * - TA type (4bytes) * - TA ID (4bytes) * - TA CMD ID (4bytes) - * - TA shard buf length (4bytes) + * - TA shard buf length + * (4bytes, value not beyond TA shared memory size) * - TA shared buf * Receive buffer: * - TA shared buf * * - For TA unload debugfs interface: * Transmit buffer: + * - TA type (4bytes) * - TA ID (4bytes) */ @@ -131,59 +149,92 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t uint32_t copy_pos = 0; int ret = 0; - struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; - struct psp_context *psp = &adev->psp; - struct ta_context context = {0}; + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; + struct psp_context *psp = &adev->psp; + struct ta_context *context = NULL; if (!buf) return -EINVAL; ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); if (ret || (!is_ta_type_valid(ta_type))) - return -EINVAL; + return -EFAULT; copy_pos += sizeof(uint32_t); ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t)); if (ret) - return -EINVAL; + return -EFAULT; copy_pos += sizeof(uint32_t); ta_bin = kzalloc(ta_bin_len, GFP_KERNEL); if (!ta_bin) - ret = -ENOMEM; + return -ENOMEM; if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) { ret = -EFAULT; goto err_free_bin; } - ret = psp_ras_terminate(psp); - if (ret) { - dev_err(adev->dev, "Failed to unload embedded RAS TA\n"); + /* Set TA context and functions */ + set_ta_context_funcs(psp, ta_type, &context); + + if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) { + dev_err(adev->dev, "Unsupported function to terminate TA\n"); + ret = -EOPNOTSUPP; goto err_free_bin; } - context.ta_type = ta_type; - context.ta_load_type = GFX_CMD_ID_LOAD_TA; - context.bin_desc.fw_version = get_bin_version(ta_bin); - context.bin_desc.size_bytes = ta_bin_len; - context.bin_desc.start_addr = ta_bin; + /* + * Allocate TA shared buf in case shared buf was freed + * due to loading TA failed before. + */ + if (!context->mem_context.shared_buf) { + ret = psp_ta_init_shared_buf(psp, &context->mem_context); + if (ret) { + ret = -ENOMEM; + goto err_free_bin; + } + } + + ret = psp_fn_ta_terminate(psp); + if (ret || context->resp_status) { + dev_err(adev->dev, + "Failed to unload embedded TA (%d) and status (0x%X)\n", + ret, context->resp_status); + if (!ret) + ret = -EINVAL; + goto err_free_ta_shared_buf; + } + + /* Prepare TA context for TA initialization */ + context->ta_type = ta_type; + context->bin_desc.fw_version = get_bin_version(ta_bin); + context->bin_desc.size_bytes = ta_bin_len; + context->bin_desc.start_addr = ta_bin; - ret = psp_ta_load(psp, &context); + if (!psp->ta_funcs->fn_ta_initialize) { + dev_err(adev->dev, "Unsupported function to initialize TA\n"); + ret = -EOPNOTSUPP; + goto err_free_ta_shared_buf; + } - if (ret || context.resp_status) { - dev_err(adev->dev, "TA load via debugfs failed (%d) status %d\n", - ret, context.resp_status); + ret = psp_fn_ta_initialize(psp); + if (ret || context->resp_status) { + dev_err(adev->dev, "Failed to load TA via debugfs (%d) and status (0x%X)\n", + ret, context->resp_status); if (!ret) ret = -EINVAL; - goto err_free_bin; + goto err_free_ta_shared_buf; } - context.initialized = true; - if (copy_to_user((char *)buf, (void *)&context.session_id, sizeof(uint32_t))) + if (copy_to_user((char *)buf, (void *)&context->session_id, sizeof(uint32_t))) ret = -EFAULT; +err_free_ta_shared_buf: + /* Only free TA shared buf when returns error code */ + if (ret && context->mem_context.shared_buf) + psp_ta_free_shared_buf(&context->mem_context); err_free_bin: kfree(ta_bin); @@ -192,58 +243,85 @@ err_free_bin: static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) { - uint32_t ta_id = 0; - int ret = 0; + uint32_t ta_type = 0; + uint32_t ta_id = 0; + uint32_t copy_pos = 0; + int ret = 0; - struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; - struct psp_context *psp = &adev->psp; - struct ta_context context = {0}; + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; + struct psp_context *psp = &adev->psp; + struct ta_context *context = NULL; if (!buf) return -EINVAL; - ret = copy_from_user((void *)&ta_id, buf, sizeof(uint32_t)); + ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); + if (ret || (!is_ta_type_valid(ta_type))) + return -EFAULT; + + copy_pos += sizeof(uint32_t); + + ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); if (ret) - return -EINVAL; + return -EFAULT; - context.session_id = ta_id; + set_ta_context_funcs(psp, ta_type, &context); + context->session_id = ta_id; - ret = psp_ta_unload(psp, &context); - if (!ret) - context.initialized = false; + if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) { + dev_err(adev->dev, "Unsupported function to terminate TA\n"); + return -EOPNOTSUPP; + } + + ret = psp_fn_ta_terminate(psp); + if (ret || context->resp_status) { + dev_err(adev->dev, "Failed to unload TA via debugfs (%d) and status (0x%X)\n", + ret, context->resp_status); + if (!ret) + ret = -EINVAL; + } + + if (context->mem_context.shared_buf) + psp_ta_free_shared_buf(&context->mem_context); return ret; } static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) { + uint32_t ta_type = 0; uint32_t ta_id = 0; uint32_t cmd_id = 0; uint32_t shared_buf_len = 0; - uint8_t *shared_buf = NULL; + uint8_t *shared_buf = NULL; uint32_t copy_pos = 0; int ret = 0; - struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; - struct psp_context *psp = &adev->psp; - struct ta_context context = {0}; + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; + struct psp_context *psp = &adev->psp; + struct ta_context *context = NULL; if (!buf) return -EINVAL; + ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); + if (ret) + return -EFAULT; + copy_pos += sizeof(uint32_t); + ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); if (ret) - return -EINVAL; + return -EFAULT; copy_pos += sizeof(uint32_t); ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t)); if (ret) - return -EINVAL; + return -EFAULT; copy_pos += sizeof(uint32_t); ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t)); if (ret) - return -EINVAL; + return -EFAULT; copy_pos += sizeof(uint32_t); shared_buf = kzalloc(shared_buf_len, GFP_KERNEL); @@ -254,26 +332,39 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size goto err_free_shared_buf; } - context.session_id = ta_id; + set_ta_context_funcs(psp, ta_type, &context); + + if (!context->initialized) { + dev_err(adev->dev, "TA is not initialized\n"); + ret = -EINVAL; + goto err_free_shared_buf; + } + + if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) { + dev_err(adev->dev, "Unsupported function to invoke TA\n"); + ret = -EOPNOTSUPP; + goto err_free_shared_buf; + } - prep_ta_mem_context(psp, &context, shared_buf, shared_buf_len); + context->session_id = ta_id; - ret = psp_ta_invoke_indirect(psp, cmd_id, &context); + ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len); + if (ret) + goto err_free_shared_buf; - if (ret || context.resp_status) { - dev_err(adev->dev, "TA invoke via debugfs failed (%d) status %d\n", - ret, context.resp_status); - if (!ret) + ret = psp_fn_ta_invoke(psp, cmd_id); + if (ret || context->resp_status) { + dev_err(adev->dev, "Failed to invoke TA via debugfs (%d) and status (0x%X)\n", + ret, context->resp_status); + if (!ret) { ret = -EINVAL; - goto err_free_ta_shared_buf; + goto err_free_shared_buf; + } } - if (copy_to_user((char *)buf, context.mem_context.shared_buf, shared_buf_len)) + if (copy_to_user((char *)buf, context->mem_context.shared_buf, shared_buf_len)) ret = -EFAULT; -err_free_ta_shared_buf: - psp_ta_free_shared_buf(&context.mem_context); - err_free_shared_buf: kfree(shared_buf); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h index cfc1542f63ef..14cd1c81c3e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h @@ -24,6 +24,11 @@ #ifndef __AMDGPU_PSP_TA_H__ #define __AMDGPU_PSP_TA_H__ +/* Calling set_ta_context_funcs is required before using the following macros */ +#define psp_fn_ta_initialize(psp) ((psp)->ta_funcs->fn_ta_initialize((psp))) +#define psp_fn_ta_invoke(psp, ta_cmd_id) ((psp)->ta_funcs->fn_ta_invoke((psp), (ta_cmd_id))) +#define psp_fn_ta_terminate(psp) ((psp)->ta_funcs->fn_ta_terminate((psp))) + void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev); #endif -- cgit v1.2.3 From bc22f8ec464af9e14263c3ed6a1c2be86618c804 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Mon, 10 Oct 2022 16:26:37 +0800 Subject: drm/amdgpu: Update ras eeprom support for smu v13_0_0 and v13_0_10 Enable RAS EEPROM support for smu v13_0_0 and v13_0_10. Signed-off-by: Candice Li Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 84c241b9a2a1..7dc39154822c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -90,6 +90,16 @@ static bool __is_ras_eeprom_supported(struct amdgpu_device *adev) { + if (adev->asic_type == CHIP_IP_DISCOVERY) { + switch (adev->ip_versions[MP1_HWIP][0]) { + case IP_VERSION(13, 0, 0): + case IP_VERSION(13, 0, 10): + return true; + default: + return false; + } + } + return adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS || adev->asic_type == CHIP_SIENNA_CICHLID || -- cgit v1.2.3 From c9bdc6c3cf39df6db9c611d05fc512b1276b1cc8 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Tue, 11 Oct 2022 15:08:38 +0800 Subject: drm/amdgpu: Add EEPROM I2C address support for ip discovery 1. Update EEPROM_I2C_MADDR_SMU_13_0_0 to EEPROM_I2C_MADDR_54H 2. Add EEPROM I2C address support for smu v13_0_0 and v13_0_10. Signed-off-by: Candice Li Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 7dc39154822c..7268ae65c140 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -38,7 +38,7 @@ #define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0 #define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0 #define EEPROM_I2C_MADDR_ALDEBARAN 0x0 -#define EEPROM_I2C_MADDR_SMU_13_0_0 (0x54UL << 16) +#define EEPROM_I2C_MADDR_54H (0x54UL << 16) /* * The 2 macros bellow represent the actual size in bytes that @@ -124,6 +124,19 @@ static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev, return true; } +static bool __get_eeprom_i2c_addr_ip_discovery(struct amdgpu_device *adev, + struct amdgpu_ras_eeprom_control *control) +{ + switch (adev->ip_versions[MP1_HWIP][0]) { + case IP_VERSION(13, 0, 0): + case IP_VERSION(13, 0, 10): + control->i2c_address = EEPROM_I2C_MADDR_54H; + return true; + default: + return false; + } +} + static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, struct amdgpu_ras_eeprom_control *control) { @@ -163,13 +176,16 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN; break; + case CHIP_IP_DISCOVERY: + return __get_eeprom_i2c_addr_ip_discovery(adev, control); + default: return false; } switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 0): - control->i2c_address = EEPROM_I2C_MADDR_SMU_13_0_0; + control->i2c_address = EEPROM_I2C_MADDR_54H; break; default: -- cgit v1.2.3 From aa193f7eff8ff753577351140b8af13b76cdc7c2 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Fri, 21 Oct 2022 16:37:34 -0400 Subject: drm/edid: add a quirk for two LG monitors to get them to work on 10bpc The LG 27GP950 and LG 27GN950 have visible display corruption when trying to use 10bpc modes. So, to fix this, cap their maximum DSC target bitrate to 15bpp. Suggested-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/drm_edid.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 4005dab6147d..b36abfa91581 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -87,6 +87,8 @@ static int oui(u8 first, u8 second, u8 third) #define EDID_QUIRK_FORCE_10BPC (1 << 11) /* Non desktop display (i.e. HMD) */ #define EDID_QUIRK_NON_DESKTOP (1 << 12) +/* Cap the DSC target bitrate to 15bpp */ +#define EDID_QUIRK_CAP_DSC_15BPP (1 << 13) #define MICROSOFT_IEEE_OUI 0xca125c @@ -147,6 +149,12 @@ static const struct edid_quirk { EDID_QUIRK('F', 'C', 'M', 13600, EDID_QUIRK_PREFER_LARGE_75 | EDID_QUIRK_DETAILED_IN_CM), + /* LG 27GP950 */ + EDID_QUIRK('G', 'S', 'M', 0x5bbf, EDID_QUIRK_CAP_DSC_15BPP), + + /* LG 27GN950 */ + EDID_QUIRK('G', 'S', 'M', 0x5b9a, EDID_QUIRK_CAP_DSC_15BPP), + /* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */ EDID_QUIRK('L', 'G', 'D', 764, EDID_QUIRK_FORCE_10BPC), @@ -6166,6 +6174,7 @@ static void drm_reset_display_info(struct drm_connector *connector) info->mso_stream_count = 0; info->mso_pixel_overlap = 0; + info->max_dsc_bpp = 0; } static u32 update_display_info(struct drm_connector *connector, @@ -6252,6 +6261,9 @@ out: info->non_desktop = true; } + if (quirks & EDID_QUIRK_CAP_DSC_15BPP) + info->max_dsc_bpp = 15; + return quirks; } -- cgit v1.2.3 From 6e5abe94c6eb9b281398e39819217e8fdd1c336f Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Mon, 24 Oct 2022 14:53:24 -0400 Subject: drm/amd/display: use max_dsc_bpp in amdgpu_dm Since, the quirk is handled in the DRM core now, we can use that value instead of the internal value. Reviewed-by: Harry Wentland Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 ++---- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9f2bf3488a78..94620f9b166c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5607,16 +5607,14 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, { struct drm_connector *drm_connector = &aconnector->base; uint32_t link_bandwidth_kbps; - uint32_t max_dsc_target_bpp_limit_override = 0; struct dc *dc = sink->ctx->dc; uint32_t max_supported_bw_in_kbps, timing_bw_in_kbps; uint32_t dsc_max_supported_bw_in_kbps; + uint32_t max_dsc_target_bpp_limit_override = + drm_connector->display_info.max_dsc_bpp; link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, dc_link_get_link_cap(aconnector->dc_link)); - if (stream->link && stream->link->local_sink) - max_dsc_target_bpp_limit_override = - stream->link->local_sink->edid_caps.panel_patch.max_dsc_target_bpp_limit; /* Set DSC policy according to dsc_clock_en */ dc_dsc_policy_set_enable_dsc_when_not_needed( diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 6ff96b4bdda5..d7907974f25a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -642,15 +642,18 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p int count, int k) { + struct drm_connector *drm_connector; int i; for (i = 0; i < count; i++) { + drm_connector = ¶ms[i].aconnector->base; + memset(¶ms[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg)); if (vars[i + k].dsc_enabled && dc_dsc_compute_config( params[i].sink->ctx->dc->res_pool->dscs[0], ¶ms[i].sink->dsc_caps.dsc_dec_caps, params[i].sink->ctx->dc->debug.dsc_min_slice_height_override, - params[i].sink->edid_caps.panel_patch.max_dsc_target_bpp_limit, + drm_connector->display_info.max_dsc_bpp, 0, params[i].timing, ¶ms[i].timing->dsc_cfg)) { @@ -692,12 +695,16 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn) struct dc_dsc_config dsc_config; u64 kbps; + struct drm_connector *drm_connector = ¶m.aconnector->base; + uint32_t max_dsc_target_bpp_limit_override = + drm_connector->display_info.max_dsc_bpp; + kbps = div_u64((u64)pbn * 994 * 8 * 54, 64); dc_dsc_compute_config( param.sink->ctx->dc->res_pool->dscs[0], ¶m.sink->dsc_caps.dsc_dec_caps, param.sink->ctx->dc->debug.dsc_min_slice_height_override, - param.sink->edid_caps.panel_patch.max_dsc_target_bpp_limit, + max_dsc_target_bpp_limit_override, (int) kbps, param.timing, &dsc_config); return dsc_config.bits_per_pixel; -- cgit v1.2.3 From 6803dfd3a69ccb318772463a86e40929fd4fbac7 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Tue, 25 Oct 2022 15:04:36 -0400 Subject: Revert "drm/amd/display: Limit max DSC target bpp for specific monitors" This reverts commit 55eea8ef98641f6e1e1c202bd3a49a57c1dd4059. This quirk is now handled in the DRM core, so we can drop all of the internal code that was added to handle it. Reviewed-by: Harry Wentland Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 35 ---------------------- 1 file changed, 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index f0b01c8dc4a6..f72c013d3a5b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -42,39 +42,6 @@ #include "dm_helpers.h" #include "ddc_service_types.h" -struct monitor_patch_info { - unsigned int manufacturer_id; - unsigned int product_id; - void (*patch_func)(struct dc_edid_caps *edid_caps, unsigned int param); - unsigned int patch_param; -}; -static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param); - -static const struct monitor_patch_info monitor_patch_table[] = { -{0x6D1E, 0x5BBF, set_max_dsc_bpp_limit, 15}, -{0x6D1E, 0x5B9A, set_max_dsc_bpp_limit, 15}, -}; - -static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param) -{ - if (edid_caps) - edid_caps->panel_patch.max_dsc_target_bpp_limit = param; -} - -static int amdgpu_dm_patch_edid_caps(struct dc_edid_caps *edid_caps) -{ - int i, ret = 0; - - for (i = 0; i < ARRAY_SIZE(monitor_patch_table); i++) - if ((edid_caps->manufacturer_id == monitor_patch_table[i].manufacturer_id) - && (edid_caps->product_id == monitor_patch_table[i].product_id)) { - monitor_patch_table[i].patch_func(edid_caps, monitor_patch_table[i].patch_param); - ret++; - } - - return ret; -} - /* dm_helpers_parse_edid_caps * * Parse edid caps @@ -149,8 +116,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps( kfree(sads); kfree(sadb); - amdgpu_dm_patch_edid_caps(edid_caps); - return result; } -- cgit v1.2.3 From 7863c1552632223967f561654422cd2016c2520c Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 26 Oct 2022 14:03:55 -0500 Subject: drm/amd: Fail the suspend if resources can't be evicted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a system does not have swap and memory is under 100% usage, amdgpu will fail to evict resources. Currently the suspend carries on proceeding to reset the GPU: ``` [drm] evicting device resources failed [drm:amdgpu_device_ip_suspend_phase2 [amdgpu]] *ERROR* suspend of IP block failed -12 [drm] free PSP TMR buffer [TTM] Failed allocating page table [drm] evicting device resources failed amdgpu 0000:03:00.0: amdgpu: MODE1 reset amdgpu 0000:03:00.0: amdgpu: GPU mode1 reset amdgpu 0000:03:00.0: amdgpu: GPU smu mode1 reset ``` At this point if the suspend actually succeeded I think that amdgpu would have recovered because the GPU would have power cut off and restored. However the kernel fails to continue the suspend from the memory pressure and amdgpu fails to run the "resume" from the aborted suspend. ``` ACPI: PM: Preparing to enter system sleep state S3 SLUB: Unable to allocate memory on node -1, gfp=0xdc0(GFP_KERNEL|__GFP_ZERO) cache: Acpi-State, object size: 80, buffer size: 80, default order: 0, min order: 0 node 0: slabs: 22, objs: 1122, free: 0 ACPI Error: AE_NO_MEMORY, Could not update object reference count (20210730/utdelete-651) [drm:psp_hw_start [amdgpu]] *ERROR* PSP load kdb failed! [drm:psp_resume [amdgpu]] *ERROR* PSP resume failed [drm:amdgpu_device_fw_loading [amdgpu]] *ERROR* resume of IP block failed -62 amdgpu 0000:03:00.0: amdgpu: amdgpu_device_ip_resume failed (-62). PM: dpm_run_callback(): pci_pm_resume+0x0/0x100 returns -62 amdgpu 0000:03:00.0: PM: failed to resume async: error -62 ``` To avoid this series of unfortunate events, fail amdgpu's suspend when the memory eviction fails. This will let the system gracefully recover and the user can try suspend again when the memory pressure is relieved. Reported-by: post@davidak.de Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2223 Signed-off-by: Mario Limonciello Reviewed-by: Alex Deucher Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6f958603c8cc..ae10acede495 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4060,15 +4060,18 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev) * at suspend time. * */ -static void amdgpu_device_evict_resources(struct amdgpu_device *adev) +static int amdgpu_device_evict_resources(struct amdgpu_device *adev) { + int ret; + /* No need to evict vram on APUs for suspend to ram or s2idle */ if ((adev->in_s3 || adev->in_s0ix) && (adev->flags & AMD_IS_APU)) - return; + return 0; - if (amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM)) + ret = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM); + if (ret) DRM_WARN("evicting device resources failed\n"); - + return ret; } /* @@ -4118,7 +4121,9 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) if (!adev->in_s0ix) amdgpu_amdkfd_suspend(adev, adev->in_runpm); - amdgpu_device_evict_resources(adev); + r = amdgpu_device_evict_resources(adev); + if (r) + return r; amdgpu_fence_driver_hw_fini(adev); -- cgit v1.2.3 From 087b8542c0b0d26066547bd2a2b08c58fd63df25 Mon Sep 17 00:00:00 2001 From: Graham Sider Date: Wed, 26 Oct 2022 15:08:24 -0400 Subject: drm/amdgpu: disable GFXOFF during compute for GFX11 Temporary workaround to fix issues observed in some compute applications when GFXOFF is enabled on GFX11. Signed-off-by: Graham Sider Acked-by: Alex Deucher Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 37db39ba8718..0d764c15f6bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -706,6 +706,13 @@ err: void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle) { + /* Temporary workaround to fix issues observed in some + * compute applications when GFXOFF is enabled on GFX11. + */ + if (IP_VERSION_MAJ(adev->ip_versions[GC_HWIP][0]) == 11) { + pr_debug("GFXOFF is %s\n", idle ? "enabled" : "disabled"); + amdgpu_gfx_off_ctrl(adev, idle); + } amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_COMPUTE, !idle); -- cgit v1.2.3 From d69a3b762dc4c9fe257b89c2a9ae809770a81d38 Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Mon, 9 May 2022 10:44:10 -0400 Subject: drm/amdkfd: Cleanup kfd_dev struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup kfd_dev struct by removing ddev and pdev as both drm_device and pci_dev can be fetched from amdgpu_device. Signed-off-by: Mukul Joshi Tested-by: Amber Lin Reviewed-by: Felix Kuehling Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 3 +-- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 12 ++++++------ drivers/gpu/drm/amd/amdkfd/kfd_device.c | 16 ++++++---------- drivers/gpu/drm/amd/amdkfd/kfd_iommu.c | 29 +++++++++++++++-------------- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +--- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 12 ++++++------ drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 25 ++++++++++++------------- 9 files changed, 49 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 0d764c15f6bf..8816853e50c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -195,7 +195,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) } adev->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev, - adev_to_drm(adev), &gpu_resources); + &gpu_resources); amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 647220a8762d..f50e3ba4d7a5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -353,7 +353,6 @@ int kgd2kfd_init(void); void kgd2kfd_exit(void); struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf); bool kgd2kfd_device_init(struct kfd_dev *kfd, - struct drm_device *ddev, const struct kgd2kfd_shared_resources *gpu_resources); void kgd2kfd_device_exit(struct kfd_dev *kfd); void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); @@ -381,7 +380,7 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) } static inline -bool kgd2kfd_device_init(struct kfd_dev *kfd, struct drm_device *ddev, +bool kgd2kfd_device_init(struct kfd_dev *kfd, const struct kgd2kfd_shared_resources *gpu_resources) { return false; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 5e0bad7e0b77..339f60a4cddd 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -2114,8 +2114,8 @@ static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev) struct acpi_table_header *table_header = NULL; struct acpi_subtable_header *sub_header = NULL; unsigned long table_end, subtable_len; - u32 pci_id = pci_domain_nr(kdev->pdev->bus) << 16 | - pci_dev_id(kdev->pdev); + u32 pci_id = pci_domain_nr(kdev->adev->pdev->bus) << 16 | + pci_dev_id(kdev->adev->pdev); u32 bdf; acpi_status status; struct acpi_srat_cpu_affinity *cpu; @@ -2190,7 +2190,7 @@ static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev) numa_node = 0; if (numa_node != NUMA_NO_NODE) - set_dev_node(&kdev->pdev->dev, numa_node); + set_dev_node(&kdev->adev->pdev->dev, numa_node); } #endif @@ -2251,14 +2251,14 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size, sub_type_hdr->proximity_domain_from = proximity_domain; #ifdef CONFIG_ACPI_NUMA - if (kdev->pdev->dev.numa_node == NUMA_NO_NODE) + if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE) kfd_find_numa_node_in_srat(kdev); #endif #ifdef CONFIG_NUMA - if (kdev->pdev->dev.numa_node == NUMA_NO_NODE) + if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE) sub_type_hdr->proximity_domain_to = 0; else - sub_type_hdr->proximity_domain_to = kdev->pdev->dev.numa_node; + sub_type_hdr->proximity_domain_to = kdev->adev->pdev->dev.numa_node; #else sub_type_hdr->proximity_domain_to = 0; #endif diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 65a1d4f9004b..ee8e5f8b007d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -227,7 +227,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) { struct kfd_dev *kfd = NULL; const struct kfd2kgd_calls *f2g = NULL; - struct pci_dev *pdev = adev->pdev; uint32_t gfx_target_version = 0; switch (adev->asic_type) { @@ -429,7 +428,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) kfd->adev = adev; kfd_device_info_init(kfd, vf, gfx_target_version); - kfd->pdev = pdev; kfd->init_complete = false; kfd->kfd2kgd = f2g; atomic_set(&kfd->compute_profile, 0); @@ -511,12 +509,10 @@ static void kfd_smi_init(struct kfd_dev *dev) } bool kgd2kfd_device_init(struct kfd_dev *kfd, - struct drm_device *ddev, const struct kgd2kfd_shared_resources *gpu_resources) { unsigned int size, map_process_packet_size; - kfd->ddev = ddev; kfd->mec_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev, KGD_ENGINE_MEC1); kfd->mec2_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev, @@ -541,7 +537,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, kfd->mec_fw_version < kfd->device_info.no_atomic_fw_version)) { dev_info(kfd_device, "skipped device %x:%x, PCI rejects atomics %d<%d\n", - kfd->pdev->vendor, kfd->pdev->device, + kfd->adev->pdev->vendor, kfd->adev->pdev->device, kfd->mec_fw_version, kfd->device_info.no_atomic_fw_version); return false; @@ -650,8 +646,8 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, kfd_smi_init(kfd); kfd->init_complete = true; - dev_info(kfd_device, "added device %x:%x\n", kfd->pdev->vendor, - kfd->pdev->device); + dev_info(kfd_device, "added device %x:%x\n", kfd->adev->pdev->vendor, + kfd->adev->pdev->device); pr_debug("Starting kfd with the following scheduling policy %d\n", kfd->dqm->sched_policy); @@ -676,7 +672,7 @@ alloc_gtt_mem_failure: amdgpu_amdkfd_free_gws(kfd->adev, kfd->gws); dev_err(kfd_device, "device %x:%x NOT added due to errors\n", - kfd->pdev->vendor, kfd->pdev->device); + kfd->adev->pdev->vendor, kfd->adev->pdev->device); out: return kfd->init_complete; } @@ -789,7 +785,7 @@ int kgd2kfd_resume_iommu(struct kfd_dev *kfd) if (err) dev_err(kfd_device, "Failed to resume IOMMU for device %x:%x\n", - kfd->pdev->vendor, kfd->pdev->device); + kfd->adev->pdev->vendor, kfd->adev->pdev->device); return err; } @@ -801,7 +797,7 @@ static int kfd_resume(struct kfd_dev *kfd) if (err) dev_err(kfd_device, "Error starting queue manager for device %x:%x\n", - kfd->pdev->vendor, kfd->pdev->device); + kfd->adev->pdev->vendor, kfd->adev->pdev->device); return err; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c index fbd0afe4da42..ec1bf611624e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c @@ -49,7 +49,7 @@ int kfd_iommu_check_device(struct kfd_dev *kfd) return -ENODEV; iommu_info.flags = 0; - err = amd_iommu_device_info(kfd->pdev, &iommu_info); + err = amd_iommu_device_info(kfd->adev->pdev, &iommu_info); if (err) return err; @@ -71,7 +71,7 @@ int kfd_iommu_device_init(struct kfd_dev *kfd) return 0; iommu_info.flags = 0; - err = amd_iommu_device_info(kfd->pdev, &iommu_info); + err = amd_iommu_device_info(kfd->adev->pdev, &iommu_info); if (err < 0) { dev_err(kfd_device, "error getting iommu info. is the iommu enabled?\n"); @@ -121,7 +121,7 @@ int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd) return -EINVAL; } - err = amd_iommu_bind_pasid(dev->pdev, p->pasid, p->lead_thread); + err = amd_iommu_bind_pasid(dev->adev->pdev, p->pasid, p->lead_thread); if (!err) pdd->bound = PDD_BOUND; @@ -139,7 +139,8 @@ void kfd_iommu_unbind_process(struct kfd_process *p) for (i = 0; i < p->n_pdds; i++) if (p->pdds[i]->bound == PDD_BOUND) - amd_iommu_unbind_pasid(p->pdds[i]->dev->pdev, p->pasid); + amd_iommu_unbind_pasid(p->pdds[i]->dev->adev->pdev, + p->pasid); } /* Callback for process shutdown invoked by the IOMMU driver */ @@ -222,7 +223,7 @@ static int kfd_bind_processes_to_device(struct kfd_dev *kfd) continue; } - err = amd_iommu_bind_pasid(kfd->pdev, p->pasid, + err = amd_iommu_bind_pasid(kfd->adev->pdev, p->pasid, p->lead_thread); if (err < 0) { pr_err("Unexpected pasid 0x%x binding failure\n", @@ -282,9 +283,9 @@ void kfd_iommu_suspend(struct kfd_dev *kfd) kfd_unbind_processes_from_device(kfd); - amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL); - amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL); - amd_iommu_free_device(kfd->pdev); + amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL); + amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL); + amd_iommu_free_device(kfd->adev->pdev); } /** kfd_iommu_resume - Restore IOMMU after resume @@ -302,20 +303,20 @@ int kfd_iommu_resume(struct kfd_dev *kfd) pasid_limit = kfd_get_pasid_limit(); - err = amd_iommu_init_device(kfd->pdev, pasid_limit); + err = amd_iommu_init_device(kfd->adev->pdev, pasid_limit); if (err) return -ENXIO; - amd_iommu_set_invalidate_ctx_cb(kfd->pdev, + amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, iommu_pasid_shutdown_callback); - amd_iommu_set_invalid_ppr_cb(kfd->pdev, + amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, iommu_invalid_ppr_cb); err = kfd_bind_processes_to_device(kfd); if (err) { - amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL); - amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL); - amd_iommu_free_device(kfd->pdev); + amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL); + amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL); + amd_iommu_free_device(kfd->adev->pdev); return err; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index bf610e3b683b..552c3ac85a13 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -254,8 +254,6 @@ struct kfd_dev { struct amdgpu_device *adev; struct kfd_device_info device_info; - struct pci_dev *pdev; - struct drm_device *ddev; unsigned int id; /* topology stub index */ @@ -1365,7 +1363,7 @@ void kfd_dec_compute_active(struct kfd_dev *dev); static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd) { #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF) - struct drm_device *ddev = kfd->ddev; + struct drm_device *ddev = adev_to_drm(kfd->adev); return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR, ddev->render->index, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 951b63677248..a26257171ab7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1050,8 +1050,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) * for auto suspend */ if (pdd->runtime_inuse) { - pm_runtime_mark_last_busy(pdd->dev->ddev->dev); - pm_runtime_put_autosuspend(pdd->dev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(pdd->dev->adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(pdd->dev->adev)->dev); pdd->runtime_inuse = false; } @@ -1633,9 +1633,9 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev, * pdd is destroyed. */ if (!pdd->runtime_inuse) { - err = pm_runtime_get_sync(dev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(dev->adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(dev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(dev->adev)->dev); return ERR_PTR(err); } } @@ -1655,8 +1655,8 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev, out: /* balance runpm reference count and exit with error */ if (!pdd->runtime_inuse) { - pm_runtime_mark_last_busy(dev->ddev->dev); - pm_runtime_put_autosuspend(dev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(dev->adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(dev->adev)->dev); } return ERR_PTR(err); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 0100812478b2..afe7c4998676 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -259,7 +259,7 @@ void svm_range_free_dma_mappings(struct svm_range *prange) pr_debug("failed to find device idx %d\n", gpuidx); continue; } - dev = &pdd->dev->pdev->dev; + dev = &pdd->dev->adev->pdev->dev; svm_range_dma_unmap(dev, dma_addr, 0, prange->npages); kvfree(dma_addr); prange->dma_addr[gpuidx] = NULL; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 3f0a4a415907..ec8c9c10d348 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -115,7 +115,7 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev) down_read(&topology_lock); list_for_each_entry(top_dev, &topology_device_list, list) - if (top_dev->gpu && top_dev->gpu->pdev == pdev) { + if (top_dev->gpu && top_dev->gpu->adev->pdev == pdev) { device = top_dev->gpu; break; } @@ -1169,13 +1169,12 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu) local_mem_size = gpu->local_mem_info.local_mem_size_private + gpu->local_mem_info.local_mem_size_public; - - buf[0] = gpu->pdev->devfn; - buf[1] = gpu->pdev->subsystem_vendor | - (gpu->pdev->subsystem_device << 16); - buf[2] = pci_domain_nr(gpu->pdev->bus); - buf[3] = gpu->pdev->device; - buf[4] = gpu->pdev->bus->number; + buf[0] = gpu->adev->pdev->devfn; + buf[1] = gpu->adev->pdev->subsystem_vendor | + (gpu->adev->pdev->subsystem_device << 16); + buf[2] = pci_domain_nr(gpu->adev->pdev->bus); + buf[3] = gpu->adev->pdev->device; + buf[4] = gpu->adev->pdev->bus->number; buf[5] = lower_32_bits(local_mem_size); buf[6] = upper_32_bits(local_mem_size); @@ -1269,7 +1268,7 @@ static void kfd_set_iolink_no_atomics(struct kfd_topology_device *dev, if (target_gpu_dev) { uint32_t cap; - pcie_capability_read_dword(target_gpu_dev->gpu->pdev, + pcie_capability_read_dword(target_gpu_dev->gpu->adev->pdev, PCI_EXP_DEVCAP2, &cap); if (!(cap & (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | @@ -1688,13 +1687,13 @@ int kfd_topology_add_device(struct kfd_dev *gpu) cu_info.num_shader_arrays_per_engine; dev->node_props.gfx_target_version = gpu->device_info.gfx_target_version; - dev->node_props.vendor_id = gpu->pdev->vendor; - dev->node_props.device_id = gpu->pdev->device; + dev->node_props.vendor_id = gpu->adev->pdev->vendor; + dev->node_props.device_id = gpu->adev->pdev->device; dev->node_props.capability |= ((dev->gpu->adev->rev_id << HSA_CAP_ASIC_REVISION_SHIFT) & HSA_CAP_ASIC_REVISION_MASK); - dev->node_props.location_id = pci_dev_id(gpu->pdev); - dev->node_props.domain = pci_domain_nr(gpu->pdev->bus); + dev->node_props.location_id = pci_dev_id(gpu->adev->pdev); + dev->node_props.domain = pci_domain_nr(gpu->adev->pdev->bus); dev->node_props.max_engine_clk_fcompute = amdgpu_amdkfd_get_max_engine_clock_in_mhz(dev->gpu->adev); dev->node_props.max_engine_clk_ccompute = -- cgit v1.2.3 From 5156133094dd6b57325fa107aca8be5be679452e Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 26 Oct 2022 15:01:09 +0800 Subject: drm/amd/display: make wake_up_aux_channel static This symbol is not used outside of dc_link_dp.c, so marks it static. drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_dp.c:5230:16: warning: no previous prototype for function 'wake_up_aux_channel'. Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=2581 Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 420119efcf5f..e5ab751a5ca1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -5227,7 +5227,7 @@ static void retrieve_cable_id(struct dc_link *link) &link->dpcd_caps.cable_id, &usbc_cable_id); } -enum dc_status wake_up_aux_channel(struct dc_link *link) +static enum dc_status wake_up_aux_channel(struct dc_link *link) { enum dc_status status = DC_ERROR_UNEXPECTED; uint32_t aux_channel_retry_cnt = 0; -- cgit v1.2.3 From 0645b7a64b908ef5cdbf9f117f53d283983fe285 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 26 Oct 2022 15:01:10 +0800 Subject: drm/amd/display: Modify mismatched function name No functional modification involved. drivers/gpu/drm/amd/amdgpu/../display/dc/dc_dmub_srv.c:615: warning: expecting prototype for setup_subvp_dmub_command(). Prototype was for populate_subvp_cmd_pipe_info() instead. Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=2587 Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 774e06936661..67eef5beab95 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -595,7 +595,7 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc, } /** - * setup_subvp_dmub_command - Helper to populate the SubVP pipe info for the DMUB subvp command + * populate_subvp_cmd_pipe_info - Helper to populate the SubVP pipe info for the DMUB subvp command * * @dc: [in] current dc state * @context: [in] new dc state -- cgit v1.2.3 From 08a32902a56e1670850fe5d518d8203e9ce354b8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 18 Oct 2022 15:52:56 +0200 Subject: clk: Remove WARN_ON NULL parent in clk_core_init_rate_req() If a clock has CLK_SET_RATE_PARENT, but core->parent is NULL (most likely because it's orphan), callers of clk_core_init_rate_req() will blindly call this function leading to a very verbose warning. Since it's a fairly common situation, let's just remove the WARN_ON but keep the check that prevents us from dereferencing the pointer. Interestingly, it fixes a regression on the Mediatek MT8195 where the GPU would stall during a clk_set_rate for its main clock. We couldn't come up with a proper explanation since the condition is essentially the same. It was then assumed that it could be timing related since printing the warning stacktrace takes a while, but we couldn't replicate the failure by using fairly large (10ms) mdelays. Fixes: 262ca38f4b6e ("clk: Stop forwarding clk_rate_requests to the parent") Reported-by: AngeloGioacchino Del Regno Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20221018-clk-range-checks-fixes-v1-1-f3ef80518140@cerno.tech Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c3c3f8c07258..37d623c7b73b 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1459,7 +1459,7 @@ static void clk_core_init_rate_req(struct clk_core * const core, { struct clk_core *parent; - if (WARN_ON(!core || !req)) + if (!core || WARN_ON(!req)) return; memset(req, 0, sizeof(*req)); -- cgit v1.2.3 From 2079d029387adfc0cc123f01a6fcf9eb6540ee4d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 18 Oct 2022 15:52:57 +0200 Subject: clk: Initialize the clk_rate_request even if clk_core is NULL Since commit c35e84b09776 ("clk: Introduce clk_hw_init_rate_request()"), users that used to initialize their clk_rate_request by initializing their local structure now rely on clk_hw_init_rate_request(). This function is backed by clk_core_init_rate_req(), which will skip the initialization if either the pointer to struct clk_core or to struct clk_rate_request are NULL. However, the core->parent pointer might be NULL because the clock is orphan, and we will thus end up with our local struct clk_rate_request left untouched. And since clk_hw_init_rate_request() doesn't return an error, we will then call a determine_rate variant with that unitialized structure. In order to avoid this, let's clear our clk_rate_request if the pointer to it is valid but the pointer to struct clk_core isn't. Fixes: c35e84b09776 ("clk: Introduce clk_hw_init_rate_request()") Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20221018-clk-range-checks-fixes-v1-2-f3ef80518140@cerno.tech Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 37d623c7b73b..eb2f9be9b9aa 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1459,11 +1459,14 @@ static void clk_core_init_rate_req(struct clk_core * const core, { struct clk_core *parent; - if (!core || WARN_ON(!req)) + if (WARN_ON(!req)) return; memset(req, 0, sizeof(*req)); + if (!core) + return; + req->rate = rate; clk_core_get_boundaries(core, &req->min_rate, &req->max_rate); -- cgit v1.2.3 From 774560cf28fe115f106b6176c54ec641491136ac Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 18 Oct 2022 15:52:58 +0200 Subject: clk: Initialize max_rate in struct clk_rate_request Since commit b46fd8dbe8ad ("clk: Zero the clk_rate_request structure"), the clk_core_init_rate_req() function clears the struct clk_rate_request passed as argument. However, the default value for max_rate isn't 0 but ULONG_MAX, and we end up creating a clk_rate_request instance where the maximum rate is 0. Let's initialize max_rate to ULONG_MAX properly. Fixes: b46fd8dbe8ad ("clk: Zero the clk_rate_request structure") Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20221018-clk-range-checks-fixes-v1-3-f3ef80518140@cerno.tech Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index eb2f9be9b9aa..57b83665e5c3 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1463,6 +1463,7 @@ static void clk_core_init_rate_req(struct clk_core * const core, return; memset(req, 0, sizeof(*req)); + req->max_rate = ULONG_MAX; if (!core) return; -- cgit v1.2.3 From ffa20aa581cf5377fc397b0d0ff9d67ea823629b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 19 Oct 2022 11:35:35 +0530 Subject: clk: qcom: Update the force mem core bit for GPU clocks There are few GPU clocks which are powering up the memories and thus enable the FORCE_MEM_PERIPH always for these clocks to force the periph_on signal to remain active during halt state of the clock. Fixes: a3cc092196ef ("clk: qcom: Add Global Clock controller (GCC) driver for SC7280") Fixes: 3e0f01d6c7e7 ("clk: qcom: Add graphics clock controller driver for SC7280") Signed-off-by: Taniya Das Signed-off-by: Satya Priya Link: https://lore.kernel.org/r/1666159535-6447-1-git-send-email-quic_c_skakit@quicinc.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sc7280.c | 1 + drivers/clk/qcom/gpucc-sc7280.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/gcc-sc7280.c b/drivers/clk/qcom/gcc-sc7280.c index 8afb7575e712..46d41ebce2b0 100644 --- a/drivers/clk/qcom/gcc-sc7280.c +++ b/drivers/clk/qcom/gcc-sc7280.c @@ -3467,6 +3467,7 @@ static int gcc_sc7280_probe(struct platform_device *pdev) regmap_update_bits(regmap, 0x28004, BIT(0), BIT(0)); regmap_update_bits(regmap, 0x28014, BIT(0), BIT(0)); regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x7100C, BIT(13), BIT(13)); ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, ARRAY_SIZE(gcc_dfs_clocks)); diff --git a/drivers/clk/qcom/gpucc-sc7280.c b/drivers/clk/qcom/gpucc-sc7280.c index 9a832f2bcf49..1490cd45a654 100644 --- a/drivers/clk/qcom/gpucc-sc7280.c +++ b/drivers/clk/qcom/gpucc-sc7280.c @@ -463,6 +463,7 @@ static int gpu_cc_sc7280_probe(struct platform_device *pdev) */ regmap_update_bits(regmap, 0x1170, BIT(0), BIT(0)); regmap_update_bits(regmap, 0x1098, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x1098, BIT(13), BIT(13)); return qcom_cc_really_probe(pdev, &gpu_cc_sc7280_desc, regmap); } -- cgit v1.2.3 From 633efc8b3dc96f56f5a57f2a49764853a2fa3f50 Mon Sep 17 00:00:00 2001 From: Chen Zhongjin Date: Wed, 26 Oct 2022 10:03:21 +0800 Subject: net: dsa: Fix possible memory leaks in dsa_loop_init() kmemleak reported memory leaks in dsa_loop_init(): kmemleak: 12 new suspected memory leaks unreferenced object 0xffff8880138ce000 (size 2048): comm "modprobe", pid 390, jiffies 4295040478 (age 238.976s) backtrace: [<000000006a94f1d5>] kmalloc_trace+0x26/0x60 [<00000000a9c44622>] phy_device_create+0x5d/0x970 [<00000000d0ee2afc>] get_phy_device+0xf3/0x2b0 [<00000000dca0c71f>] __fixed_phy_register.part.0+0x92/0x4e0 [<000000008a834798>] fixed_phy_register+0x84/0xb0 [<0000000055223fcb>] dsa_loop_init+0xa9/0x116 [dsa_loop] ... There are two reasons for memleak in dsa_loop_init(). First, fixed_phy_register() create and register phy_device: fixed_phy_register() get_phy_device() phy_device_create() # freed by phy_device_free() phy_device_register() # freed by phy_device_remove() But fixed_phy_unregister() only calls phy_device_remove(). So the memory allocated in phy_device_create() is leaked. Second, when mdio_driver_register() fail in dsa_loop_init(), it just returns and there is no cleanup for phydevs. Fix the problems by catching the error of mdio_driver_register() in dsa_loop_init(), then calling both fixed_phy_unregister() and phy_device_free() to release phydevs. Also add a function for phydevs cleanup to avoid duplacate. Fixes: 98cd1552ea27 ("net: dsa: Mock-up driver") Signed-off-by: Chen Zhongjin Signed-off-by: David S. Miller --- drivers/net/dsa/dsa_loop.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c index b9107fe40023..5b139f2206b6 100644 --- a/drivers/net/dsa/dsa_loop.c +++ b/drivers/net/dsa/dsa_loop.c @@ -376,6 +376,17 @@ static struct mdio_driver dsa_loop_drv = { #define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2) +static void dsa_loop_phydevs_unregister(void) +{ + unsigned int i; + + for (i = 0; i < NUM_FIXED_PHYS; i++) + if (!IS_ERR(phydevs[i])) { + fixed_phy_unregister(phydevs[i]); + phy_device_free(phydevs[i]); + } +} + static int __init dsa_loop_init(void) { struct fixed_phy_status status = { @@ -383,23 +394,23 @@ static int __init dsa_loop_init(void) .speed = SPEED_100, .duplex = DUPLEX_FULL, }; - unsigned int i; + unsigned int i, ret; for (i = 0; i < NUM_FIXED_PHYS; i++) phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL); - return mdio_driver_register(&dsa_loop_drv); + ret = mdio_driver_register(&dsa_loop_drv); + if (ret) + dsa_loop_phydevs_unregister(); + + return ret; } module_init(dsa_loop_init); static void __exit dsa_loop_exit(void) { - unsigned int i; - mdio_driver_unregister(&dsa_loop_drv); - for (i = 0; i < NUM_FIXED_PHYS; i++) - if (!IS_ERR(phydevs[i])) - fixed_phy_unregister(phydevs[i]); + dsa_loop_phydevs_unregister(); } module_exit(dsa_loop_exit); -- cgit v1.2.3 From 8fdf3f6aba7cfa0c0e2bf66ecca7bb5783acd0d6 Mon Sep 17 00:00:00 2001 From: Radhey Shyam Pandey Date: Wed, 26 Oct 2022 20:45:24 +0530 Subject: net: emaclite: update reset_lock member documentation Instead of generic description, mention what reset_lock actually protects i.e. lock to serialize xmit and tx_timeout execution. Signed-off-by: Radhey Shyam Pandey Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 05848ff15fb5..a3967f8de417 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -108,7 +108,7 @@ * @next_tx_buf_to_use: next Tx buffer to write to * @next_rx_buf_to_use: next Rx buffer to read from * @base_addr: base address of the Emaclite device - * @reset_lock: lock used for synchronization + * @reset_lock: lock to serialize xmit and tx_timeout execution * @deferred_skb: holds an skb (for transmission at a later time) when the * Tx buffer is not free * @phy_dev: pointer to the PHY device -- cgit v1.2.3 From 13c30a755847c7e804e1bf755e66e3ff7b7f9367 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Thu, 20 Oct 2022 09:56:24 +0800 Subject: soundwire: intel: Initialize clock stop timeout The bus->clk_stop_timeout member is only initialized to a non-zero value during the codec driver probe. This can lead to corner cases where this value remains pegged at zero when the bus suspends, which results in an endless loop in sdw_bus_wait_for_clk_prep_deprep(). Corner cases include configurations with no codecs described in the firmware, or delays in probing codec drivers. Initializing the default timeout to the smallest non-zero value avoid this problem and allows for the existing logic to be preserved: the bus->clk_stop_timeout is set as the maximum required by all codecs connected on the bus. Fixes: 1f2dcf3a154ac ("soundwire: intel: set dev_num_ida_min") Signed-off-by: Sjoerd Simons Reviewed-by: Pierre-Louis Bossart Reviewed-by: Chao Song Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20221020015624.1703950-1-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/intel.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 244209358784..8c76541d553f 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -1513,6 +1513,7 @@ static int intel_link_probe(struct auxiliary_device *auxdev, bus->link_id = auxdev->id; bus->dev_num_ida_min = INTEL_DEV_NUM_IDA_MIN; + bus->clk_stop_timeout = 1; sdw_cdns_probe(cdns); -- cgit v1.2.3 From f936fa7a954b262cb3908bbc8f01ba19dfaf9fbf Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 26 Oct 2022 12:02:05 +0100 Subject: soundwire: qcom: reinit broadcast completion For some reason we never reinit the broadcast completion, there is a danger that broadcast commands could be treated as completed by driver from previous complete status. Fix this by reinitializing the completion before sending a broadcast command. Fixes: ddea6cf7b619 ("soundwire: qcom: update register read/write routine") Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20221026110210.6575-2-srinivas.kandagatla@linaro.org Signed-off-by: Vinod Koul --- drivers/soundwire/qcom.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index b33d5db494a5..8f1a1eb017a2 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -344,6 +344,9 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data, if (swrm_wait_for_wr_fifo_avail(swrm)) return SDW_CMD_FAIL_OTHER; + if (cmd_id == SWR_BROADCAST_CMD_ID) + reinit_completion(&swrm->broadcast); + /* Its assumed that write is okay as we do not get any status back */ swrm->reg_write(swrm, SWRM_CMD_FIFO_WR_CMD, val); -- cgit v1.2.3 From 49a467310dc4fae591a3547860ee04d8730780f4 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 26 Oct 2022 12:02:06 +0100 Subject: soundwire: qcom: check for outanding writes before doing a read Reading will increase the fifo count, so check for outstanding cmd wrt. write fifo depth to avoid overflow as read will also increase write fifo cnt. Fixes: a661308c34de ("soundwire: qcom: wait for fifo space to be available before read/write") Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20221026110210.6575-3-srinivas.kandagatla@linaro.org Signed-off-by: Vinod Koul --- drivers/soundwire/qcom.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 8f1a1eb017a2..cee2b2223141 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -380,6 +380,12 @@ static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *swrm, val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr); + /* + * Check for outstanding cmd wrt. write fifo depth to avoid + * overflow as read will also increase write fifo cnt. + */ + swrm_wait_for_wr_fifo_avail(swrm); + /* wait for FIFO RD to complete to avoid overflow */ usleep_range(100, 105); swrm->reg_write(swrm, SWRM_CMD_FIFO_RD_CMD, val); -- cgit v1.2.3 From 04948e757148f870a31f4887ea2239403f516c3c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Oct 2022 18:21:16 +0200 Subject: phy: qcom-qmp-combo: fix NULL-deref on runtime resume Commit fc64623637da ("phy: qcom-qmp-combo,usb: add support for separate PCS_USB region") started treating the PCS_USB registers as potentially separate from the PCS registers but used the wrong base when no PCS_USB offset has been provided. Fix the PCS_USB base used at runtime resume to prevent dereferencing a NULL pointer on platforms that do not provide a PCS_USB offset (e.g. SC7180). Fixes: fc64623637da ("phy: qcom-qmp-combo,usb: add support for separate PCS_USB region") Cc: stable@vger.kernel.org # 5.20 Signed-off-by: Johan Hovold Reviewed-by: Dmitry Baryshkov Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20221026162116.26462-1-johan+linaro@kernel.org Signed-off-by: Vinod Koul --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 9807c4d935cd..ba9d761ec49a 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -2240,7 +2240,7 @@ static void qmp_combo_enable_autonomous_mode(struct qmp_phy *qphy) static void qmp_combo_disable_autonomous_mode(struct qmp_phy *qphy) { const struct qmp_phy_cfg *cfg = qphy->cfg; - void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs_usb; + void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs; void __iomem *pcs_misc = qphy->pcs_misc; /* Disable i/o clamp_n on resume for normal mode */ -- cgit v1.2.3 From 2124becad797245d49252d2d733aee0322233d7e Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 14 Oct 2022 07:11:36 -0500 Subject: ACPI: x86: Add another system to quirk list for forcing StorageD3Enable commit 018d6711c26e4 ("ACPI: x86: Add a quirk for Dell Inspiron 14 2-in-1 for StorageD3Enable") introduced a quirk to allow a system with ambiguous use of _ADR 0 to force StorageD3Enable. Julius Brockmann reports that Inspiron 16 5625 suffers that same symptoms. Add this other system to the list as well. Link: https://bugzilla.kernel.org/show_bug.cgi?id=216440 Reported-and-tested-by: Julius Brockmann Signed-off-by: Mario Limonciello Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/utils.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index f8a2cbdc0ce2..d7d3f1669d4c 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -219,6 +219,12 @@ static const struct dmi_system_id force_storage_d3_dmi[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 14 7425 2-in-1"), } }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 16 5625"), + } + }, {} }; -- cgit v1.2.3 From 07c0d131cc0fe1f3981a42958fc52d573d303d89 Mon Sep 17 00:00:00 2001 From: Chen Zhongjin Date: Tue, 25 Oct 2022 10:41:46 +0800 Subject: RDMA/core: Fix null-ptr-deref in ib_core_cleanup() KASAN reported a null-ptr-deref error: KASAN: null-ptr-deref in range [0x0000000000000118-0x000000000000011f] CPU: 1 PID: 379 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) RIP: 0010:destroy_workqueue+0x2f/0x740 RSP: 0018:ffff888016137df8 EFLAGS: 00000202 ... Call Trace: ib_core_cleanup+0xa/0xa1 [ib_core] __do_sys_delete_module.constprop.0+0x34f/0x5b0 do_syscall_64+0x3a/0x90 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7fa1a0d221b7 ... It is because the fail of roce_gid_mgmt_init() is ignored: ib_core_init() roce_gid_mgmt_init() gid_cache_wq = alloc_ordered_workqueue # fail ... ib_core_cleanup() roce_gid_mgmt_cleanup() destroy_workqueue(gid_cache_wq) # destroy an unallocated wq Fix this by catching the fail of roce_gid_mgmt_init() in ib_core_init(). Fixes: 03db3a2d81e6 ("IB/core: Add RoCE GID table management") Signed-off-by: Chen Zhongjin Link: https://lore.kernel.org/r/20221025024146.109137-1-chenzhongjin@huawei.com Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/device.c | 10 +++++++++- drivers/infiniband/core/nldev.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index ae60c73babcc..b69e2c4e4d2a 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -2815,10 +2815,18 @@ static int __init ib_core_init(void) nldev_init(); rdma_nl_register(RDMA_NL_LS, ibnl_ls_cb_table); - roce_gid_mgmt_init(); + ret = roce_gid_mgmt_init(); + if (ret) { + pr_warn("Couldn't init RoCE GID management\n"); + goto err_parent; + } return 0; +err_parent: + rdma_nl_unregister(RDMA_NL_LS); + nldev_exit(); + unregister_pernet_device(&rdma_dev_net_ops); err_compat: unregister_blocking_lsm_notifier(&ibdev_lsm_nb); err_sa: diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index b92358f606d0..12dc97067ed2 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -2537,7 +2537,7 @@ void __init nldev_init(void) rdma_nl_register(RDMA_NL_NLDEV, nldev_cb_table); } -void __exit nldev_exit(void) +void nldev_exit(void) { rdma_nl_unregister(RDMA_NL_NLDEV); } -- cgit v1.2.3 From 7a47e077e503feb73d56e491ce89aa73b67a3972 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Oct 2022 18:32:32 +0300 Subject: RDMA/qedr: clean up work queue on failure in qedr_alloc_resources() Add a check for if create_singlethread_workqueue() fails and also destroy the work queue on failure paths. Fixes: e411e0587e0d ("RDMA/qedr: Add iWARP connection management functions") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/Y1gBkDucQhhWj5YM@kili Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/qedr/main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index 5152f10d2e6d..ba0c3e4c07d8 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c @@ -344,6 +344,10 @@ static int qedr_alloc_resources(struct qedr_dev *dev) if (IS_IWARP(dev)) { xa_init(&dev->qps); dev->iwarp_wq = create_singlethread_workqueue("qedr_iwarpq"); + if (!dev->iwarp_wq) { + rc = -ENOMEM; + goto err1; + } } /* Allocate Status blocks for CNQ */ @@ -351,7 +355,7 @@ static int qedr_alloc_resources(struct qedr_dev *dev) GFP_KERNEL); if (!dev->sb_array) { rc = -ENOMEM; - goto err1; + goto err_destroy_wq; } dev->cnq_array = kcalloc(dev->num_cnq, @@ -402,6 +406,9 @@ err3: kfree(dev->cnq_array); err2: kfree(dev->sb_array); +err_destroy_wq: + if (IS_IWARP(dev)) + destroy_workqueue(dev->iwarp_wq); err1: kfree(dev->sgid_tbl); return rc; -- cgit v1.2.3 From f11a74b45d330ad1ab986852b099747161052526 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 27 Oct 2022 15:52:31 +0200 Subject: efi: efivars: Fix variable writes with unsupported query_variable_store() Commit 8a254d90a775 ("efi: efivars: Fix variable writes without query_variable_store()") addressed an issue that was introduced during the EFI variable store refactor, where alternative implementations of the efivars layer that lacked query_variable_store() would no longer work. Unfortunately, there is another case to consider here, which was missed: if the efivars layer is backed by the EFI runtime services as usual, but the EFI implementation predates the introduction of QueryVariableInfo(), we will return EFI_UNSUPPORTED, and this is no longer being dealt with correctly. So let's fix this, and while at it, clean up the code a bit, by merging the check_var_size() routines as well as their callers. Cc: # v6.0 Fixes: bbc6d2c6ef22 ("efi: vars: Switch to new wrapper layer") Signed-off-by: Ard Biesheuvel Tested-by: Aditya Garg --- drivers/firmware/efi/vars.c | 68 +++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index 433b61587139..0ba9f18312f5 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c @@ -21,29 +21,22 @@ static struct efivars *__efivars; static DEFINE_SEMAPHORE(efivars_lock); -static efi_status_t check_var_size(u32 attributes, unsigned long size) -{ - const struct efivar_operations *fops; - - fops = __efivars->ops; - - if (!fops->query_variable_store) - return (size <= SZ_64K) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES; - - return fops->query_variable_store(attributes, size, false); -} - -static -efi_status_t check_var_size_nonblocking(u32 attributes, unsigned long size) +static efi_status_t check_var_size(bool nonblocking, u32 attributes, + unsigned long size) { const struct efivar_operations *fops; + efi_status_t status; fops = __efivars->ops; if (!fops->query_variable_store) + status = EFI_UNSUPPORTED; + else + status = fops->query_variable_store(attributes, size, + nonblocking); + if (status == EFI_UNSUPPORTED) return (size <= SZ_64K) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES; - - return fops->query_variable_store(attributes, size, true); + return status; } /** @@ -195,26 +188,6 @@ efi_status_t efivar_get_next_variable(unsigned long *name_size, } EXPORT_SYMBOL_NS_GPL(efivar_get_next_variable, EFIVAR); -/* - * efivar_set_variable_blocking() - local helper function for set_variable - * - * Must be called with efivars_lock held. - */ -static efi_status_t -efivar_set_variable_blocking(efi_char16_t *name, efi_guid_t *vendor, - u32 attr, unsigned long data_size, void *data) -{ - efi_status_t status; - - if (data_size > 0) { - status = check_var_size(attr, data_size + - ucs2_strsize(name, 1024)); - if (status != EFI_SUCCESS) - return status; - } - return __efivars->ops->set_variable(name, vendor, attr, data_size, data); -} - /* * efivar_set_variable_locked() - set a variable identified by name/vendor * @@ -228,23 +201,21 @@ efi_status_t efivar_set_variable_locked(efi_char16_t *name, efi_guid_t *vendor, efi_set_variable_t *setvar; efi_status_t status; - if (!nonblocking) - return efivar_set_variable_blocking(name, vendor, attr, - data_size, data); + if (data_size > 0) { + status = check_var_size(nonblocking, attr, + data_size + ucs2_strsize(name, 1024)); + if (status != EFI_SUCCESS) + return status; + } /* * If no _nonblocking variant exists, the ordinary one * is assumed to be non-blocking. */ - setvar = __efivars->ops->set_variable_nonblocking ?: - __efivars->ops->set_variable; + setvar = __efivars->ops->set_variable_nonblocking; + if (!setvar || !nonblocking) + setvar = __efivars->ops->set_variable; - if (data_size > 0) { - status = check_var_size_nonblocking(attr, data_size + - ucs2_strsize(name, 1024)); - if (status != EFI_SUCCESS) - return status; - } return setvar(name, vendor, attr, data_size, data); } EXPORT_SYMBOL_NS_GPL(efivar_set_variable_locked, EFIVAR); @@ -264,7 +235,8 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor, if (efivar_lock()) return EFI_ABORTED; - status = efivar_set_variable_blocking(name, vendor, attr, data_size, data); + status = efivar_set_variable_locked(name, vendor, attr, data_size, + data, false); efivar_unlock(); return status; } -- cgit v1.2.3 From ae4b3c1252f0fd0951d2f072a02ba46cac8d6c92 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 26 Oct 2022 16:56:33 +0100 Subject: spi: tegra210-quad: Don't initialise DMA if not supported The following error messages are observed on boot for Tegra234 ... ERR KERN tegra-qspi 3270000.spi: cannot use DMA: -19 ERR KERN tegra-qspi 3270000.spi: falling back to PIO Tegra234 does not support DMA for the QSPI and so initialising the DMA is expected to fail. The above error messages are misleading for devices that don't support DMA and so fix this by skipping the DMA initialisation for devices that don't support DMA. Signed-off-by: Jon Hunter Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20221026155633.141792-1-jonathanh@nvidia.com Signed-off-by: Mark Brown --- drivers/spi/spi-tegra210-quad.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index 904972606bd4..10f0c5a6e0dc 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -720,6 +720,9 @@ static int tegra_qspi_start_cpu_based_transfer(struct tegra_qspi *qspi, struct s static void tegra_qspi_deinit_dma(struct tegra_qspi *tqspi) { + if (!tqspi->soc_data->has_dma) + return; + if (tqspi->tx_dma_buf) { dma_free_coherent(tqspi->dev, tqspi->dma_buf_size, tqspi->tx_dma_buf, tqspi->tx_dma_phys); @@ -750,6 +753,9 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi) u32 *dma_buf; int err; + if (!tqspi->soc_data->has_dma) + return 0; + dma_chan = dma_request_chan(tqspi->dev, "rx"); if (IS_ERR(dma_chan)) { err = PTR_ERR(dma_chan); -- cgit v1.2.3 From f5e4ec155d145002fd9840868453d785fab86d42 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Fri, 28 Oct 2022 17:00:42 +0100 Subject: random: use arch_get_random*_early() in random_init() While reworking the archrandom handling, commit d349ab99eec7 ("random: handle archrandom with multiple longs") switched to the non-early archrandom helpers in random_init(), which broke initialization of the entropy pool from the arm64 random generator. Indeed at that point the arm64 CPU features, which verify that all CPUs have compatible capabilities, are not finalized so arch_get_random_seed_longs() is unsuccessful. Instead random_init() should use the _early functions, which check only the boot CPU on arm64. On other architectures the _early functions directly call the normal ones. Fixes: d349ab99eec7 ("random: handle archrandom with multiple longs") Cc: stable@vger.kernel.org Signed-off-by: Jean-Philippe Brucker Signed-off-by: Jason A. Donenfeld --- drivers/char/random.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/random.c b/drivers/char/random.c index 2fe28eeb2f38..69754155300e 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -791,13 +791,13 @@ void __init random_init_early(const char *command_line) #endif for (i = 0, arch_bits = sizeof(entropy) * 8; i < ARRAY_SIZE(entropy);) { - longs = arch_get_random_seed_longs(entropy, ARRAY_SIZE(entropy) - i); + longs = arch_get_random_seed_longs_early(entropy, ARRAY_SIZE(entropy) - i); if (longs) { _mix_pool_bytes(entropy, sizeof(*entropy) * longs); i += longs; continue; } - longs = arch_get_random_longs(entropy, ARRAY_SIZE(entropy) - i); + longs = arch_get_random_longs_early(entropy, ARRAY_SIZE(entropy) - i); if (longs) { _mix_pool_bytes(entropy, sizeof(*entropy) * longs); i += longs; -- cgit v1.2.3 From 21ce2c121fa07b00b0906bd781590ea362e82ea2 Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Thu, 27 Oct 2022 12:56:55 +0300 Subject: net: ethernet: adi: adin1110: Fix notifiers ADIN1110 was registering netdev_notifiers on each device probe. This leads to warnings/probe failures because of double registration of the same notifier when to adin1110/2111 devices are connected to the same system. Move the registration of netdev_notifiers in module init call, in this way multiple driver instances can use the same notifiers. Fixes: bc93e19d088b ("net: ethernet: adi: Add ADIN1110 support") Signed-off-by: Alexandru Tachici Link: https://lore.kernel.org/r/20221027095655.89890-2-alexandru.tachici@analog.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/adi/adin1110.c | 38 ++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c index 1744d623999d..606c97610808 100644 --- a/drivers/net/ethernet/adi/adin1110.c +++ b/drivers/net/ethernet/adi/adin1110.c @@ -1512,16 +1512,15 @@ static struct notifier_block adin1110_switchdev_notifier = { .notifier_call = adin1110_switchdev_event, }; -static void adin1110_unregister_notifiers(void *data) +static void adin1110_unregister_notifiers(void) { unregister_switchdev_blocking_notifier(&adin1110_switchdev_blocking_notifier); unregister_switchdev_notifier(&adin1110_switchdev_notifier); unregister_netdevice_notifier(&adin1110_netdevice_nb); } -static int adin1110_setup_notifiers(struct adin1110_priv *priv) +static int adin1110_setup_notifiers(void) { - struct device *dev = &priv->spidev->dev; int ret; ret = register_netdevice_notifier(&adin1110_netdevice_nb); @@ -1536,13 +1535,14 @@ static int adin1110_setup_notifiers(struct adin1110_priv *priv) if (ret < 0) goto err_sdev; - return devm_add_action_or_reset(dev, adin1110_unregister_notifiers, NULL); + return 0; err_sdev: unregister_switchdev_notifier(&adin1110_switchdev_notifier); err_netdev: unregister_netdevice_notifier(&adin1110_netdevice_nb); + return ret; } @@ -1613,10 +1613,6 @@ static int adin1110_probe_netdevs(struct adin1110_priv *priv) if (ret < 0) return ret; - ret = adin1110_setup_notifiers(priv); - if (ret < 0) - return ret; - for (i = 0; i < priv->cfg->ports_nr; i++) { ret = devm_register_netdev(dev, priv->ports[i]->netdev); if (ret < 0) { @@ -1693,7 +1689,31 @@ static struct spi_driver adin1110_driver = { .probe = adin1110_probe, .id_table = adin1110_spi_id, }; -module_spi_driver(adin1110_driver); + +static int __init adin1110_driver_init(void) +{ + int ret; + + ret = adin1110_setup_notifiers(); + if (ret < 0) + return ret; + + ret = spi_register_driver(&adin1110_driver); + if (ret < 0) { + adin1110_unregister_notifiers(); + return ret; + } + + return 0; +} + +static void __exit adin1110_exit(void) +{ + adin1110_unregister_notifiers(); + spi_unregister_driver(&adin1110_driver); +} +module_init(adin1110_driver_init); +module_exit(adin1110_exit); MODULE_DESCRIPTION("ADIN1110 Network driver"); MODULE_AUTHOR("Alexandru Tachici "); -- cgit v1.2.3 From 0ba7b623f15d52fa056eca26573d8cf1b9c29fd1 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 22 Oct 2022 08:08:55 +0200 Subject: soc: imx: imx93-pd: Fix the error handling path of imx93_pd_probe() In imx93_pd_probe(); if an error occurs, some resources need to be released as done in the remove function. Fixes: 0a0f7cc25d4a ("soc: imx: add i.MX93 SRC power domain driver") Signed-off-by: Christophe JAILLET Signed-off-by: Shawn Guo --- drivers/soc/imx/imx93-pd.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/imx/imx93-pd.c b/drivers/soc/imx/imx93-pd.c index 1f3d7039c1de..4d235c8c4924 100644 --- a/drivers/soc/imx/imx93-pd.c +++ b/drivers/soc/imx/imx93-pd.c @@ -135,11 +135,24 @@ static int imx93_pd_probe(struct platform_device *pdev) ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off); if (ret) - return ret; + goto err_clk_unprepare; platform_set_drvdata(pdev, domain); - return of_genpd_add_provider_simple(np, &domain->genpd); + ret = of_genpd_add_provider_simple(np, &domain->genpd); + if (ret) + goto err_genpd_remove; + + return 0; + +err_genpd_remove: + pm_genpd_remove(&domain->genpd); + +err_clk_unprepare: + if (!domain->init_off) + clk_bulk_disable_unprepare(domain->num_clks, domain->clks); + + return ret; } static const struct of_device_id imx93_pd_ids[] = { -- cgit v1.2.3 From fbe605ab157b174385b3f19ce33928d3548a9b09 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Sat, 29 Oct 2022 16:29:31 +0800 Subject: platform/loongarch: laptop: Adjust resume order for loongson_hotkey_resume() Some laptops don't support SW_LID, but still have backlight control, move backlight resuming before SW_LID event handling so as to avoid backlight mistake due to early return. Signed-off-by: Huacai Chen --- drivers/platform/loongarch/loongson-laptop.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/loongarch/loongson-laptop.c b/drivers/platform/loongarch/loongson-laptop.c index f0166ad5d2c2..0e6f4efe21e5 100644 --- a/drivers/platform/loongarch/loongson-laptop.c +++ b/drivers/platform/loongarch/loongson-laptop.c @@ -199,6 +199,13 @@ static int loongson_hotkey_resume(struct device *dev) struct key_entry ke; struct backlight_device *bd; + bd = backlight_device_get_by_type(BACKLIGHT_PLATFORM); + if (bd) { + loongson_laptop_backlight_update(bd) ? + pr_warn("Loongson_backlight: resume brightness failed") : + pr_info("Loongson_backlight: resume brightness %d\n", bd->props.brightness); + } + /* * Only if the firmware supports SW_LID event model, we can handle the * event. This is for the consideration of development board without EC. @@ -228,13 +235,6 @@ static int loongson_hotkey_resume(struct device *dev) } } - bd = backlight_device_get_by_type(BACKLIGHT_PLATFORM); - if (bd) { - loongson_laptop_backlight_update(bd) ? - pr_warn("Loongson_backlight: resume brightness failed") : - pr_info("Loongson_backlight: resume brightness %d\n", bd->props.brightness); - } - return 0; } -- cgit v1.2.3 From d81916910f7498fe7a768697e0101d488f9fe665 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sat, 29 Oct 2022 16:29:31 +0800 Subject: platform/loongarch: laptop: Fix possible UAF and simplify generic_acpi_laptop_init() Currently the return value of 'sub_driver->init' is not checked. If sparse_keymap_setup() called in the init function fails, 'generic_ inputdev' is freed, then it will lead a UAF when using it in generic_ acpi_laptop_init(). Fix it by checking the return value and setting generic_inputdev to NULL after free, so as to avoid double free it. The error code in generic_subdriver_init() is always negative, so the return of generic_subdriver_init() can be simplified. Fixes: 6246ed09111f ("LoongArch: Add ACPI-based generic laptop driver") Signed-off-by: Yang Yingliang Signed-off-by: Huacai Chen --- drivers/platform/loongarch/loongson-laptop.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/loongarch/loongson-laptop.c b/drivers/platform/loongarch/loongson-laptop.c index 0e6f4efe21e5..99203584949d 100644 --- a/drivers/platform/loongarch/loongson-laptop.c +++ b/drivers/platform/loongarch/loongson-laptop.c @@ -448,6 +448,7 @@ static int __init event_init(struct generic_sub_driver *sub_driver) if (ret < 0) { pr_err("Failed to setup input device keymap\n"); input_free_device(generic_inputdev); + generic_inputdev = NULL; return ret; } @@ -502,8 +503,11 @@ static int __init generic_subdriver_init(struct generic_sub_driver *sub_driver) if (ret) return -EINVAL; - if (sub_driver->init) - sub_driver->init(sub_driver); + if (sub_driver->init) { + ret = sub_driver->init(sub_driver); + if (ret) + goto err_out; + } if (sub_driver->notify) { ret = setup_acpi_notify(sub_driver); @@ -519,7 +523,7 @@ static int __init generic_subdriver_init(struct generic_sub_driver *sub_driver) err_out: generic_subdriver_exit(sub_driver); - return (ret < 0) ? ret : 0; + return ret; } static void generic_subdriver_exit(struct generic_sub_driver *sub_driver) -- cgit v1.2.3 From 57572cacd36e6d4be7722d7770d23f4430219827 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 2 Oct 2022 15:41:33 +0100 Subject: iio: accel: bma400: Ensure VDDIO is enable defore reading the chip ID. The regulator enables were after the check on the chip variant, which was very unlikely to return a correct value when not powered. Presumably all the device anyone is testing on have a regulator that is already powered up when this code runs for reasons beyond the scope of this driver. Move the read call down a few lines. Fixes: 3cf7ded15e40 ("iio: accel: bma400: basic regulator support") Signed-off-by: Jonathan Cameron Reviewed-by: Dan Robertson Cc: Link: https://lore.kernel.org/r/20221002144133.3771029-1-jic23@kernel.org --- drivers/iio/accel/bma400_core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index ad8fce3e08cd..490c342ef72a 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -869,18 +869,6 @@ static int bma400_init(struct bma400_data *data) unsigned int val; int ret; - /* Try to read chip_id register. It must return 0x90. */ - ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val); - if (ret) { - dev_err(data->dev, "Failed to read chip id register\n"); - return ret; - } - - if (val != BMA400_ID_REG_VAL) { - dev_err(data->dev, "Chip ID mismatch\n"); - return -ENODEV; - } - data->regulators[BMA400_VDD_REGULATOR].supply = "vdd"; data->regulators[BMA400_VDDIO_REGULATOR].supply = "vddio"; ret = devm_regulator_bulk_get(data->dev, @@ -906,6 +894,18 @@ static int bma400_init(struct bma400_data *data) if (ret) return ret; + /* Try to read chip_id register. It must return 0x90. */ + ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val); + if (ret) { + dev_err(data->dev, "Failed to read chip id register\n"); + return ret; + } + + if (val != BMA400_ID_REG_VAL) { + dev_err(data->dev, "Chip ID mismatch\n"); + return -ENODEV; + } + ret = bma400_get_power_mode(data); if (ret) { dev_err(data->dev, "Failed to get the initial power-mode\n"); -- cgit v1.2.3 From 17f442e7e47579d3881fc4d47354eaef09302e6f Mon Sep 17 00:00:00 2001 From: Mitja Spes Date: Fri, 21 Oct 2022 15:58:20 +0200 Subject: iio: pressure: ms5611: fixed value compensation bug When using multiple instances of this driver the compensation PROM was overwritten by the last initialized sensor. Now each sensor has own PROM storage. Signed-off-by: Mitja Spes Fixes: 9690d81a02dc ("iio: pressure: ms5611: add support for MS5607 temperature and pressure sensor") Link: https://lore.kernel.org/r/20221021135827.1444793-2-mitja@lxnav.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5611.h | 12 +++------ drivers/iio/pressure/ms5611_core.c | 51 ++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h index cbc9349c342a..550b75b7186f 100644 --- a/drivers/iio/pressure/ms5611.h +++ b/drivers/iio/pressure/ms5611.h @@ -25,13 +25,6 @@ enum { MS5607, }; -struct ms5611_chip_info { - u16 prom[MS5611_PROM_WORDS_NB]; - - int (*temp_and_pressure_compensate)(struct ms5611_chip_info *chip_info, - s32 *temp, s32 *pressure); -}; - /* * OverSampling Rate descriptor. * Warning: cmd MUST be kept aligned on a word boundary (see @@ -50,12 +43,15 @@ struct ms5611_state { const struct ms5611_osr *pressure_osr; const struct ms5611_osr *temp_osr; + u16 prom[MS5611_PROM_WORDS_NB]; + int (*reset)(struct ms5611_state *st); int (*read_prom_word)(struct ms5611_state *st, int index, u16 *word); int (*read_adc_temp_and_pressure)(struct ms5611_state *st, s32 *temp, s32 *pressure); - struct ms5611_chip_info *chip_info; + int (*compensate_temp_and_pressure)(struct ms5611_state *st, s32 *temp, + s32 *pressure); struct regulator *vdd; }; diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 717521de66c4..c564a1d6cafe 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -85,7 +85,7 @@ static int ms5611_read_prom(struct iio_dev *indio_dev) struct ms5611_state *st = iio_priv(indio_dev); for (i = 0; i < MS5611_PROM_WORDS_NB; i++) { - ret = st->read_prom_word(st, i, &st->chip_info->prom[i]); + ret = st->read_prom_word(st, i, &st->prom[i]); if (ret < 0) { dev_err(&indio_dev->dev, "failed to read prom at %d\n", i); @@ -93,7 +93,7 @@ static int ms5611_read_prom(struct iio_dev *indio_dev) } } - if (!ms5611_prom_is_valid(st->chip_info->prom, MS5611_PROM_WORDS_NB)) { + if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) { dev_err(&indio_dev->dev, "PROM integrity check failed\n"); return -ENODEV; } @@ -114,21 +114,20 @@ static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev, return ret; } - return st->chip_info->temp_and_pressure_compensate(st->chip_info, - temp, pressure); + return st->compensate_temp_and_pressure(st, temp, pressure); } -static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info, +static int ms5611_temp_and_pressure_compensate(struct ms5611_state *st, s32 *temp, s32 *pressure) { s32 t = *temp, p = *pressure; s64 off, sens, dt; - dt = t - (chip_info->prom[5] << 8); - off = ((s64)chip_info->prom[2] << 16) + ((chip_info->prom[4] * dt) >> 7); - sens = ((s64)chip_info->prom[1] << 15) + ((chip_info->prom[3] * dt) >> 8); + dt = t - (st->prom[5] << 8); + off = ((s64)st->prom[2] << 16) + ((st->prom[4] * dt) >> 7); + sens = ((s64)st->prom[1] << 15) + ((st->prom[3] * dt) >> 8); - t = 2000 + ((chip_info->prom[6] * dt) >> 23); + t = 2000 + ((st->prom[6] * dt) >> 23); if (t < 2000) { s64 off2, sens2, t2; @@ -154,17 +153,17 @@ static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_inf return 0; } -static int ms5607_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info, +static int ms5607_temp_and_pressure_compensate(struct ms5611_state *st, s32 *temp, s32 *pressure) { s32 t = *temp, p = *pressure; s64 off, sens, dt; - dt = t - (chip_info->prom[5] << 8); - off = ((s64)chip_info->prom[2] << 17) + ((chip_info->prom[4] * dt) >> 6); - sens = ((s64)chip_info->prom[1] << 16) + ((chip_info->prom[3] * dt) >> 7); + dt = t - (st->prom[5] << 8); + off = ((s64)st->prom[2] << 17) + ((st->prom[4] * dt) >> 6); + sens = ((s64)st->prom[1] << 16) + ((st->prom[3] * dt) >> 7); - t = 2000 + ((chip_info->prom[6] * dt) >> 23); + t = 2000 + ((st->prom[6] * dt) >> 23); if (t < 2000) { s64 off2, sens2, t2, tmp; @@ -342,15 +341,6 @@ static int ms5611_write_raw(struct iio_dev *indio_dev, static const unsigned long ms5611_scan_masks[] = {0x3, 0}; -static struct ms5611_chip_info chip_info_tbl[] = { - [MS5611] = { - .temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate, - }, - [MS5607] = { - .temp_and_pressure_compensate = ms5607_temp_and_pressure_compensate, - } -}; - static const struct iio_chan_spec ms5611_channels[] = { { .type = IIO_PRESSURE, @@ -433,7 +423,20 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, struct ms5611_state *st = iio_priv(indio_dev); mutex_init(&st->lock); - st->chip_info = &chip_info_tbl[type]; + + switch (type) { + case MS5611: + st->compensate_temp_and_pressure = + ms5611_temp_and_pressure_compensate; + break; + case MS5607: + st->compensate_temp_and_pressure = + ms5607_temp_and_pressure_compensate; + break; + default: + return -EINVAL; + } + st->temp_osr = &ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1]; st->pressure_osr = -- cgit v1.2.3 From 741cec30cc52058d1c10d415f3b98319887e4f73 Mon Sep 17 00:00:00 2001 From: Mitja Spes Date: Fri, 21 Oct 2022 15:58:21 +0200 Subject: iio: pressure: ms5611: changed hardcoded SPI speed to value limited Don't hardcode the ms5611 SPI speed, limit it instead. Signed-off-by: Mitja Spes Fixes: c0644160a8b5 ("iio: pressure: add support for MS5611 pressure and temperature sensor") Link: https://lore.kernel.org/r/20221021135827.1444793-3-mitja@lxnav.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5611_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index 432e912096f4..a0a7205c9c3a 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -91,7 +91,7 @@ static int ms5611_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); spi->mode = SPI_MODE_0; - spi->max_speed_hz = 20000000; + spi->max_speed_hz = min(spi->max_speed_hz, 20000000U); spi->bits_per_word = 8; ret = spi_setup(spi); if (ret < 0) -- cgit v1.2.3 From 1eb20332a082fa801fb89c347c5e62de916a4001 Mon Sep 17 00:00:00 2001 From: Saravanan Sekar Date: Sat, 29 Oct 2022 11:29:53 +0200 Subject: iio: adc: mp2629: fix wrong comparison of channel Input voltage channel enum is compared against iio address instead of the channel. Fixes: 7abd9fb64682 ("iio: adc: mp2629: Add support for mp2629 ADC driver") Signed-off-by: Saravanan Sekar Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221029093000.45451-2-sravanhome@gmail.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mp2629_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c index 30a31f185d08..f7af9af1665d 100644 --- a/drivers/iio/adc/mp2629_adc.c +++ b/drivers/iio/adc/mp2629_adc.c @@ -74,7 +74,7 @@ static int mp2629_read_raw(struct iio_dev *indio_dev, if (ret) return ret; - if (chan->address == MP2629_INPUT_VOLT) + if (chan->channel == MP2629_INPUT_VOLT) rval &= GENMASK(6, 0); *val = rval; return IIO_VAL_INT; -- cgit v1.2.3 From bfab00b94bd8569cdb84a6511d6615e6a8104e9c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 26 Sep 2022 22:37:52 +0200 Subject: drm/rockchip: dw_hdmi: filter regulator -EPROBE_DEFER error messages When the avdd-0v9 or avdd-1v8 supply are not yet available, EPROBE_DEFER is returned by rockchip_hdmi_parse_dt(). This causes the following error message to be printed multiple times: dwhdmi-rockchip fe0a0000.hdmi: [drm:dw_hdmi_rockchip_bind [rockchipdrm]] *ERROR* Unable to parse OF data Fix that by not printing the message when rockchip_hdmi_parse_dt() returns -EPROBE_DEFER. Fixes: ca80c4eb4b01 ("drm/rockchip: dw_hdmi: add regulator support") Signed-off-by: Aurelien Jarno Reviewed-by: Dmitry Osipenko Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20220926203752.5430-1-aurelien@aurel32.net --- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index c14f88893868..2f4b8f64cbad 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -565,7 +565,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, ret = rockchip_hdmi_parse_dt(hdmi); if (ret) { - DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n"); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n"); return ret; } -- cgit v1.2.3 From 0be67e0556e469c57100ffe3c90df90abc796f3b Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 19 Oct 2022 17:03:48 -0700 Subject: drm/rockchip: dsi: Clean up 'usage_mode' when failing to attach If we fail to attach the first time (especially: EPROBE_DEFER), we fail to clean up 'usage_mode', and thus will fail to attach on any subsequent attempts, with "dsi controller already in use". Re-set to DW_DSI_USAGE_IDLE on attach failure. This is especially common to hit when enabling asynchronous probe on a duel-DSI system (such as RK3399 Gru/Scarlet), such that we're more likely to fail dw_mipi_dsi_rockchip_find_second() the first time. Fixes: 71f68fe7f121 ("drm/rockchip: dsi: add ability to work as a phy instead of full dsi") Cc: Signed-off-by: Brian Norris Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20221019170255.1.Ia68dfb27b835d31d22bfe23812baf366ee1c6eac@changeid --- drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index bf6948125b84..d222c6811207 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -1051,23 +1051,31 @@ static int dw_mipi_dsi_rockchip_host_attach(void *priv_data, if (ret) { DRM_DEV_ERROR(dsi->dev, "Failed to register component: %d\n", ret); - return ret; + goto out; } second = dw_mipi_dsi_rockchip_find_second(dsi); - if (IS_ERR(second)) - return PTR_ERR(second); + if (IS_ERR(second)) { + ret = PTR_ERR(second); + goto out; + } if (second) { ret = component_add(second, &dw_mipi_dsi_rockchip_ops); if (ret) { DRM_DEV_ERROR(second, "Failed to register component: %d\n", ret); - return ret; + goto out; } } return 0; + +out: + mutex_lock(&dsi->usage_mutex); + dsi->usage_mode = DW_DSI_USAGE_IDLE; + mutex_unlock(&dsi->usage_mutex); + return ret; } static int dw_mipi_dsi_rockchip_host_detach(void *priv_data, -- cgit v1.2.3 From 81e592f86f7afdb76d655e7fbd7803d7b8f985d8 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 19 Oct 2022 17:03:49 -0700 Subject: drm/rockchip: dsi: Force synchronous probe We can't safely probe a dual-DSI display asynchronously (driver_async_probe='*' or driver_async_probe='dw-mipi-dsi-rockchip' cmdline), because dw_mipi_dsi_rockchip_find_second() pokes one DSI device's drvdata from the other device without any locking. Request synchronous probe, at least until this driver learns some appropriate locking for dual-DSI initialization. Cc: Signed-off-by: Brian Norris Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20221019170255.2.I6b985b0ca372b7e35c6d9ea970b24bcb262d4fc1@changeid --- drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index d222c6811207..528ddce144e5 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -1689,5 +1689,11 @@ struct platform_driver dw_mipi_dsi_rockchip_driver = { .of_match_table = dw_mipi_dsi_rockchip_dt_ids, .pm = &dw_mipi_dsi_rockchip_pm_ops, .name = "dw-mipi-dsi-rockchip", + /* + * For dual-DSI display, one DSI pokes at the other DSI's + * drvdata in dw_mipi_dsi_rockchip_find_second(). This is not + * safe for asynchronous probe. + */ + .probe_type = PROBE_FORCE_SYNCHRONOUS, }, }; -- cgit v1.2.3 From ab78c74cfc5a3caa2bbb7627cb8f3bca40bb5fb0 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Thu, 20 Oct 2022 19:12:47 +0100 Subject: drm/rockchip: fix fbdev on non-IOMMU devices When switching to the generic fbdev infrastructure, it was missed that framebuffers were created with the alloc_kmap parameter to rockchip_gem_create_object() set to true. The generic infrastructure calls this via the .dumb_create() driver operation and thus creates a buffer without an associated kmap. alloc_kmap only makes a difference on devices without an IOMMU, but when it is missing rockchip_gem_prime_vmap() fails and the framebuffer cannot be used. Detect the case where a buffer is being allocated for the framebuffer and ensure a kernel mapping is created in this case. Fixes: 24af7c34b290 ("drm/rockchip: use generic fbdev setup") Reported-by: Johan Jonker Cc: Thomas Zimmermann Signed-off-by: John Keeping Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20221020181248.2497065-1-john@metanate.com --- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 614e97aaac80..da8a69953706 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -364,9 +364,12 @@ rockchip_gem_create_with_handle(struct drm_file *file_priv, { struct rockchip_gem_object *rk_obj; struct drm_gem_object *obj; + bool is_framebuffer; int ret; - rk_obj = rockchip_gem_create_object(drm, size, false); + is_framebuffer = drm->fb_helper && file_priv == drm->fb_helper->client.file; + + rk_obj = rockchip_gem_create_object(drm, size, is_framebuffer); if (IS_ERR(rk_obj)) return ERR_CAST(rk_obj); -- cgit v1.2.3 From 553c5a429aee26c9cfaf37ae158a8915540270fe Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sun, 23 Oct 2022 18:07:47 +0200 Subject: drm/rockchip: dsi: Fix VOP selection on SoCs that support it lcdsel_grf_reg is defined as u32, so "< 0" comaprison is always false, which breaks VOP selection on eg. RK3399. Compare against 0. Fixes: f3aaa6125b6f ("drm/rockchip: dsi: add rk3568 support") Signed-off-by: Ondrej Jirman Tested-by: Chris Morgan Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20221023160747.607943-1-megi@xff.cz --- drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 528ddce144e5..f4df9820b295 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -752,7 +752,7 @@ static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi) static void dw_mipi_dsi_rockchip_set_lcdsel(struct dw_mipi_dsi_rockchip *dsi, int mux) { - if (dsi->cdata->lcdsel_grf_reg < 0) + if (dsi->cdata->lcdsel_grf_reg) regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg, mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big); } @@ -1643,7 +1643,6 @@ static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = { static const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = { { .reg = 0xfe060000, - .lcdsel_grf_reg = -1, .lanecfg1_grf_reg = RK3568_GRF_VO_CON2, .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI0_SKEWCALHS | RK3568_DSI0_FORCETXSTOPMODE | @@ -1653,7 +1652,6 @@ static const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = { }, { .reg = 0xfe070000, - .lcdsel_grf_reg = -1, .lanecfg1_grf_reg = RK3568_GRF_VO_CON3, .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI1_SKEWCALHS | RK3568_DSI1_FORCETXSTOPMODE | -- cgit v1.2.3 From 471bf2406c043491b1a8288e5f04bc278f7d7ca1 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Fri, 28 Oct 2022 11:52:05 +0200 Subject: drm/rockchip: vop2: fix null pointer in plane_atomic_disable If the vop2_plane_atomic_disable function is called with NULL as a state, accessing the old_pstate runs into a null pointer exception. However, the drm_atomic_helper_disable_planes_on_crtc function calls the atomic_disable callback with state NULL. Allow to disable a plane without passing a plane state by checking the old_pstate only if a state is passed. Signed-off-by: Michael Tretter Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20221028095206.2136601-2-m.tretter@pengutronix.de --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index aac20be5ac08..26f8a8489ded 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -996,13 +996,15 @@ static int vop2_plane_atomic_check(struct drm_plane *plane, static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *state) { - struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane); + struct drm_plane_state *old_pstate = NULL; struct vop2_win *win = to_vop2_win(plane); struct vop2 *vop2 = win->vop2; drm_dbg(vop2->drm, "%s disable\n", win->data->name); - if (!old_pstate->crtc) + if (state) + old_pstate = drm_atomic_get_old_plane_state(state, plane); + if (old_pstate && !old_pstate->crtc) return; vop2_win_disable(win); -- cgit v1.2.3 From 447fb14bf07905b880c9ed1ea92c53d6dd0649d7 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Fri, 28 Oct 2022 11:52:06 +0200 Subject: drm/rockchip: vop2: disable planes when disabling the crtc The vop2 driver needs to explicitly disable the planes if the crtc is disabled. Unless the planes are explicitly disabled, the address of the last framebuffer is kept in the registers of the VOP2. When re-enabling the encoder after it has been disabled by the driver, the VOP2 will start and read the framebuffer that has been freed but is still pointed to by the register. The iommu will catch these read accesses and print errors. Explicitly disable the planes when the crtc is disabled to reset the registers. Signed-off-by: Michael Tretter Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20221028095206.2136601-3-m.tretter@pengutronix.de --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 26f8a8489ded..105a548d0abe 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -877,10 +877,14 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, { struct vop2_video_port *vp = to_vop2_video_port(crtc); struct vop2 *vop2 = vp->vop2; + struct drm_crtc_state *old_crtc_state; int ret; vop2_lock(vop2); + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); + drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false); + drm_crtc_vblank_off(crtc); /* -- cgit v1.2.3 From 8e4aae6b8ca76afb1fb64dcb24be44ba814e7f8a Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Thu, 27 Oct 2022 22:03:29 +0800 Subject: nfc: fdp: Fix potential memory leak in fdp_nci_send() fdp_nci_send() will call fdp_nci_i2c_write that will not free skb in the function. As a result, when fdp_nci_i2c_write() finished, the skb will memleak. fdp_nci_send() should free skb after fdp_nci_i2c_write() finished. Fixes: a06347c04c13 ("NFC: Add Intel Fields Peak NFC solution driver") Signed-off-by: Shang XiaoJing Signed-off-by: David S. Miller --- drivers/nfc/fdp/fdp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c index c6b3334f24c9..f12f903a9dd1 100644 --- a/drivers/nfc/fdp/fdp.c +++ b/drivers/nfc/fdp/fdp.c @@ -249,11 +249,19 @@ static int fdp_nci_close(struct nci_dev *ndev) static int fdp_nci_send(struct nci_dev *ndev, struct sk_buff *skb) { struct fdp_nci_info *info = nci_get_drvdata(ndev); + int ret; if (atomic_dec_and_test(&info->data_pkt_counter)) info->data_pkt_counter_cb(ndev); - return info->phy_ops->write(info->phy, skb); + ret = info->phy_ops->write(info->phy, skb); + if (ret < 0) { + kfree_skb(skb); + return ret; + } + + consume_skb(skb); + return 0; } static int fdp_nci_request_firmware(struct nci_dev *ndev) -- cgit v1.2.3 From 7bf1ed6aff0f70434bd0cdd45495e83f1dffb551 Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Thu, 27 Oct 2022 22:03:30 +0800 Subject: nfc: nxp-nci: Fix potential memory leak in nxp_nci_send() nxp_nci_send() will call nxp_nci_i2c_write(), and only free skb when nxp_nci_i2c_write() failed. However, even if the nxp_nci_i2c_write() run succeeds, the skb will not be freed in nxp_nci_i2c_write(). As the result, the skb will memleak. nxp_nci_send() should also free the skb when nxp_nci_i2c_write() succeeds. Fixes: dece45855a8b ("NFC: nxp-nci: Add support for NXP NCI chips") Signed-off-by: Shang XiaoJing Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/nfc/nxp-nci/core.c b/drivers/nfc/nxp-nci/core.c index 7c93d484dc1b..580cb6ecffee 100644 --- a/drivers/nfc/nxp-nci/core.c +++ b/drivers/nfc/nxp-nci/core.c @@ -80,10 +80,13 @@ static int nxp_nci_send(struct nci_dev *ndev, struct sk_buff *skb) return -EINVAL; r = info->phy_ops->write(info->phy_id, skb); - if (r < 0) + if (r < 0) { kfree_skb(skb); + return r; + } - return r; + consume_skb(skb); + return 0; } static int nxp_nci_rf_pll_unlocked_ntf(struct nci_dev *ndev, -- cgit v1.2.3 From 3a146b7e3099dc7cf3114f627d9b79291e2d2203 Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Thu, 27 Oct 2022 22:03:31 +0800 Subject: nfc: s3fwrn5: Fix potential memory leak in s3fwrn5_nci_send() s3fwrn5_nci_send() will call s3fwrn5_i2c_write() or s3fwrn82_uart_write(), and free the skb if write() failed. However, even if the write() run succeeds, the skb will not be freed in write(). As the result, the skb will memleak. s3fwrn5_nci_send() should also free the skb when write() succeeds. Fixes: c04c674fadeb ("nfc: s3fwrn5: Add driver for Samsung S3FWRN5 NFC Chip") Signed-off-by: Shang XiaoJing Signed-off-by: David S. Miller --- drivers/nfc/s3fwrn5/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c index 1c412007fabb..0270e05b68df 100644 --- a/drivers/nfc/s3fwrn5/core.c +++ b/drivers/nfc/s3fwrn5/core.c @@ -110,11 +110,15 @@ static int s3fwrn5_nci_send(struct nci_dev *ndev, struct sk_buff *skb) } ret = s3fwrn5_write(info, skb); - if (ret < 0) + if (ret < 0) { kfree_skb(skb); + mutex_unlock(&info->mutex); + return ret; + } + consume_skb(skb); mutex_unlock(&info->mutex); - return ret; + return 0; } static int s3fwrn5_nci_post_setup(struct nci_dev *ndev) -- cgit v1.2.3 From 93d904a734a74c54d945a9884b4962977f1176cd Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Thu, 27 Oct 2022 22:03:32 +0800 Subject: nfc: nfcmrvl: Fix potential memory leak in nfcmrvl_i2c_nci_send() nfcmrvl_i2c_nci_send() will be called by nfcmrvl_nci_send(), and skb should be freed in nfcmrvl_i2c_nci_send(). However, nfcmrvl_nci_send() will only free skb when i2c_master_send() return >=0, which means skb will memleak when i2c_master_send() failed. Free skb no matter whether i2c_master_send() succeeds. Fixes: b5b3e23e4cac ("NFC: nfcmrvl: add i2c driver") Signed-off-by: Shang XiaoJing Signed-off-by: David S. Miller --- drivers/nfc/nfcmrvl/i2c.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c index acef0cfd76af..24436c9e54c9 100644 --- a/drivers/nfc/nfcmrvl/i2c.c +++ b/drivers/nfc/nfcmrvl/i2c.c @@ -132,10 +132,15 @@ static int nfcmrvl_i2c_nci_send(struct nfcmrvl_private *priv, ret = -EREMOTEIO; } else ret = 0; + } + + if (ret) { kfree_skb(skb); + return ret; } - return ret; + consume_skb(skb); + return 0; } static void nfcmrvl_i2c_nci_update_config(struct nfcmrvl_private *priv, -- cgit v1.2.3 From 6fdaed8c79887680bc46cb0a51775bd7c8645528 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Thu, 27 Oct 2022 22:57:11 +0900 Subject: drm/format-helper: Only advertise supported formats for conversion drm_fb_build_fourcc_list() currently returns all emulated formats unconditionally as long as the native format is among them, even though not all combinations have conversion helpers. Although the list is arguably provided to userspace in precedence order, userspace can pick something out-of-order (and thus break when it shouldn't), or simply only support a format that is unsupported (and thus think it can work, which results in the appearance of a hang as FB blits fail later on, instead of the initialization error you'd expect in this case). Add checks to filter the list of emulated formats to only those supported for conversion to the native format. This presumes that there is a single native format (only the first is checked, if there are multiple). Refactoring this API to drop the native list or support it properly (by returning the appropriate emulated->native mapping table) is left for a future patch. The simpledrm driver is left as-is with a full table of emulated formats. This keeps all currently working conversions available and drops all the broken ones (i.e. this a strict bugfix patch, adding no new supported formats nor removing any actually working ones). In order to avoid proliferation of emulated formats, future drivers should advertise only XRGB8888 as the sole emulated format (since some userspace assumes its presence). This fixes a real user regression where the ?RGB2101010 support commit started advertising it unconditionally where not supported, and KWin decided to start to use it over the native format and broke, but also the fixes the spurious RGB565/RGB888 formats which have been wrongly unconditionally advertised since the dawn of simpledrm. Fixes: 6ea966fca084 ("drm/simpledrm: Add [AX]RGB2101010 formats") Fixes: 11e8f5fd223b ("drm: Add simpledrm driver") Cc: stable@vger.kernel.org Signed-off-by: Hector Martin Acked-by: Pekka Paalanen Reviewed-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20221027135711.24425-1-marcan@marcan.st --- drivers/gpu/drm/drm_format_helper.c | 66 ++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index e2f76621453c..3ee59bae9d2f 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -807,6 +807,38 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t return false; } +static const uint32_t conv_from_xrgb8888[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, +}; + +static const uint32_t conv_from_rgb565_888[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, +}; + +static bool is_conversion_supported(uint32_t from, uint32_t to) +{ + switch (from) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + return is_listed_fourcc(conv_from_xrgb8888, ARRAY_SIZE(conv_from_xrgb8888), to); + case DRM_FORMAT_RGB565: + case DRM_FORMAT_RGB888: + return is_listed_fourcc(conv_from_rgb565_888, ARRAY_SIZE(conv_from_rgb565_888), to); + case DRM_FORMAT_XRGB2101010: + return to == DRM_FORMAT_ARGB2101010; + case DRM_FORMAT_ARGB2101010: + return to == DRM_FORMAT_XRGB2101010; + default: + return false; + } +} + /** * drm_fb_build_fourcc_list - Filters a list of supported color formats against * the device's native formats @@ -827,7 +859,9 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t * be handed over to drm_universal_plane_init() et al. Native formats * will go before emulated formats. Other heuristics might be applied * to optimize the order. Formats near the beginning of the list are - * usually preferred over formats near the end of the list. + * usually preferred over formats near the end of the list. Formats + * without conversion helpers will be skipped. New drivers should only + * pass in XRGB8888 and avoid exposing additional emulated formats. * * Returns: * The number of color-formats 4CC codes returned in @fourccs_out. @@ -839,7 +873,7 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev, { u32 *fourccs = fourccs_out; const u32 *fourccs_end = fourccs_out + nfourccs_out; - bool found_native = false; + uint32_t native_format = 0; size_t i; /* @@ -858,26 +892,18 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev, drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); - if (!found_native) - found_native = is_listed_fourcc(driver_fourccs, driver_nfourccs, fourcc); + /* + * There should only be one native format with the current API. + * This API needs to be refactored to correctly support arbitrary + * sets of native formats, since it needs to report which native + * format to use for each emulated format. + */ + if (!native_format) + native_format = fourcc; *fourccs = fourcc; ++fourccs; } - /* - * The plane's atomic_update helper converts the framebuffer's color format - * to a native format when copying to device memory. - * - * If there is not a single format supported by both, device and - * driver, the native formats are likely not supported by the conversion - * helpers. Therefore *only* support the native formats and add a - * conversion helper ASAP. - */ - if (!found_native) { - drm_warn(dev, "Format conversion helpers required to add extra formats.\n"); - goto out; - } - /* * The extra formats, emulated by the driver, go second. */ @@ -890,6 +916,9 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev, } else if (fourccs == fourccs_end) { drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); continue; /* end of available output buffer */ + } else if (!is_conversion_supported(fourcc, native_format)) { + drm_dbg_kms(dev, "Unsupported emulated format %p4cc\n", &fourcc); + continue; /* format is not supported for conversion */ } drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); @@ -898,7 +927,6 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev, ++fourccs; } -out: return fourccs - fourccs_out; } EXPORT_SYMBOL(drm_fb_build_fourcc_list); -- cgit v1.2.3 From 06a4df5863f73af193a4ff7abf7cb04058584f06 Mon Sep 17 00:00:00 2001 From: Zhang Changzhong Date: Fri, 28 Oct 2022 10:09:11 +0800 Subject: net: fec: fix improper use of NETDEV_TX_BUSY The ndo_start_xmit() method must not free skb when returning NETDEV_TX_BUSY, since caller is going to requeue freed skb. Fix it by returning NETDEV_TX_OK in case of dma_map_single() fails. Fixes: 79f339125ea3 ("net: fec: Add software TSO support") Signed-off-by: Zhang Changzhong Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 28ef4d3c1878..f623c12eaf95 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -713,7 +713,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, dev_kfree_skb_any(skb); if (net_ratelimit()) netdev_err(ndev, "Tx DMA memory map failed\n"); - return NETDEV_TX_BUSY; + return NETDEV_TX_OK; } bdp->cbd_datlen = cpu_to_fec16(size); @@ -775,7 +775,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, dev_kfree_skb_any(skb); if (net_ratelimit()) netdev_err(ndev, "Tx DMA memory map failed\n"); - return NETDEV_TX_BUSY; + return NETDEV_TX_OK; } } -- cgit v1.2.3 From 171a93182eccd6e6835d2c86b40787f9f832efaa Mon Sep 17 00:00:00 2001 From: Sergey Shtylyov Date: Sat, 29 Oct 2022 00:07:06 +0300 Subject: ata: pata_legacy: fix pdc20230_set_piomode() Clang gives a warning when compiling pata_legacy.c with 'make W=1' about the 'rt' local variable in pdc20230_set_piomode() being set but unused. Quite obviously, there is an outb() call missing to write back the updated variable. Moreover, checking the docs by Petr Soucek revealed that bitwise AND should have been done with a negated timing mask and the master/slave timing masks were swapped while updating... Fixes: 669a5db411d8 ("[libata] Add a bunch of PATA drivers.") Reported-by: Damien Le Moal Signed-off-by: Sergey Shtylyov Signed-off-by: Damien Le Moal --- drivers/ata/pata_legacy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 0a8bf09a5c19..03c580625c2c 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -315,9 +315,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) outb(inb(0x1F4) & 0x07, 0x1F4); rt = inb(0x1F3); - rt &= 0x07 << (3 * adev->devno); + rt &= ~(0x07 << (3 * !adev->devno)); if (pio) - rt |= (1 + 3 * pio) << (3 * adev->devno); + rt |= (1 + 3 * pio) << (3 * !adev->devno); + outb(rt, 0x1F3); udelay(100); outb(inb(0x1F2) | 0x01, 0x1F2); -- cgit v1.2.3 From 015618c3ec19584c83ff179fa631be8cec906aaf Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sat, 29 Oct 2022 15:49:31 +0800 Subject: ata: palmld: fix return value check in palmld_pata_probe() If devm_platform_ioremap_resource() fails, it never return NULL pointer, replace the check with IS_ERR(). Fixes: 57bf0f5a162d ("ARM: pxa: use pdev resource for palmld mmio") Signed-off-by: Yang Yingliang Reviewed-by: Sergey Shtylyov Signed-off-by: Damien Le Moal --- drivers/ata/pata_palmld.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_palmld.c b/drivers/ata/pata_palmld.c index 400e65190904..51caa2a427dd 100644 --- a/drivers/ata/pata_palmld.c +++ b/drivers/ata/pata_palmld.c @@ -63,8 +63,8 @@ static int palmld_pata_probe(struct platform_device *pdev) /* remap drive's physical memory address */ mem = devm_platform_ioremap_resource(pdev, 0); - if (!mem) - return -ENOMEM; + if (IS_ERR(mem)) + return PTR_ERR(mem); /* request and activate power and reset GPIOs */ lda->power = devm_gpiod_get(dev, "power", GPIOD_OUT_HIGH); -- cgit v1.2.3 From d7164a5048e8a6afe2cc4aaf7f12643c14e7f241 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 25 Oct 2022 14:44:55 +0300 Subject: drm/i915/tgl+: Add locking around DKL PHY register accesses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accessing the TypeC DKL PHY registers during modeset-commit, -verification, DP link-retraining and AUX power well toggling is racy due to these code paths being concurrent and the PHY register bank selection register (HIP_INDEX_REG) being shared between PHY instances (aka TC ports) and the bank selection being not atomic wrt. the actual PHY register access. Add the required locking around each PHY register bank selection-> register access sequence. Kudos to Ville for noticing the race conditions. v2: - Add the DKL PHY register accessors to intel_dkl_phy.[ch]. (Jani) - Make the DKL_REG_TC_PORT macro independent of PHY internals. - Move initing the DKL PHY lock to a more logical place. v3: - Fix parameter reuse in the DKL_REG_TC_PORT definition. - Document the usage of phy_lock. v4: - Fix adding TC_PORT_1 offset in the DKL_REG_TC_PORT definition. Cc: Ville Syrjälä Cc: Jani Nikula Cc: # v5.5+ Acked-by: Jani Nikula Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20221025114457.2191004-1-imre.deak@intel.com (cherry picked from commit 89cb0ba4ceee6bed1059904859c5723b3f39da68) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_ddi.c | 68 ++++++------- drivers/gpu/drm/i915/display/intel_display_core.h | 8 ++ .../drm/i915/display/intel_display_power_well.c | 7 +- drivers/gpu/drm/i915/display/intel_dkl_phy.c | 109 +++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dkl_phy.h | 24 +++++ drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 59 +++++------ drivers/gpu/drm/i915/i915_driver.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 3 + 9 files changed, 204 insertions(+), 76 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dkl_phy.c create mode 100644 drivers/gpu/drm/i915/display/intel_dkl_phy.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index a26edcdadc21..cea00aaca04b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -282,6 +282,7 @@ i915-y += \ display/intel_ddi.o \ display/intel_ddi_buf_trans.o \ display/intel_display_trace.o \ + display/intel_dkl_phy.o \ display/intel_dp.o \ display/intel_dp_aux.o \ display/intel_dp_aux_backlight.o \ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index da8472cdc135..69ecf2a3d6c6 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -43,6 +43,7 @@ #include "intel_de.h" #include "intel_display_power.h" #include "intel_display_types.h" +#include "intel_dkl_phy.h" #include "intel_dp.h" #include "intel_dp_link_training.h" #include "intel_dp_mst.h" @@ -1262,33 +1263,30 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, for (ln = 0; ln < 2; ln++) { int level; - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, ln)); - - intel_de_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port), 0); + intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port), ln, 0); level = intel_ddi_level(encoder, crtc_state, 2*ln+0); - intel_de_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port), - DKL_TX_PRESHOOT_COEFF_MASK | - DKL_TX_DE_EMPAHSIS_COEFF_MASK | - DKL_TX_VSWING_CONTROL_MASK, - DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | - DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | - DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port), ln, + DKL_TX_PRESHOOT_COEFF_MASK | + DKL_TX_DE_EMPAHSIS_COEFF_MASK | + DKL_TX_VSWING_CONTROL_MASK, + DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | + DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | + DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); level = intel_ddi_level(encoder, crtc_state, 2*ln+1); - intel_de_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port), - DKL_TX_PRESHOOT_COEFF_MASK | - DKL_TX_DE_EMPAHSIS_COEFF_MASK | - DKL_TX_VSWING_CONTROL_MASK, - DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | - DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | - DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port), ln, + DKL_TX_PRESHOOT_COEFF_MASK | + DKL_TX_DE_EMPAHSIS_COEFF_MASK | + DKL_TX_VSWING_CONTROL_MASK, + DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) | + DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | + DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); - intel_de_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), - DKL_TX_DP20BITMODE, 0); + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), ln, + DKL_TX_DP20BITMODE, 0); if (IS_ALDERLAKE_P(dev_priv)) { u32 val; @@ -1306,10 +1304,10 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0); } - intel_de_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), - DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK | - DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, - val); + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), ln, + DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK | + DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, + val); } } } @@ -2019,12 +2017,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port, return; if (DISPLAY_VER(dev_priv) >= 12) { - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x0)); - ln0 = intel_de_read(dev_priv, DKL_DP_MODE(tc_port)); - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x1)); - ln1 = intel_de_read(dev_priv, DKL_DP_MODE(tc_port)); + ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port), 0); + ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port), 1); } else { ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port)); ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port)); @@ -2085,12 +2079,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port, } if (DISPLAY_VER(dev_priv) >= 12) { - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x0)); - intel_de_write(dev_priv, DKL_DP_MODE(tc_port), ln0); - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x1)); - intel_de_write(dev_priv, DKL_DP_MODE(tc_port), ln1); + intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port), 0, ln0); + intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port), 1, ln1); } else { intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0); intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1); @@ -3094,10 +3084,8 @@ static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder) enum tc_port tc_port = intel_port_to_tc(i915, encoder->port); int ln; - for (ln = 0; ln < 2; ln++) { - intel_de_write(i915, HIP_INDEX_REG(tc_port), HIP_INDEX_VAL(tc_port, ln)); - intel_de_rmw(i915, DKL_PCS_DW5(tc_port), DKL_PCS_DW5_CORE_SOFTRESET, 0); - } + for (ln = 0; ln < 2; ln++) + intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port), ln, DKL_PCS_DW5_CORE_SOFTRESET, 0); } static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 96cf994b0ad1..9b51148e8ba5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -315,6 +315,14 @@ struct intel_display { struct intel_global_obj obj; } dbuf; + struct { + /* + * dkl.phy_lock protects against concurrent access of the + * Dekel TypeC PHYs. + */ + spinlock_t phy_lock; + } dkl; + struct { /* VLV/CHV/BXT/GLK DSI MMIO register base address */ u32 mmio_base; diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index df7ee4969ef1..1d18eee56253 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -12,6 +12,7 @@ #include "intel_de.h" #include "intel_display_power_well.h" #include "intel_display_types.h" +#include "intel_dkl_phy.h" #include "intel_dmc.h" #include "intel_dpio_phy.h" #include "intel_dpll.h" @@ -529,11 +530,9 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, enum tc_port tc_port; tc_port = TGL_AUX_PW_TO_TC_PORT(i915_power_well_instance(power_well)->hsw.idx); - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x2)); - if (intel_de_wait_for_set(dev_priv, DKL_CMN_UC_DW_27(tc_port), - DKL_CMN_UC_DW27_UC_HEALTH, 1)) + if (wait_for(intel_dkl_phy_read(dev_priv, DKL_CMN_UC_DW_27(tc_port), 2) & + DKL_CMN_UC_DW27_UC_HEALTH, 1)) drm_warn(&dev_priv->drm, "Timeout waiting TC uC health\n"); } diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.c b/drivers/gpu/drm/i915/display/intel_dkl_phy.c new file mode 100644 index 000000000000..710b030c7ed5 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + */ + +#include "i915_drv.h" +#include "i915_reg.h" + +#include "intel_de.h" +#include "intel_display.h" +#include "intel_dkl_phy.h" + +static void +dkl_phy_set_hip_idx(struct drm_i915_private *i915, i915_reg_t reg, int idx) +{ + enum tc_port tc_port = DKL_REG_TC_PORT(reg); + + drm_WARN_ON(&i915->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS); + + intel_de_write(i915, + HIP_INDEX_REG(tc_port), + HIP_INDEX_VAL(tc_port, idx)); +} + +/** + * intel_dkl_phy_read - read a Dekel PHY register + * @i915: i915 device instance + * @reg: Dekel PHY register + * @ln: lane instance of @reg + * + * Read the @reg Dekel PHY register. + * + * Returns the read value. + */ +u32 +intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln) +{ + u32 val; + + spin_lock(&i915->display.dkl.phy_lock); + + dkl_phy_set_hip_idx(i915, reg, ln); + val = intel_de_read(i915, reg); + + spin_unlock(&i915->display.dkl.phy_lock); + + return val; +} + +/** + * intel_dkl_phy_write - write a Dekel PHY register + * @i915: i915 device instance + * @reg: Dekel PHY register + * @ln: lane instance of @reg + * @val: value to write + * + * Write @val to the @reg Dekel PHY register. + */ +void +intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 val) +{ + spin_lock(&i915->display.dkl.phy_lock); + + dkl_phy_set_hip_idx(i915, reg, ln); + intel_de_write(i915, reg, val); + + spin_unlock(&i915->display.dkl.phy_lock); +} + +/** + * intel_dkl_phy_rmw - read-modify-write a Dekel PHY register + * @i915: i915 device instance + * @reg: Dekel PHY register + * @ln: lane instance of @reg + * @clear: mask to clear + * @set: mask to set + * + * Read the @reg Dekel PHY register, clearing then setting the @clear/@set bits in it, and writing + * this value back to the register if the value differs from the read one. + */ +void +intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 clear, u32 set) +{ + spin_lock(&i915->display.dkl.phy_lock); + + dkl_phy_set_hip_idx(i915, reg, ln); + intel_de_rmw(i915, reg, clear, set); + + spin_unlock(&i915->display.dkl.phy_lock); +} + +/** + * intel_dkl_phy_posting_read - do a posting read from a Dekel PHY register + * @i915: i915 device instance + * @reg: Dekel PHY register + * @ln: lane instance of @reg + * + * Read the @reg Dekel PHY register without returning the read value. + */ +void +intel_dkl_phy_posting_read(struct drm_i915_private *i915, i915_reg_t reg, int ln) +{ + spin_lock(&i915->display.dkl.phy_lock); + + dkl_phy_set_hip_idx(i915, reg, ln); + intel_de_posting_read(i915, reg); + + spin_unlock(&i915->display.dkl.phy_lock); +} diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.h b/drivers/gpu/drm/i915/display/intel_dkl_phy.h new file mode 100644 index 000000000000..260ad121a0b1 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DKL_PHY_H__ +#define __INTEL_DKL_PHY_H__ + +#include + +#include "i915_reg_defs.h" + +struct drm_i915_private; + +u32 +intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln); +void +intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 val); +void +intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 clear, u32 set); +void +intel_dkl_phy_posting_read(struct drm_i915_private *i915, i915_reg_t reg, int ln); + +#endif /* __INTEL_DKL_PHY_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index e5fb66a5dd02..64dd603dc69a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -25,6 +25,7 @@ #include "intel_de.h" #include "intel_display_types.h" +#include "intel_dkl_phy.h" #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_dpll_mgr.h" @@ -3508,15 +3509,12 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv, * All registers read here have the same HIP_INDEX_REG even though * they are on different building blocks */ - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x2)); - - hw_state->mg_refclkin_ctl = intel_de_read(dev_priv, - DKL_REFCLKIN_CTL(tc_port)); + hw_state->mg_refclkin_ctl = intel_dkl_phy_read(dev_priv, + DKL_REFCLKIN_CTL(tc_port), 2); hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK; hw_state->mg_clktop2_hsclkctl = - intel_de_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port)); + intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2); hw_state->mg_clktop2_hsclkctl &= MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK | MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK | @@ -3524,32 +3522,32 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv, MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK; hw_state->mg_clktop2_coreclkctl1 = - intel_de_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port)); + intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2); hw_state->mg_clktop2_coreclkctl1 &= MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK; - hw_state->mg_pll_div0 = intel_de_read(dev_priv, DKL_PLL_DIV0(tc_port)); + hw_state->mg_pll_div0 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV0(tc_port), 2); val = DKL_PLL_DIV0_MASK; if (dev_priv->display.vbt.override_afc_startup) val |= DKL_PLL_DIV0_AFC_STARTUP_MASK; hw_state->mg_pll_div0 &= val; - hw_state->mg_pll_div1 = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port)); + hw_state->mg_pll_div1 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port), 2); hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK | DKL_PLL_DIV1_TDC_TARGET_CNT_MASK); - hw_state->mg_pll_ssc = intel_de_read(dev_priv, DKL_PLL_SSC(tc_port)); + hw_state->mg_pll_ssc = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port), 2); hw_state->mg_pll_ssc &= (DKL_PLL_SSC_IREF_NDIV_RATIO_MASK | DKL_PLL_SSC_STEP_LEN_MASK | DKL_PLL_SSC_STEP_NUM_MASK | DKL_PLL_SSC_EN); - hw_state->mg_pll_bias = intel_de_read(dev_priv, DKL_PLL_BIAS(tc_port)); + hw_state->mg_pll_bias = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port), 2); hw_state->mg_pll_bias &= (DKL_PLL_BIAS_FRAC_EN_H | DKL_PLL_BIAS_FBDIV_FRAC_MASK); hw_state->mg_pll_tdc_coldst_bias = - intel_de_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); + intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2); hw_state->mg_pll_tdc_coldst_bias &= (DKL_PLL_TDC_SSC_STEP_SIZE_MASK | DKL_PLL_TDC_FEED_FWD_GAIN_MASK); @@ -3737,61 +3735,58 @@ static void dkl_pll_write(struct drm_i915_private *dev_priv, * All registers programmed here have the same HIP_INDEX_REG even * though on different building block */ - intel_de_write(dev_priv, HIP_INDEX_REG(tc_port), - HIP_INDEX_VAL(tc_port, 0x2)); - /* All the registers are RMW */ - val = intel_de_read(dev_priv, DKL_REFCLKIN_CTL(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_REFCLKIN_CTL(tc_port), 2); val &= ~MG_REFCLKIN_CTL_OD_2_MUX_MASK; val |= hw_state->mg_refclkin_ctl; - intel_de_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), 2, val); - val = intel_de_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2); val &= ~MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK; val |= hw_state->mg_clktop2_coreclkctl1; - intel_de_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2, val); - val = intel_de_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2); val &= ~(MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK | MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK | MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK | MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK); val |= hw_state->mg_clktop2_hsclkctl; - intel_de_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2, val); val = DKL_PLL_DIV0_MASK; if (dev_priv->display.vbt.override_afc_startup) val |= DKL_PLL_DIV0_AFC_STARTUP_MASK; - intel_de_rmw(dev_priv, DKL_PLL_DIV0(tc_port), val, - hw_state->mg_pll_div0); + intel_dkl_phy_rmw(dev_priv, DKL_PLL_DIV0(tc_port), 2, val, + hw_state->mg_pll_div0); - val = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port), 2); val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK | DKL_PLL_DIV1_TDC_TARGET_CNT_MASK); val |= hw_state->mg_pll_div1; - intel_de_write(dev_priv, DKL_PLL_DIV1(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_PLL_DIV1(tc_port), 2, val); - val = intel_de_read(dev_priv, DKL_PLL_SSC(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port), 2); val &= ~(DKL_PLL_SSC_IREF_NDIV_RATIO_MASK | DKL_PLL_SSC_STEP_LEN_MASK | DKL_PLL_SSC_STEP_NUM_MASK | DKL_PLL_SSC_EN); val |= hw_state->mg_pll_ssc; - intel_de_write(dev_priv, DKL_PLL_SSC(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_PLL_SSC(tc_port), 2, val); - val = intel_de_read(dev_priv, DKL_PLL_BIAS(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port), 2); val &= ~(DKL_PLL_BIAS_FRAC_EN_H | DKL_PLL_BIAS_FBDIV_FRAC_MASK); val |= hw_state->mg_pll_bias; - intel_de_write(dev_priv, DKL_PLL_BIAS(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_PLL_BIAS(tc_port), 2, val); - val = intel_de_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); + val = intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2); val &= ~(DKL_PLL_TDC_SSC_STEP_SIZE_MASK | DKL_PLL_TDC_FEED_FWD_GAIN_MASK); val |= hw_state->mg_pll_tdc_coldst_bias; - intel_de_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), val); + intel_dkl_phy_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2, val); - intel_de_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); + intel_dkl_phy_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2); } static void icl_pll_power_enable(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c459eb362c47..f2a15d8155f4 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -353,6 +353,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) mutex_init(&dev_priv->display.wm.wm_mutex); mutex_init(&dev_priv->display.pps.mutex); mutex_init(&dev_priv->display.hdcp.comp_mutex); + spin_lock_init(&dev_priv->display.dkl.phy_lock); i915_memcpy_init_early(dev_priv); intel_runtime_pm_init_early(&dev_priv->runtime_pm); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0b287a59dc2f..da35bb2db26b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7420,6 +7420,9 @@ enum skl_power_gate { #define _DKL_PHY5_BASE 0x16C000 #define _DKL_PHY6_BASE 0x16D000 +#define DKL_REG_TC_PORT(__reg) \ + (TC_PORT_1 + ((__reg).reg - _DKL_PHY1_BASE) / (_DKL_PHY2_BASE - _DKL_PHY1_BASE)) + /* DEKEL PHY MMIO Address = Phy base + (internal address & ~index_mask) */ #define _DKL_PCS_DW5 0x14 #define DKL_PCS_DW5(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \ -- cgit v1.2.3 From d3f6bacfca86f6cf6bf85be1e8b54083d68d8195 Mon Sep 17 00:00:00 2001 From: Robert Beckett Date: Thu, 20 Oct 2022 13:03:08 +0200 Subject: drm/i915: stop abusing swiotlb_max_segment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit swiotlb_max_segment used to return either the maximum size that swiotlb could bounce, or for Xen PV PAGE_SIZE even if swiotlb could bounce buffer larger mappings. This made i915 on Xen PV work as it bypasses the coherency aspect of the DMA API and can't cope with bounce buffering and this avoided bounce buffering for the Xen/PV case. So instead of adding this hack back, check for Xen/PV directly in i915 for the Xen case and otherwise use the proper DMA API helper to query the maximum mapping size. Replace swiotlb_max_segment() calls with dma_max_mapping_size(). In i915_gem_object_get_pages_internal() no longer consider max_segment only if CONFIG_SWIOTLB is enabled. There can be other (iommu related) causes of specific max segment sizes. Fixes: a2daa27c0c61 ("swiotlb: simplify swiotlb_max_segment") Reported-by: Marek Marczykowski-Górecki Signed-off-by: Robert Beckett Signed-off-by: Christoph Hellwig [hch: added the Xen hack, rewrote the changelog] Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20221020110308.1582518-1-hch@lst.de (cherry picked from commit 78a07fe777c42800bd1adaec12abe5dcee43919e) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/gem/i915_gem_internal.c | 19 ++++------------ drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 4 ++-- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 2 +- drivers/gpu/drm/i915/i915_scatterlist.h | 34 +++++++++++++++++----------- 5 files changed, 29 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c index c698f95af15f..629acb403a2c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c @@ -6,7 +6,6 @@ #include #include -#include #include "i915_drv.h" #include "i915_gem.h" @@ -38,22 +37,12 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) struct scatterlist *sg; unsigned int sg_page_sizes; unsigned int npages; - int max_order; + int max_order = MAX_ORDER; + unsigned int max_segment; gfp_t gfp; - max_order = MAX_ORDER; -#ifdef CONFIG_SWIOTLB - if (is_swiotlb_active(obj->base.dev->dev)) { - unsigned int max_segment; - - max_segment = swiotlb_max_segment(); - if (max_segment) { - max_segment = max_t(unsigned int, max_segment, - PAGE_SIZE) >> PAGE_SHIFT; - max_order = min(max_order, ilog2(max_segment)); - } - } -#endif + max_segment = i915_sg_segment_size(i915->drm.dev) >> PAGE_SHIFT; + max_order = min(max_order, get_order(max_segment)); gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE; if (IS_I965GM(i915) || IS_I965G(i915)) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index f42ca1179f37..11125c32dd35 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -194,7 +194,7 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj) struct intel_memory_region *mem = obj->mm.region; struct address_space *mapping = obj->base.filp->f_mapping; const unsigned long page_count = obj->base.size / PAGE_SIZE; - unsigned int max_segment = i915_sg_segment_size(); + unsigned int max_segment = i915_sg_segment_size(i915->drm.dev); struct sg_table *st; struct sgt_iter sgt_iter; struct page *page; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 4f861782c3e8..a4aa9500fa17 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -189,7 +189,7 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev, struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev); struct intel_memory_region *mr = i915->mm.regions[INTEL_MEMORY_SYSTEM]; struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm); - const unsigned int max_segment = i915_sg_segment_size(); + const unsigned int max_segment = i915_sg_segment_size(i915->drm.dev); const size_t size = (size_t)ttm->num_pages << PAGE_SHIFT; struct file *filp = i915_tt->filp; struct sgt_iter sgt_iter; @@ -538,7 +538,7 @@ static struct i915_refct_sgt *i915_ttm_tt_get_st(struct ttm_tt *ttm) ret = sg_alloc_table_from_pages_segment(st, ttm->pages, ttm->num_pages, 0, (unsigned long)ttm->num_pages << PAGE_SHIFT, - i915_sg_segment_size(), GFP_KERNEL); + i915_sg_segment_size(i915_tt->dev), GFP_KERNEL); if (ret) { st->sgl = NULL; return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index d4398948f016..f34e01a7fefb 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -129,7 +129,7 @@ static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj) static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) { const unsigned long num_pages = obj->base.size >> PAGE_SHIFT; - unsigned int max_segment = i915_sg_segment_size(); + unsigned int max_segment = i915_sg_segment_size(obj->base.dev->dev); struct sg_table *st; unsigned int sg_page_sizes; struct page **pvec; diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h index 9ddb3e743a3e..b0a1db44f895 100644 --- a/drivers/gpu/drm/i915/i915_scatterlist.h +++ b/drivers/gpu/drm/i915/i915_scatterlist.h @@ -9,7 +9,8 @@ #include #include -#include +#include +#include #include "i915_gem.h" @@ -127,19 +128,26 @@ static inline unsigned int i915_sg_dma_sizes(struct scatterlist *sg) return page_sizes; } -static inline unsigned int i915_sg_segment_size(void) +static inline unsigned int i915_sg_segment_size(struct device *dev) { - unsigned int size = swiotlb_max_segment(); - - if (size == 0) - size = UINT_MAX; - - size = rounddown(size, PAGE_SIZE); - /* swiotlb_max_segment_size can return 1 byte when it means one page. */ - if (size < PAGE_SIZE) - size = PAGE_SIZE; - - return size; + size_t max = min_t(size_t, UINT_MAX, dma_max_mapping_size(dev)); + + /* + * For Xen PV guests pages aren't contiguous in DMA (machine) address + * space. The DMA API takes care of that both in dma_alloc_* (by + * calling into the hypervisor to make the pages contiguous) and in + * dma_map_* (by bounce buffering). But i915 abuses ignores the + * coherency aspects of the DMA API and thus can't cope with bounce + * buffering actually happening, so add a hack here to force small + * allocations and mappings when running in PV mode on Xen. + * + * Note this will still break if bounce buffering is required for other + * reasons, like confidential computing hypervisors or PCIe root ports + * with addressing limitations. + */ + if (xen_pv_domain()) + max = PAGE_SIZE; + return round_down(max, PAGE_SIZE); } bool i915_sg_trim(struct sg_table *orig_st); -- cgit v1.2.3 From 3e206b6aa6df7eed4297577e0cf8403169b800a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 13:11:27 +0300 Subject: drm/i915/sdvo: Filter out invalid outputs more sensibly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We try to filter out the corresponding xxx1 output if the xxx0 output is not present. But the way that is being done is pretty awkward. Make it less so. Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026101134.20865-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula (cherry picked from commit cc1e66394daaa7e9f005e2487a84e34a39f9308b) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/display/intel_sdvo.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index f5b744bef18f..30d3778c6136 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2926,16 +2926,33 @@ err: return false; } +static u16 intel_sdvo_filter_output_flags(u16 flags) +{ + flags &= SDVO_OUTPUT_MASK; + + /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/ + if (!(flags & SDVO_OUTPUT_TMDS0)) + flags &= ~SDVO_OUTPUT_TMDS1; + + if (!(flags & SDVO_OUTPUT_RGB0)) + flags &= ~SDVO_OUTPUT_RGB1; + + if (!(flags & SDVO_OUTPUT_LVDS0)) + flags &= ~SDVO_OUTPUT_LVDS1; + + return flags; +} + static bool intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags) { - /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/ + flags = intel_sdvo_filter_output_flags(flags); if (flags & SDVO_OUTPUT_TMDS0) if (!intel_sdvo_dvi_init(intel_sdvo, 0)) return false; - if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK) + if (flags & SDVO_OUTPUT_TMDS1) if (!intel_sdvo_dvi_init(intel_sdvo, 1)) return false; @@ -2956,7 +2973,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags) if (!intel_sdvo_analog_init(intel_sdvo, 0)) return false; - if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK) + if (flags & SDVO_OUTPUT_RGB1) if (!intel_sdvo_analog_init(intel_sdvo, 1)) return false; @@ -2964,11 +2981,11 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags) if (!intel_sdvo_lvds_init(intel_sdvo, 0)) return false; - if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK) + if (flags & SDVO_OUTPUT_LVDS1) if (!intel_sdvo_lvds_init(intel_sdvo, 1)) return false; - if ((flags & SDVO_OUTPUT_MASK) == 0) { + if (flags == 0) { unsigned char bytes[2]; intel_sdvo->controlled_output = 0; -- cgit v1.2.3 From e79762512120f11c51317570519a1553c70805d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 13:11:28 +0300 Subject: drm/i915/sdvo: Setup DDC fully before output init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call intel_sdvo_select_ddc_bus() before initializing any of the outputs. And before that is functional (assuming no VBT) we have to set up the controlled_outputs thing. Otherwise DDC won't be functional during the output init but LVDS really needs it for the fixed mode setup. Note that the whole multi output support still looks very bogus, and more work will be needed to make it correct. But for now this should at least fix the LVDS EDID fixed mode setup. Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/7301 Fixes: aa2b88074a56 ("drm/i915/sdvo: Fix multi function encoder stuff") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026101134.20865-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula (cherry picked from commit 64b7b557dc8a96d9cfed6aedbf81de2df80c025d) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/display/intel_sdvo.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 30d3778c6136..8046d02a8ad0 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2747,13 +2747,10 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) if (!intel_sdvo_connector) return false; - if (device == 0) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS0; + if (device == 0) intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0; - } else if (device == 1) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS1; + else if (device == 1) intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1; - } intel_connector = &intel_sdvo_connector->base; connector = &intel_connector->base; @@ -2808,7 +2805,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; - intel_sdvo->controlled_output |= type; intel_sdvo_connector->output_flag = type; if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { @@ -2849,13 +2845,10 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) encoder->encoder_type = DRM_MODE_ENCODER_DAC; connector->connector_type = DRM_MODE_CONNECTOR_VGA; - if (device == 0) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0; + if (device == 0) intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0; - } else if (device == 1) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1; + else if (device == 1) intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; - } if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { kfree(intel_sdvo_connector); @@ -2885,13 +2878,10 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) encoder->encoder_type = DRM_MODE_ENCODER_LVDS; connector->connector_type = DRM_MODE_CONNECTOR_LVDS; - if (device == 0) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0; + if (device == 0) intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0; - } else if (device == 1) { - intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1; + else if (device == 1) intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; - } if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { kfree(intel_sdvo_connector); @@ -2946,8 +2936,14 @@ static u16 intel_sdvo_filter_output_flags(u16 flags) static bool intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); + flags = intel_sdvo_filter_output_flags(flags); + intel_sdvo->controlled_output = flags; + + intel_sdvo_select_ddc_bus(i915, intel_sdvo); + if (flags & SDVO_OUTPUT_TMDS0) if (!intel_sdvo_dvi_init(intel_sdvo, 0)) return false; @@ -2988,7 +2984,6 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags) if (flags == 0) { unsigned char bytes[2]; - intel_sdvo->controlled_output = 0; memcpy(bytes, &intel_sdvo->caps.output_flags, 2); DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n", SDVO_NAME(intel_sdvo), @@ -3400,8 +3395,6 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, */ intel_sdvo->base.cloneable = 0; - intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo); - /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) goto err_output; -- cgit v1.2.3 From cf82d0ecb84e8ef9958721193f901609b408655b Mon Sep 17 00:00:00 2001 From: "zhichao.liu" Date: Fri, 21 Oct 2022 17:16:53 +0800 Subject: spi: mediatek: Fix package division error Commit 7e963fb2a33ce ("spi: mediatek: add ipm design support for MT7986") makes a mistake on package dividing operation (one change is missing), need to fix it. Background: Ipm design is expanding the HW capability of dma (adjust package length from 1KB to 64KB), and using "dev_comp->ipm_support" flag to indicate it. Issue description: Ipm support patch (said above) is missing to handle remainder at package dividing operation. One case, a transmission length is 65KB, is will divide to 1K (package length) * 65(package loop) in non-ipm desgin case, and will divide to 64K(package length) * 1(package loop) + 1K(remainder) in ipm design case. And the 1K remainder will be lost with the current SW flow, and the transmission will be failure. So, it should be fixed. Solution: Add "ipm_design" flag in function "mtk_spi_get_mult_delta()" to indicate HW capability, and modify the parameters corespondingly. fixes: 7e963fb2a33ce ("spi: mediatek: add ipm design support for MT7986") Signed-off-by: zhichao.liu Link: https://lore.kernel.org/r/20221021091653.18297-1-zhichao.liu@mediatek.com Signed-off-by: Mark Brown --- drivers/spi/spi-mt65xx.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 11aeae7fe7fc..a33c9a3de395 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -551,14 +551,17 @@ static void mtk_spi_enable_transfer(struct spi_master *master) writel(cmd, mdata->base + SPI_CMD_REG); } -static int mtk_spi_get_mult_delta(u32 xfer_len) +static int mtk_spi_get_mult_delta(struct mtk_spi *mdata, u32 xfer_len) { - u32 mult_delta; + u32 mult_delta = 0; - if (xfer_len > MTK_SPI_PACKET_SIZE) - mult_delta = xfer_len % MTK_SPI_PACKET_SIZE; - else - mult_delta = 0; + if (mdata->dev_comp->ipm_design) { + if (xfer_len > MTK_SPI_IPM_PACKET_SIZE) + mult_delta = xfer_len % MTK_SPI_IPM_PACKET_SIZE; + } else { + if (xfer_len > MTK_SPI_PACKET_SIZE) + mult_delta = xfer_len % MTK_SPI_PACKET_SIZE; + } return mult_delta; } @@ -570,22 +573,22 @@ static void mtk_spi_update_mdata_len(struct spi_master *master) if (mdata->tx_sgl_len && mdata->rx_sgl_len) { if (mdata->tx_sgl_len > mdata->rx_sgl_len) { - mult_delta = mtk_spi_get_mult_delta(mdata->rx_sgl_len); + mult_delta = mtk_spi_get_mult_delta(mdata, mdata->rx_sgl_len); mdata->xfer_len = mdata->rx_sgl_len - mult_delta; mdata->rx_sgl_len = mult_delta; mdata->tx_sgl_len -= mdata->xfer_len; } else { - mult_delta = mtk_spi_get_mult_delta(mdata->tx_sgl_len); + mult_delta = mtk_spi_get_mult_delta(mdata, mdata->tx_sgl_len); mdata->xfer_len = mdata->tx_sgl_len - mult_delta; mdata->tx_sgl_len = mult_delta; mdata->rx_sgl_len -= mdata->xfer_len; } } else if (mdata->tx_sgl_len) { - mult_delta = mtk_spi_get_mult_delta(mdata->tx_sgl_len); + mult_delta = mtk_spi_get_mult_delta(mdata, mdata->tx_sgl_len); mdata->xfer_len = mdata->tx_sgl_len - mult_delta; mdata->tx_sgl_len = mult_delta; } else if (mdata->rx_sgl_len) { - mult_delta = mtk_spi_get_mult_delta(mdata->rx_sgl_len); + mult_delta = mtk_spi_get_mult_delta(mdata, mdata->rx_sgl_len); mdata->xfer_len = mdata->rx_sgl_len - mult_delta; mdata->rx_sgl_len = mult_delta; } -- cgit v1.2.3 From 224e858f215a3d6304f95a92357a1753475ca9cf Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 29 Oct 2022 09:04:29 +0800 Subject: ublk_drv: return flag of UBLK_F_URING_CMD_COMP_IN_TASK in case of module UBLK_F_URING_CMD_COMP_IN_TASK needs to be set and returned to userspace if ublk driver is built as module, otherwise userspace may get wrong flags shown. Fixes: 71f28f3136af ("ublk_drv: add io_uring based userspace block driver") Signed-off-by: Ming Lei Reviewed-by: ZiyangZhang Link: https://lore.kernel.org/r/20221029010432.598367-2-ming.lei@redhat.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 5afce6ffaadf..6b2f214f0d5c 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -1658,6 +1658,9 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd) */ ub->dev_info.flags &= UBLK_F_ALL; + if (!IS_BUILTIN(CONFIG_BLK_DEV_UBLK)) + ub->dev_info.flags |= UBLK_F_URING_CMD_COMP_IN_TASK; + /* We are not ready to support zero copy */ ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY; -- cgit v1.2.3 From d57c2c6c1145148bb23d68db73de0b52d482d4ba Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 29 Oct 2022 09:04:30 +0800 Subject: ublk_drv: comment on ublk_driver entry of Kconfig Add help info for choosing to build ublk_drv as module or builtin. Signed-off-by: Ming Lei Reviewed-by: ZiyangZhang Link: https://lore.kernel.org/r/20221029010432.598367-3-ming.lei@redhat.com Signed-off-by: Jens Axboe --- drivers/block/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index db1b4b202646..a41145d52de9 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -408,6 +408,12 @@ config BLK_DEV_UBLK definition isn't finalized yet, and might change according to future requirement, so mark is as experimental now. + Say Y if you want to get better performance because task_work_add() + can be used in IO path for replacing io_uring cmd, which will become + shared between IO tasks and ubq daemon, meantime task_work_add() can + can handle batch more effectively, but task_work_add() isn't exported + for module, so ublk has to be built to kernel. + source "drivers/block/rnbd/Kconfig" endif # BLK_DEV -- cgit v1.2.3 From 3ab6e94ca539242247d4f00414a1bde584d001ed Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 29 Oct 2022 09:04:31 +0800 Subject: ublk_drv: avoid to touch io_uring cmd in blk_mq io path io_uring cmd is supposed to be used in ubq daemon context mainly, and we should try to avoid to touch it in ublk io submission context, otherwise this data could become shared between the two contexts, and performance is hurt. So link request into one per-queue list, and use same batching policy of io_uring command, just avoid to touch ucmd in blk-mq io context. Signed-off-by: Ming Lei Reviewed-by: ZiyangZhang Link: https://lore.kernel.org/r/20221029010432.598367-4-ming.lei@redhat.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 83 +++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 6b2f214f0d5c..3a59271dafe4 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -57,11 +57,14 @@ #define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD) struct ublk_rq_data { - struct callback_head work; + union { + struct callback_head work; + struct llist_node node; + }; }; struct ublk_uring_cmd_pdu { - struct request *req; + struct ublk_queue *ubq; }; /* @@ -119,6 +122,8 @@ struct ublk_queue { struct task_struct *ubq_daemon; char *io_cmd_buf; + struct llist_head io_cmds; + unsigned long io_addr; /* mapped vm address */ unsigned int max_io_sz; bool force_abort; @@ -764,8 +769,12 @@ static inline void __ublk_rq_task_work(struct request *req) static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd) { struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); + struct ublk_queue *ubq = pdu->ubq; + struct llist_node *io_cmds = llist_del_all(&ubq->io_cmds); + struct ublk_rq_data *data; - __ublk_rq_task_work(pdu->req); + llist_for_each_entry(data, io_cmds, node) + __ublk_rq_task_work(blk_mq_rq_from_pdu(data)); } static void ublk_rq_task_work_fn(struct callback_head *work) @@ -777,17 +786,50 @@ static void ublk_rq_task_work_fn(struct callback_head *work) __ublk_rq_task_work(req); } +static void ublk_submit_cmd(struct ublk_queue *ubq, const struct request *rq) +{ + struct ublk_io *io = &ubq->ios[rq->tag]; + + /* + * If the check pass, we know that this is a re-issued request aborted + * previously in monitor_work because the ubq_daemon(cmd's task) is + * PF_EXITING. We cannot call io_uring_cmd_complete_in_task() anymore + * because this ioucmd's io_uring context may be freed now if no inflight + * ioucmd exists. Otherwise we may cause null-deref in ctx->fallback_work. + * + * Note: monitor_work sets UBLK_IO_FLAG_ABORTED and ends this request(releasing + * the tag). Then the request is re-started(allocating the tag) and we are here. + * Since releasing/allocating a tag implies smp_mb(), finding UBLK_IO_FLAG_ABORTED + * guarantees that here is a re-issued request aborted previously. + */ + if (unlikely(io->flags & UBLK_IO_FLAG_ABORTED)) { + struct llist_node *io_cmds = llist_del_all(&ubq->io_cmds); + struct ublk_rq_data *data; + + llist_for_each_entry(data, io_cmds, node) + __ublk_abort_rq(ubq, blk_mq_rq_from_pdu(data)); + } else { + struct io_uring_cmd *cmd = io->cmd; + struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); + + pdu->ubq = ubq; + io_uring_cmd_complete_in_task(cmd, ublk_rq_task_work_cb); + } +} + static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { struct ublk_queue *ubq = hctx->driver_data; struct request *rq = bd->rq; + struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq); blk_status_t res; /* fill iod to slot in io cmd buffer */ res = ublk_setup_iod(ubq, rq); if (unlikely(res != BLK_STS_OK)) return BLK_STS_IOERR; + /* With recovery feature enabled, force_abort is set in * ublk_stop_dev() before calling del_gendisk(). We have to * abort all requeued and new rqs here to let del_gendisk() @@ -809,36 +851,15 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx, } if (ublk_can_use_task_work(ubq)) { - struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq); enum task_work_notify_mode notify_mode = bd->last ? TWA_SIGNAL_NO_IPI : TWA_NONE; if (task_work_add(ubq->ubq_daemon, &data->work, notify_mode)) goto fail; } else { - struct ublk_io *io = &ubq->ios[rq->tag]; - struct io_uring_cmd *cmd = io->cmd; - struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); - - /* - * If the check pass, we know that this is a re-issued request aborted - * previously in monitor_work because the ubq_daemon(cmd's task) is - * PF_EXITING. We cannot call io_uring_cmd_complete_in_task() anymore - * because this ioucmd's io_uring context may be freed now if no inflight - * ioucmd exists. Otherwise we may cause null-deref in ctx->fallback_work. - * - * Note: monitor_work sets UBLK_IO_FLAG_ABORTED and ends this request(releasing - * the tag). Then the request is re-started(allocating the tag) and we are here. - * Since releasing/allocating a tag implies smp_mb(), finding UBLK_IO_FLAG_ABORTED - * guarantees that here is a re-issued request aborted previously. - */ - if ((io->flags & UBLK_IO_FLAG_ABORTED)) - goto fail; - - pdu->req = rq; - io_uring_cmd_complete_in_task(cmd, ublk_rq_task_work_cb); + if (llist_add(&data->node, &ubq->io_cmds)) + ublk_submit_cmd(ubq, rq); } - return BLK_STS_OK; } @@ -1168,17 +1189,19 @@ static void ublk_handle_need_get_data(struct ublk_device *ub, int q_id, { struct ublk_queue *ubq = ublk_get_queue(ub, q_id); struct request *req = blk_mq_tag_to_rq(ub->tag_set.tags[q_id], tag); + struct ublk_rq_data *data = blk_mq_rq_to_pdu(req); if (ublk_can_use_task_work(ubq)) { - struct ublk_rq_data *data = blk_mq_rq_to_pdu(req); - /* should not fail since we call it just in ubq->ubq_daemon */ task_work_add(ubq->ubq_daemon, &data->work, TWA_SIGNAL_NO_IPI); } else { struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); - pdu->req = req; - io_uring_cmd_complete_in_task(cmd, ublk_rq_task_work_cb); + if (llist_add(&data->node, &ubq->io_cmds)) { + pdu->ubq = ubq; + io_uring_cmd_complete_in_task(cmd, + ublk_rq_task_work_cb); + } } } -- cgit v1.2.3 From fee32f312405726eec6b35b5740c48acda0315e9 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 29 Oct 2022 09:04:32 +0800 Subject: ublk_drv: add ublk_queue_cmd() for cleanup Add helper of ublk_queue_cmd() so that both ublk_queue_rq() and ublk_handle_need_get_data() can reuse this helper. Signed-off-by: Ming Lei Reviewed-by: ZiyangZhang Link: https://lore.kernel.org/r/20221029010432.598367-5-ming.lei@redhat.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 3a59271dafe4..f96cb01e9604 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -817,12 +817,28 @@ static void ublk_submit_cmd(struct ublk_queue *ubq, const struct request *rq) } } +static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq, + bool last) +{ + struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq); + + if (ublk_can_use_task_work(ubq)) { + enum task_work_notify_mode notify_mode = last ? + TWA_SIGNAL_NO_IPI : TWA_NONE; + + if (task_work_add(ubq->ubq_daemon, &data->work, notify_mode)) + __ublk_abort_rq(ubq, rq); + } else { + if (llist_add(&data->node, &ubq->io_cmds)) + ublk_submit_cmd(ubq, rq); + } +} + static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { struct ublk_queue *ubq = hctx->driver_data; struct request *rq = bd->rq; - struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq); blk_status_t res; /* fill iod to slot in io cmd buffer */ @@ -845,21 +861,12 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx, blk_mq_start_request(bd->rq); if (unlikely(ubq_daemon_is_dying(ubq))) { - fail: __ublk_abort_rq(ubq, rq); return BLK_STS_OK; } - if (ublk_can_use_task_work(ubq)) { - enum task_work_notify_mode notify_mode = bd->last ? - TWA_SIGNAL_NO_IPI : TWA_NONE; + ublk_queue_cmd(ubq, rq, bd->last); - if (task_work_add(ubq->ubq_daemon, &data->work, notify_mode)) - goto fail; - } else { - if (llist_add(&data->node, &ubq->io_cmds)) - ublk_submit_cmd(ubq, rq); - } return BLK_STS_OK; } @@ -1185,24 +1192,12 @@ static void ublk_mark_io_ready(struct ublk_device *ub, struct ublk_queue *ubq) } static void ublk_handle_need_get_data(struct ublk_device *ub, int q_id, - int tag, struct io_uring_cmd *cmd) + int tag) { struct ublk_queue *ubq = ublk_get_queue(ub, q_id); struct request *req = blk_mq_tag_to_rq(ub->tag_set.tags[q_id], tag); - struct ublk_rq_data *data = blk_mq_rq_to_pdu(req); - if (ublk_can_use_task_work(ubq)) { - /* should not fail since we call it just in ubq->ubq_daemon */ - task_work_add(ubq->ubq_daemon, &data->work, TWA_SIGNAL_NO_IPI); - } else { - struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); - - if (llist_add(&data->node, &ubq->io_cmds)) { - pdu->ubq = ubq; - io_uring_cmd_complete_in_task(cmd, - ublk_rq_task_work_cb); - } - } + ublk_queue_cmd(ubq, req, true); } static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) @@ -1290,7 +1285,7 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) io->addr = ub_cmd->addr; io->cmd = cmd; io->flags |= UBLK_IO_FLAG_ACTIVE; - ublk_handle_need_get_data(ub, ub_cmd->q_id, ub_cmd->tag, cmd); + ublk_handle_need_get_data(ub, ub_cmd->q_id, ub_cmd->tag); break; default: goto out; -- cgit v1.2.3 From d372ec94a018c3a19dad71e2ee3478126394d9fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 27 Sep 2022 21:06:13 +0300 Subject: drm/i915: Simplify intel_panel_add_edid_alt_fixed_modes() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit a5810f551d0a ("drm/i915: Allow more varied alternate fixed modes for panels") intel_panel_add_edid_alt_fixed_modes() no longer considers vrr vs. drrs separately. So no reason to pass them as separate parameters either. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220927180615.25476-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula (cherry picked from commit eb89e83c152b122a94e79527d63cb7c79823c37e) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_lvds.c | 3 +-- drivers/gpu/drm/i915/display/intel_panel.c | 4 ++-- drivers/gpu/drm/i915/display/intel_panel.h | 2 +- drivers/gpu/drm/i915/display/intel_sdvo.c | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 47419d162f30..2b5bc95a8b0d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5276,7 +5276,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, encoder->devdata, IS_ERR(edid) ? NULL : edid); intel_panel_add_edid_fixed_modes(intel_connector, - intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE, + intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE || intel_vrr_is_capable(intel_connector)); /* MSO requires information from the EDID */ diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 9aa38e8141b5..e5352239b2a2 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -972,8 +972,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) /* Try EDID first */ intel_panel_add_edid_fixed_modes(intel_connector, - intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE, - false); + intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE); /* Failed to get EDID, what about VBT? */ if (!intel_panel_preferred_fixed_mode(intel_connector)) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index a3a3f9fe4342..41cec9dc4223 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -254,10 +254,10 @@ static void intel_panel_destroy_probed_modes(struct intel_connector *connector) } void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, - bool has_drrs, bool has_vrr) + bool use_alt_fixed_modes) { intel_panel_add_edid_preferred_mode(connector); - if (intel_panel_preferred_fixed_mode(connector) && (has_drrs || has_vrr)) + if (intel_panel_preferred_fixed_mode(connector) && use_alt_fixed_modes) intel_panel_add_edid_alt_fixed_modes(connector); intel_panel_destroy_probed_modes(connector); } diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index eff3ffd3d082..5c5b5b7f95b6 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -44,7 +44,7 @@ int intel_panel_fitting(struct intel_crtc_state *crtc_state, int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode); void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, - bool has_drrs, bool has_vrr); + bool use_alt_fixed_modes); void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector); void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector); void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 8046d02a8ad0..8ee7b05ab733 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2901,7 +2901,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) if (!intel_panel_preferred_fixed_mode(intel_connector)) { intel_ddc_get_modes(connector, &intel_sdvo->ddc); - intel_panel_add_edid_fixed_modes(intel_connector, false, false); + intel_panel_add_edid_fixed_modes(intel_connector, false); } intel_panel_init(intel_connector); -- cgit v1.2.3 From 12caf46cf4fc92b1c3884cb363ace2e12732fd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 13:11:29 +0300 Subject: drm/i915/sdvo: Grab mode_config.mutex during LVDS init to avoid WARNs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_mode_probed_add() is unhappy about being called w/o mode_config.mutex. Grab it during LVDS fixed mode setup to silence the WARNs. Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/7301 Fixes: aa2b88074a56 ("drm/i915/sdvo: Fix multi function encoder stuff") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026101134.20865-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula (cherry picked from commit a3cd4f447281c56377de2ee109327400eb00668d) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/display/intel_sdvo.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 8ee7b05ab733..774c1dc31a52 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2900,8 +2900,12 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) intel_panel_add_vbt_sdvo_fixed_mode(intel_connector); if (!intel_panel_preferred_fixed_mode(intel_connector)) { + mutex_lock(&i915->drm.mode_config.mutex); + intel_ddc_get_modes(connector, &intel_sdvo->ddc); intel_panel_add_edid_fixed_modes(intel_connector, false); + + mutex_unlock(&i915->drm.mode_config.mutex); } intel_panel_init(intel_connector); -- cgit v1.2.3 From 363a5328f4b0517e59572118ccfb7c626d81dca9 Mon Sep 17 00:00:00 2001 From: Ziyang Xuan Date: Sat, 29 Oct 2022 17:41:01 +0800 Subject: net: tun: fix bugs for oversize packet when napi frags enabled Recently, we got two syzkaller problems because of oversize packet when napi frags enabled. One of the problems is because the first seg size of the iov_iter from user space is very big, it is 2147479538 which is bigger than the threshold value for bail out early in __alloc_pages(). And skb->pfmemalloc is true, __kmalloc_reserve() would use pfmemalloc reserves without __GFP_NOWARN flag. Thus we got a warning as following: ======================================================== WARNING: CPU: 1 PID: 17965 at mm/page_alloc.c:5295 __alloc_pages+0x1308/0x16c4 mm/page_alloc.c:5295 ... Call trace: __alloc_pages+0x1308/0x16c4 mm/page_alloc.c:5295 __alloc_pages_node include/linux/gfp.h:550 [inline] alloc_pages_node include/linux/gfp.h:564 [inline] kmalloc_large_node+0x94/0x350 mm/slub.c:4038 __kmalloc_node_track_caller+0x620/0x8e4 mm/slub.c:4545 __kmalloc_reserve.constprop.0+0x1e4/0x2b0 net/core/skbuff.c:151 pskb_expand_head+0x130/0x8b0 net/core/skbuff.c:1654 __skb_grow include/linux/skbuff.h:2779 [inline] tun_napi_alloc_frags+0x144/0x610 drivers/net/tun.c:1477 tun_get_user+0x31c/0x2010 drivers/net/tun.c:1835 tun_chr_write_iter+0x98/0x100 drivers/net/tun.c:2036 The other problem is because odd IPv6 packets without NEXTHDR_NONE extension header and have big packet length, it is 2127925 which is bigger than ETH_MAX_MTU(65535). After ipv6_gso_pull_exthdrs() in ipv6_gro_receive(), network_header offset and transport_header offset are all bigger than U16_MAX. That would trigger skb->network_header and skb->transport_header overflow error, because they are all '__u16' type. Eventually, it would affect the value for __skb_push(skb, value), and make it be a big value. After __skb_push() in ipv6_gro_receive(), skb->data would less than skb->head, an out of bounds memory bug occurred. That would trigger the problem as following: ================================================================== BUG: KASAN: use-after-free in eth_type_trans+0x100/0x260 ... Call trace: dump_backtrace+0xd8/0x130 show_stack+0x1c/0x50 dump_stack_lvl+0x64/0x7c print_address_description.constprop.0+0xbc/0x2e8 print_report+0x100/0x1e4 kasan_report+0x80/0x120 __asan_load8+0x78/0xa0 eth_type_trans+0x100/0x260 napi_gro_frags+0x164/0x550 tun_get_user+0xda4/0x1270 tun_chr_write_iter+0x74/0x130 do_iter_readv_writev+0x130/0x1ec do_iter_write+0xbc/0x1e0 vfs_writev+0x13c/0x26c To fix the problems, restrict the packet size less than (ETH_MAX_MTU - NET_SKB_PAD - NET_IP_ALIGN) which has considered reserved skb space in napi_alloc_skb() because transport_header is an offset from skb->head. Add len check in tun_napi_alloc_frags() simply. Fixes: 90e33d459407 ("tun: enable napi_gro_frags() for TUN/TAP driver") Signed-off-by: Ziyang Xuan Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20221029094101.1653855-1-william.xuanziyang@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/tun.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 27c6d235cbda..946628050f28 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1459,7 +1459,8 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile, int err; int i; - if (it->nr_segs > MAX_SKB_FRAGS + 1) + if (it->nr_segs > MAX_SKB_FRAGS + 1 || + len > (ETH_MAX_MTU - NET_SKB_PAD - NET_IP_ALIGN)) return ERR_PTR(-EMSGSIZE); local_bh_disable(); -- cgit v1.2.3 From ca1547ab15f48dc81624183ae17a2fd1bad06dfc Mon Sep 17 00:00:00 2001 From: Saravanan Sekar Date: Sat, 29 Oct 2022 11:29:55 +0200 Subject: iio: adc: mp2629: fix potential array out of bound access Add sentinel at end of maps to avoid potential array out of bound access in iio core. Fixes: 7abd9fb64682 ("iio: adc: mp2629: Add support for mp2629 ADC driver") Signed-off-by: Saravanan Sekar Link: https://lore.kernel.org/r/20221029093000.45451-4-sravanhome@gmail.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mp2629_adc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c index f7af9af1665d..88e947f300cf 100644 --- a/drivers/iio/adc/mp2629_adc.c +++ b/drivers/iio/adc/mp2629_adc.c @@ -57,7 +57,8 @@ static struct iio_map mp2629_adc_maps[] = { MP2629_MAP(SYSTEM_VOLT, "system-volt"), MP2629_MAP(INPUT_VOLT, "input-volt"), MP2629_MAP(BATT_CURRENT, "batt-current"), - MP2629_MAP(INPUT_CURRENT, "input-current") + MP2629_MAP(INPUT_CURRENT, "input-current"), + { } }; static int mp2629_read_raw(struct iio_dev *indio_dev, -- cgit v1.2.3 From 65f20301607d07ee279b0804d11a05a62a6c1a1c Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 24 Oct 2022 16:45:11 +0800 Subject: iio: adc: at91_adc: fix possible memory leak in at91_adc_allocate_trigger() If iio_trigger_register() returns error, it should call iio_trigger_free() to give up the reference that hold in iio_trigger_alloc(), so that it can call iio_trig_release() to free memory when the refcount hit to 0. Fixes: 0e589d5fb317 ("ARM: AT91: IIO: Add AT91 ADC driver.") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221024084511.815096-1-yangyingliang@huawei.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 532daaa6f943..366e252ebeb0 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -634,8 +634,10 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev, trig->ops = &at91_adc_trigger_ops; ret = iio_trigger_register(trig); - if (ret) + if (ret) { + iio_trigger_free(trig); return NULL; + } return trig; } -- cgit v1.2.3 From dd4753f88f242f46d0d8726f5936f64e754a47f2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 14 Oct 2022 12:39:52 +0300 Subject: iio: imu: bno055: uninitialized variable bug in bno055_trigger_handler() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bug is basically harmless, although it will trigger a runtime warning if you use KMSan. On the first iteration through the loop, the "best_delta" variable is uninitialized so re-order the condition to prevent reading uninitialized memory. Fixes: 4aefe1c2bd0c ("iio: imu: add Bosch Sensortec BNO055 core driver") Signed-off-by: Dan Carpenter Acked-by: Nuno Sá Link: https://lore.kernel.org/r/Y0kuaO9PQkSQja+A@kili Signed-off-by: Jonathan Cameron --- drivers/iio/imu/bno055/bno055.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/imu/bno055/bno055.c b/drivers/iio/imu/bno055/bno055.c index 307557a609e3..52744dd98e65 100644 --- a/drivers/iio/imu/bno055/bno055.c +++ b/drivers/iio/imu/bno055/bno055.c @@ -632,7 +632,7 @@ static int bno055_set_regmask(struct bno055_priv *priv, int val, int val2, return -EINVAL; } delta = abs(tbl_val - req_val); - if (delta < best_delta || first) { + if (first || delta < best_delta) { best_delta = delta; hwval = i; first = false; -- cgit v1.2.3 From e6cb8769452e8236b52134e5cb4a18b8f5986932 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 24 Oct 2022 18:28:43 +0200 Subject: wifi: airo: do not assign -1 to unsigned char With char becoming unsigned by default, and with `char` alone being ambiguous and based on architecture, we get a warning when assigning the unchecked output of hex_to_bin() to that unsigned char. Mark `key` as a `u8`, which matches the struct's type, and then check each call to hex_to_bin() before casting. Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Jason A. Donenfeld Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20221024162843.535921-1-Jason@zx2c4.com --- drivers/net/wireless/cisco/airo.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index 10daef81c355..fb2c35bd73bb 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -5232,7 +5232,7 @@ static int get_wep_tx_idx(struct airo_info *ai) return -1; } -static int set_wep_key(struct airo_info *ai, u16 index, const char *key, +static int set_wep_key(struct airo_info *ai, u16 index, const u8 *key, u16 keylen, int perm, int lock) { static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; @@ -5283,7 +5283,7 @@ static void proc_wepkey_on_close(struct inode *inode, struct file *file) struct net_device *dev = pde_data(inode); struct airo_info *ai = dev->ml_priv; int i, rc; - char key[16]; + u8 key[16]; u16 index = 0; int j = 0; @@ -5311,12 +5311,22 @@ static void proc_wepkey_on_close(struct inode *inode, struct file *file) } for (i = 0; i < 16*3 && data->wbuffer[i+j]; i++) { + int val; + + if (i % 3 == 2) + continue; + + val = hex_to_bin(data->wbuffer[i+j]); + if (val < 0) { + airo_print_err(ai->dev->name, "WebKey passed invalid key hex"); + return; + } switch(i%3) { case 0: - key[i/3] = hex_to_bin(data->wbuffer[i+j])<<4; + key[i/3] = (u8)val << 4; break; case 1: - key[i/3] |= hex_to_bin(data->wbuffer[i+j]); + key[i/3] |= (u8)val; break; } } -- cgit v1.2.3 From 6788ba8aed4e28e90f72d68a9d794e34eac17295 Mon Sep 17 00:00:00 2001 From: Dokyung Song Date: Fri, 21 Oct 2022 15:13:59 +0900 Subject: wifi: brcmfmac: Fix potential buffer overflow in brcmf_fweh_event_worker() This patch fixes an intra-object buffer overflow in brcmfmac that occurs when the device provides a 'bsscfgidx' equal to or greater than the buffer size. The patch adds a check that leads to a safe failure if that is the case. This fixes CVE-2022-3628. UBSAN: array-index-out-of-bounds in drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index 52 is out of range for type 'brcmf_if *[16]' CPU: 0 PID: 1898 Comm: kworker/0:2 Tainted: G O 5.14.0+ #132 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 Workqueue: events brcmf_fweh_event_worker Call Trace: dump_stack_lvl+0x57/0x7d ubsan_epilogue+0x5/0x40 __ubsan_handle_out_of_bounds+0x69/0x80 ? memcpy+0x39/0x60 brcmf_fweh_event_worker+0xae1/0xc00 ? brcmf_fweh_call_event_handler.isra.0+0x100/0x100 ? rcu_read_lock_sched_held+0xa1/0xd0 ? rcu_read_lock_bh_held+0xb0/0xb0 ? lockdep_hardirqs_on_prepare+0x273/0x3e0 process_one_work+0x873/0x13e0 ? lock_release+0x640/0x640 ? pwq_dec_nr_in_flight+0x320/0x320 ? rwlock_bug.part.0+0x90/0x90 worker_thread+0x8b/0xd10 ? __kthread_parkme+0xd9/0x1d0 ? process_one_work+0x13e0/0x13e0 kthread+0x379/0x450 ? _raw_spin_unlock_irq+0x24/0x30 ? set_kthread_struct+0x100/0x100 ret_from_fork+0x1f/0x30 ================================================================================ general protection fault, probably for non-canonical address 0xe5601c0020023fff: 0000 [#1] SMP KASAN KASAN: maybe wild-memory-access in range [0x2b0100010011fff8-0x2b0100010011ffff] CPU: 0 PID: 1898 Comm: kworker/0:2 Tainted: G O 5.14.0+ #132 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 Workqueue: events brcmf_fweh_event_worker RIP: 0010:brcmf_fweh_call_event_handler.isra.0+0x42/0x100 Code: 89 f5 53 48 89 fb 48 83 ec 08 e8 79 0b 38 fe 48 85 ed 74 7e e8 6f 0b 38 fe 48 89 ea 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80> 3c 02 00 0f 85 8b 00 00 00 4c 8b 7d 00 44 89 e0 48 ba 00 00 00 RSP: 0018:ffffc9000259fbd8 EFLAGS: 00010207 RAX: dffffc0000000000 RBX: ffff888115d8cd50 RCX: 0000000000000000 RDX: 0560200020023fff RSI: ffffffff8304bc91 RDI: ffff888115d8cd50 RBP: 2b0100010011ffff R08: ffff888112340050 R09: ffffed1023549809 R10: ffff88811aa4c047 R11: ffffed1023549808 R12: 0000000000000045 R13: ffffc9000259fca0 R14: ffff888112340050 R15: ffff888112340000 FS: 0000000000000000(0000) GS:ffff88811aa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000004053ccc0 CR3: 0000000112740000 CR4: 0000000000750ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: brcmf_fweh_event_worker+0x117/0xc00 ? brcmf_fweh_call_event_handler.isra.0+0x100/0x100 ? rcu_read_lock_sched_held+0xa1/0xd0 ? rcu_read_lock_bh_held+0xb0/0xb0 ? lockdep_hardirqs_on_prepare+0x273/0x3e0 process_one_work+0x873/0x13e0 ? lock_release+0x640/0x640 ? pwq_dec_nr_in_flight+0x320/0x320 ? rwlock_bug.part.0+0x90/0x90 worker_thread+0x8b/0xd10 ? __kthread_parkme+0xd9/0x1d0 ? process_one_work+0x13e0/0x13e0 kthread+0x379/0x450 ? _raw_spin_unlock_irq+0x24/0x30 ? set_kthread_struct+0x100/0x100 ret_from_fork+0x1f/0x30 Modules linked in: 88XXau(O) 88x2bu(O) ---[ end trace 41d302138f3ff55a ]--- RIP: 0010:brcmf_fweh_call_event_handler.isra.0+0x42/0x100 Code: 89 f5 53 48 89 fb 48 83 ec 08 e8 79 0b 38 fe 48 85 ed 74 7e e8 6f 0b 38 fe 48 89 ea 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80> 3c 02 00 0f 85 8b 00 00 00 4c 8b 7d 00 44 89 e0 48 ba 00 00 00 RSP: 0018:ffffc9000259fbd8 EFLAGS: 00010207 RAX: dffffc0000000000 RBX: ffff888115d8cd50 RCX: 0000000000000000 RDX: 0560200020023fff RSI: ffffffff8304bc91 RDI: ffff888115d8cd50 RBP: 2b0100010011ffff R08: ffff888112340050 R09: ffffed1023549809 R10: ffff88811aa4c047 R11: ffffed1023549808 R12: 0000000000000045 R13: ffffc9000259fca0 R14: ffff888112340050 R15: ffff888112340000 FS: 0000000000000000(0000) GS:ffff88811aa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000004053ccc0 CR3: 0000000112740000 CR4: 0000000000750ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Kernel panic - not syncing: Fatal exception Reported-by: Dokyung Song Reported-by: Jisoo Jang Reported-by: Minsuk Kang Reviewed-by: Arend van Spriel Cc: Signed-off-by: Dokyung Song Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20221021061359.GA550858@laguna --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index bc3f4e4edcdf..dac7eb77799b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -228,6 +228,10 @@ static void brcmf_fweh_event_worker(struct work_struct *work) brcmf_fweh_event_name(event->code), event->code, event->emsg.ifidx, event->emsg.bsscfgidx, event->emsg.addr); + if (event->emsg.bsscfgidx >= BRCMF_MAX_IFS) { + bphy_err(drvr, "invalid bsscfg index: %u\n", event->emsg.bsscfgidx); + goto event_free; + } /* convert event message */ emsg_be = &event->emsg; -- cgit v1.2.3 From 3f4071cbd2063b917486d1047a4da47718215fee Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Fri, 28 Oct 2022 15:08:26 +0100 Subject: firmware: arm_scmi: Cleanup the core driver removal callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform drivers .remove callbacks are not supposed to fail and report errors. Such errors are indeed ignored by the core platform drivers and the driver unbind process is anyway completed. The SCMI core platform driver as it is now, instead, bails out reporting an error in case of an explicit unbind request. Fix the removal path by adding proper device links between the core SCMI device and the SCMI protocol devices so that a full SCMI stack unbind is triggered when the core driver is removed. The remove process does not bail out anymore on the anomalous conditions triggered by an explicit unbind but the user is still warned. Reported-by: Uwe Kleine-König Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20221028140833.280091-1-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/bus.c | 11 +++++++++++ drivers/firmware/arm_scmi/common.h | 1 + drivers/firmware/arm_scmi/driver.c | 31 +++++++++++++++++++------------ 3 files changed, 31 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index d4e23101448a..35bb70724d44 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -216,9 +216,20 @@ void scmi_device_destroy(struct scmi_device *scmi_dev) device_unregister(&scmi_dev->dev); } +void scmi_device_link_add(struct device *consumer, struct device *supplier) +{ + struct device_link *link; + + link = device_link_add(consumer, supplier, DL_FLAG_AUTOREMOVE_CONSUMER); + + WARN_ON(!link); +} + void scmi_set_handle(struct scmi_device *scmi_dev) { scmi_dev->handle = scmi_handle_get(&scmi_dev->dev); + if (scmi_dev->handle) + scmi_device_link_add(&scmi_dev->dev, scmi_dev->handle->dev); } int scmi_protocol_register(const struct scmi_protocol *proto) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 61aba7447c32..9b87b5b69535 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -97,6 +97,7 @@ static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr) struct scmi_revision_info * scmi_revision_area_get(const struct scmi_protocol_handle *ph); int scmi_handle_put(const struct scmi_handle *handle); +void scmi_device_link_add(struct device *consumer, struct device *supplier); struct scmi_handle *scmi_handle_get(struct device *dev); void scmi_set_handle(struct scmi_device *scmi_dev); void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph, diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 609ebedee9cb..7e19b6055d75 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2273,10 +2273,16 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table) sdev = scmi_get_protocol_device(child, info, id_table->protocol_id, id_table->name); - /* Set handle if not already set: device existed */ - if (sdev && !sdev->handle) - sdev->handle = - scmi_handle_get_from_info_unlocked(info); + if (sdev) { + /* Set handle if not already set: device existed */ + if (!sdev->handle) + sdev->handle = + scmi_handle_get_from_info_unlocked(info); + /* Relink consumer and suppliers */ + if (sdev->handle) + scmi_device_link_add(&sdev->dev, + sdev->handle->dev); + } } else { dev_err(info->dev, "Failed. SCMI protocol %d not active.\n", @@ -2475,20 +2481,17 @@ void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id) static int scmi_remove(struct platform_device *pdev) { - int ret = 0, id; + int ret, id; struct scmi_info *info = platform_get_drvdata(pdev); struct device_node *child; mutex_lock(&scmi_list_mutex); if (info->users) - ret = -EBUSY; - else - list_del(&info->node); + dev_warn(&pdev->dev, + "Still active SCMI users will be forcibly unbound.\n"); + list_del(&info->node); mutex_unlock(&scmi_list_mutex); - if (ret) - return ret; - scmi_notification_exit(&info->handle); mutex_lock(&info->protocols_mtx); @@ -2500,7 +2503,11 @@ static int scmi_remove(struct platform_device *pdev) idr_destroy(&info->active_protocols); /* Safe to free channels since no more users */ - return scmi_cleanup_txrx_channels(info); + ret = scmi_cleanup_txrx_channels(info); + if (ret) + dev_warn(&pdev->dev, "Failed to cleanup SCMI channels.\n"); + + return 0; } static ssize_t protocol_version_show(struct device *dev, -- cgit v1.2.3 From fd96fbc8fad35d6b1872c90df8a2f5d721f14d91 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Fri, 28 Oct 2022 15:08:27 +0100 Subject: firmware: arm_scmi: Suppress the driver's bind attributes Suppress the capability to unbind the core SCMI driver since all the SCMI stack protocol drivers depend on it. Fixes: aa4f886f3893 ("firmware: arm_scmi: add basic driver infrastructure for SCMI") Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20221028140833.280091-2-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 7e19b6055d75..94be633b55a0 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2578,6 +2578,7 @@ MODULE_DEVICE_TABLE(of, scmi_of_match); static struct platform_driver scmi_driver = { .driver = { .name = "arm-scmi", + .suppress_bind_attrs = true, .of_match_table = scmi_of_match, .dev_groups = versions_groups, }, -- cgit v1.2.3 From 59172b212ec0dbb97ceb5671d912e6e61fa802d5 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Fri, 28 Oct 2022 15:08:28 +0100 Subject: firmware: arm_scmi: Make tx_prepare time out eventually SCMI transports based on shared memory, at start of transmissions, have to wait for the shared Tx channel area to be eventually freed by the SCMI platform before accessing the channel. In fact the channel is owned by the SCMI platform until marked as free by the platform itself and, as such, cannot be used by the agent until relinquished. As a consequence a badly misbehaving SCMI platform firmware could lock the channel indefinitely and make the kernel side SCMI stack loop forever waiting for such channel to be freed, possibly hanging the whole boot sequence. Add a timeout to the existent Tx waiting spin-loop so that, when the system ends up in this situation, the SCMI stack can at least bail-out, nosily warn the user, and abort the transmission. Reported-by: YaxiongTian Suggested-by: YaxiongTian Cc: Vincent Guittot Cc: Etienne Carriere Cc: Florian Fainelli Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20221028140833.280091-3-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 4 +++- drivers/firmware/arm_scmi/driver.c | 1 + drivers/firmware/arm_scmi/mailbox.c | 2 +- drivers/firmware/arm_scmi/optee.c | 2 +- drivers/firmware/arm_scmi/shmem.c | 31 +++++++++++++++++++++++++++---- drivers/firmware/arm_scmi/smc.c | 2 +- 6 files changed, 34 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 9b87b5b69535..a1c0154c31c6 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -118,6 +118,7 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id); * * @dev: Reference to device in the SCMI hierarchy corresponding to this * channel + * @rx_timeout_ms: The configured RX timeout in milliseconds. * @handle: Pointer to SCMI entity handle * @no_completion_irq: Flag to indicate that this channel has no completion * interrupt mechanism for synchronous commands. @@ -127,6 +128,7 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id); */ struct scmi_chan_info { struct device *dev; + unsigned int rx_timeout_ms; struct scmi_handle *handle; bool no_completion_irq; void *transport_info; @@ -233,7 +235,7 @@ void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id); struct scmi_shared_mem; void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, - struct scmi_xfer *xfer); + struct scmi_xfer *xfer, struct scmi_chan_info *cinfo); u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem); void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 94be633b55a0..985775f210f9 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2013,6 +2013,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device *dev, return -ENOMEM; cinfo->dev = dev; + cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms; ret = info->desc->ops->chan_setup(cinfo, info->dev, tx); if (ret) diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index 08ff4d110beb..1e40cb035044 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -36,7 +36,7 @@ static void tx_prepare(struct mbox_client *cl, void *m) { struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl); - shmem_tx_prepare(smbox->shmem, m); + shmem_tx_prepare(smbox->shmem, m, smbox->cinfo); } static void rx_callback(struct mbox_client *cl, void *m) diff --git a/drivers/firmware/arm_scmi/optee.c b/drivers/firmware/arm_scmi/optee.c index f42dad997ac9..2a7aeab40e54 100644 --- a/drivers/firmware/arm_scmi/optee.c +++ b/drivers/firmware/arm_scmi/optee.c @@ -498,7 +498,7 @@ static int scmi_optee_send_message(struct scmi_chan_info *cinfo, msg_tx_prepare(channel->req.msg, xfer); ret = invoke_process_msg_channel(channel, msg_command_size(xfer)); } else { - shmem_tx_prepare(channel->req.shmem, xfer); + shmem_tx_prepare(channel->req.shmem, xfer, cinfo); ret = invoke_process_smt_channel(channel); } diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c index 0e3eaea5d852..1dfe534b8518 100644 --- a/drivers/firmware/arm_scmi/shmem.c +++ b/drivers/firmware/arm_scmi/shmem.c @@ -5,10 +5,13 @@ * Copyright (C) 2019 ARM Ltd. */ +#include #include #include #include +#include + #include "common.h" /* @@ -30,16 +33,36 @@ struct scmi_shared_mem { }; void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, - struct scmi_xfer *xfer) + struct scmi_xfer *xfer, struct scmi_chan_info *cinfo) { + ktime_t stop; + /* * Ideally channel must be free by now unless OS timeout last * request and platform continued to process the same, wait * until it releases the shared memory, otherwise we may endup - * overwriting its response with new message payload or vice-versa + * overwriting its response with new message payload or vice-versa. + * Giving up anyway after twice the expected channel timeout so as + * not to bail-out on intermittent issues where the platform is + * occasionally a bit slower to answer. + * + * Note that after a timeout is detected we bail-out and carry on but + * the transport functionality is probably permanently compromised: + * this is just to ease debugging and avoid complete hangs on boot + * due to a misbehaving SCMI firmware. */ - spin_until_cond(ioread32(&shmem->channel_status) & - SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); + stop = ktime_add_ms(ktime_get(), 2 * cinfo->rx_timeout_ms); + spin_until_cond((ioread32(&shmem->channel_status) & + SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE) || + ktime_after(ktime_get(), stop)); + if (!(ioread32(&shmem->channel_status) & + SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) { + WARN_ON_ONCE(1); + dev_err(cinfo->dev, + "Timeout waiting for a free TX channel !\n"); + return; + } + /* Mark channel busy + clear error */ iowrite32(0x0, &shmem->channel_status); iowrite32(xfer->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED, diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c index 745acfdd0b3d..87a7b13cf868 100644 --- a/drivers/firmware/arm_scmi/smc.c +++ b/drivers/firmware/arm_scmi/smc.c @@ -188,7 +188,7 @@ static int smc_send_message(struct scmi_chan_info *cinfo, */ smc_channel_lock_acquire(scmi_info, xfer); - shmem_tx_prepare(scmi_info->shmem, xfer); + shmem_tx_prepare(scmi_info->shmem, xfer, cinfo); arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res); -- cgit v1.2.3 From be9ba1f7f9e0b565b19f4294f5871da9d654bc6d Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Fri, 28 Oct 2022 15:08:29 +0100 Subject: firmware: arm_scmi: Make Rx chan_setup fail on memory errors SCMI Rx channels are optional and they can fail to be setup when not present but anyway channels setup routines must bail-out on memory errors. Make channels setup, and related probing, fail when memory errors are reported on Rx channels. Fixes: 5c8a47a5a91d ("firmware: arm_scmi: Make scmi core independent of the transport type") Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20221028140833.280091-4-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 985775f210f9..f818d00bb2c6 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2045,8 +2045,12 @@ scmi_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id) { int ret = scmi_chan_setup(info, dev, prot_id, true); - if (!ret) /* Rx is optional, hence no error check */ - scmi_chan_setup(info, dev, prot_id, false); + if (!ret) { + /* Rx is optional, report only memory errors */ + ret = scmi_chan_setup(info, dev, prot_id, false); + if (ret && ret != -ENOMEM) + ret = 0; + } return ret; } -- cgit v1.2.3 From 5ffc1c4cb896f8d2cf10309422da3633a616d60f Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Fri, 28 Oct 2022 15:08:30 +0100 Subject: firmware: arm_scmi: Fix devres allocation device in virtio transport SCMI virtio transport device managed allocations must use the main platform device in devres operations instead of the channel devices. Cc: Peter Hilber Fixes: 46abe13b5e3d ("firmware: arm_scmi: Add virtio transport") Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20221028140833.280091-5-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/virtio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c index 14709dbc96a1..36b7686843a4 100644 --- a/drivers/firmware/arm_scmi/virtio.c +++ b/drivers/firmware/arm_scmi/virtio.c @@ -444,12 +444,12 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, for (i = 0; i < vioch->max_msg; i++) { struct scmi_vio_msg *msg; - msg = devm_kzalloc(cinfo->dev, sizeof(*msg), GFP_KERNEL); + msg = devm_kzalloc(dev, sizeof(*msg), GFP_KERNEL); if (!msg) return -ENOMEM; if (tx) { - msg->request = devm_kzalloc(cinfo->dev, + msg->request = devm_kzalloc(dev, VIRTIO_SCMI_MAX_PDU_SIZE, GFP_KERNEL); if (!msg->request) @@ -458,7 +458,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, refcount_set(&msg->users, 1); } - msg->input = devm_kzalloc(cinfo->dev, VIRTIO_SCMI_MAX_PDU_SIZE, + msg->input = devm_kzalloc(dev, VIRTIO_SCMI_MAX_PDU_SIZE, GFP_KERNEL); if (!msg->input) return -ENOMEM; -- cgit v1.2.3 From 1eff6929aff594fba3182660f7b6213ec0ceda0c Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Fri, 28 Oct 2022 15:08:31 +0100 Subject: firmware: arm_scmi: Fix deferred_tx_wq release on error paths Use devres to allocate the dedicated deferred_tx_wq polling workqueue so as to automatically trigger the proper resource release on error path. Reported-by: Dan Carpenter Fixes: 5a3b7185c47c ("firmware: arm_scmi: Add atomic mode support to virtio transport") Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20221028140833.280091-6-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/virtio.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c index 36b7686843a4..33c9b81a55cd 100644 --- a/drivers/firmware/arm_scmi/virtio.c +++ b/drivers/firmware/arm_scmi/virtio.c @@ -148,7 +148,6 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch) { unsigned long flags; DECLARE_COMPLETION_ONSTACK(vioch_shutdown_done); - void *deferred_wq = NULL; /* * Prepare to wait for the last release if not already released @@ -162,16 +161,11 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch) vioch->shutdown_done = &vioch_shutdown_done; virtio_break_device(vioch->vqueue->vdev); - if (!vioch->is_rx && vioch->deferred_tx_wq) { - deferred_wq = vioch->deferred_tx_wq; + if (!vioch->is_rx && vioch->deferred_tx_wq) /* Cannot be kicked anymore after this...*/ vioch->deferred_tx_wq = NULL; - } spin_unlock_irqrestore(&vioch->lock, flags); - if (deferred_wq) - destroy_workqueue(deferred_wq); - scmi_vio_channel_release(vioch); /* Let any possibly concurrent RX path release the channel */ @@ -416,6 +410,11 @@ static bool virtio_chan_available(struct device *dev, int idx) return vioch && !vioch->cinfo; } +static void scmi_destroy_tx_workqueue(void *deferred_tx_wq) +{ + destroy_workqueue(deferred_tx_wq); +} + static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, bool tx) { @@ -430,6 +429,8 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, /* Setup a deferred worker for polling. */ if (tx && !vioch->deferred_tx_wq) { + int ret; + vioch->deferred_tx_wq = alloc_workqueue(dev_name(&scmi_vdev->dev), WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS, @@ -437,6 +438,11 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, if (!vioch->deferred_tx_wq) return -ENOMEM; + ret = devm_add_action_or_reset(dev, scmi_destroy_tx_workqueue, + vioch->deferred_tx_wq); + if (ret) + return ret; + INIT_WORK(&vioch->deferred_tx_work, scmi_vio_deferred_tx_worker); } -- cgit v1.2.3 From 569bea74c94d37785682b11bab76f557520477cd Mon Sep 17 00:00:00 2001 From: Chen Zhongjin Date: Thu, 27 Oct 2022 20:13:53 +0800 Subject: i2c: piix4: Fix adapter not be removed in piix4_remove() In piix4_probe(), the piix4 adapter will be registered in: piix4_probe() piix4_add_adapters_sb800() / piix4_add_adapter() i2c_add_adapter() Based on the probed device type, piix4_add_adapters_sb800() or single piix4_add_adapter() will be called. For the former case, piix4_adapter_count is set as the number of adapters, while for antoher case it is not set and kept default *zero*. When piix4 is removed, piix4_remove() removes the adapters added in piix4_probe(), basing on the piix4_adapter_count value. Because the count is zero for the single adapter case, the adapter won't be removed and makes the sources allocated for adapter leaked, such as the i2c client and device. These sources can still be accessed by i2c or bus and cause problems. An easily reproduced case is that if a new adapter is registered, i2c will get the leaked adapter and try to call smbus_algorithm, which was already freed: Triggered by: rmmod i2c_piix4 && modprobe max31730 BUG: unable to handle page fault for address: ffffffffc053d860 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page Oops: 0000 [#1] PREEMPT SMP KASAN CPU: 0 PID: 3752 Comm: modprobe Tainted: G Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) RIP: 0010:i2c_default_probe (drivers/i2c/i2c-core-base.c:2259) i2c_core RSP: 0018:ffff888107477710 EFLAGS: 00000246 ... i2c_detect (drivers/i2c/i2c-core-base.c:2302) i2c_core __process_new_driver (drivers/i2c/i2c-core-base.c:1336) i2c_core bus_for_each_dev (drivers/base/bus.c:301) i2c_for_each_dev (drivers/i2c/i2c-core-base.c:1823) i2c_core i2c_register_driver (drivers/i2c/i2c-core-base.c:1861) i2c_core do_one_initcall (init/main.c:1296) do_init_module (kernel/module/main.c:2455) ... ---[ end trace 0000000000000000 ]--- Fix this problem by correctly set piix4_adapter_count as 1 for the single adapter so it can be normally removed. Fixes: 528d53a1592b ("i2c: piix4: Fix probing of reserved ports on AMD Family 16h Model 30h") Signed-off-by: Chen Zhongjin Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-piix4.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 39cb1b7bb865..809fbd014cd6 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -1080,6 +1080,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) "", &piix4_main_adapters[0]); if (retval < 0) return retval; + piix4_adapter_count = 1; } /* Check for auxiliary SMBus on some AMD chipsets */ -- cgit v1.2.3 From cdbf26251d3b35c4ccaea0c3a6de4318f727d3d2 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 20 Oct 2022 16:39:33 +0200 Subject: i2c: tegra: Allocate DMA memory for DMA engine When the I2C controllers are running in DMA mode, it is the DMA engine that performs the memory accesses rather than the I2C controller. Pass the DMA engine's struct device pointer to the DMA API to make sure the correct DMA operations are used. This fixes an issue where the DMA engine's SMMU stream ID needs to be misleadingly set for the I2C controllers in device tree. Suggested-by: Robin Murphy Signed-off-by: Thierry Reding Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 954022c04cc4..3869c258a529 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -284,6 +284,7 @@ struct tegra_i2c_dev { struct dma_chan *tx_dma_chan; struct dma_chan *rx_dma_chan; unsigned int dma_buf_size; + struct device *dma_dev; dma_addr_t dma_phys; void *dma_buf; @@ -420,7 +421,7 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len) static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev) { if (i2c_dev->dma_buf) { - dma_free_coherent(i2c_dev->dev, i2c_dev->dma_buf_size, + dma_free_coherent(i2c_dev->dma_dev, i2c_dev->dma_buf_size, i2c_dev->dma_buf, i2c_dev->dma_phys); i2c_dev->dma_buf = NULL; } @@ -472,10 +473,13 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) i2c_dev->tx_dma_chan = chan; + WARN_ON(i2c_dev->tx_dma_chan->device != i2c_dev->rx_dma_chan->device); + i2c_dev->dma_dev = chan->device->dev; + i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len + I2C_PACKET_HEADER_SIZE; - dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size, + dma_buf = dma_alloc_coherent(i2c_dev->dma_dev, i2c_dev->dma_buf_size, &dma_phys, GFP_KERNEL | __GFP_NOWARN); if (!dma_buf) { dev_err(i2c_dev->dev, "failed to allocate DMA buffer\n"); @@ -1272,7 +1276,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, if (i2c_dev->dma_mode) { if (i2c_dev->msg_read) { - dma_sync_single_for_device(i2c_dev->dev, + dma_sync_single_for_device(i2c_dev->dma_dev, i2c_dev->dma_phys, xfer_size, DMA_FROM_DEVICE); @@ -1280,7 +1284,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, if (err) return err; } else { - dma_sync_single_for_cpu(i2c_dev->dev, + dma_sync_single_for_cpu(i2c_dev->dma_dev, i2c_dev->dma_phys, xfer_size, DMA_TO_DEVICE); } @@ -1293,7 +1297,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE, msg->buf, msg->len); - dma_sync_single_for_device(i2c_dev->dev, + dma_sync_single_for_device(i2c_dev->dma_dev, i2c_dev->dma_phys, xfer_size, DMA_TO_DEVICE); @@ -1344,7 +1348,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, } if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) { - dma_sync_single_for_cpu(i2c_dev->dev, + dma_sync_single_for_cpu(i2c_dev->dma_dev, i2c_dev->dma_phys, xfer_size, DMA_FROM_DEVICE); -- cgit v1.2.3 From d6643d7207c572c1b0305ed505101f15502c6c87 Mon Sep 17 00:00:00 2001 From: Nam Cao Date: Thu, 6 Oct 2022 16:54:40 +0200 Subject: i2c: i801: add lis3lv02d's I2C address for Vostro 5568 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dell Vostro 5568 laptop has lis3lv02d, but its i2c address is not known to the kernel. Add this address. Output of "cat /sys/devices/platform/lis3lv02d/position" on Dell Vostro 5568 laptop: - Horizontal: (-18,0,1044) - Front elevated: (522,-18,1080) - Left elevated: (-18,-360,1080) - Upside down: (36,108,-1134) Signed-off-by: Nam Cao Reviewed-by: Jean Delvare Reviewed-by: Pali Rohár Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index e06509edc5f3..1fda1eaa6d6a 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1243,6 +1243,7 @@ static const struct { */ { "Latitude 5480", 0x29 }, { "Vostro V131", 0x1d }, + { "Vostro 5568", 0x29 }, }; static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv) -- cgit v1.2.3 From d755f89220a2b49bc90b7b520bb6edeb4adb5f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 24 Oct 2022 08:46:49 +0300 Subject: drm/i915/psr: Send update also on invalidate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are observing mouse cursor stuttering when using xrandr --scaling=1.2x1.2. X scaling/transformation seems to be doing fronbuffer rendering. When moving mouse cursor X seems to perform several invalidates and only one DirtyFB. I.e. it seems to be assuming updates are sent to panel while drawing is done. Earlier we were disabling PSR in frontbuffer invalidate call back (when drawing in X started). PSR was re-enabled in frontbuffer flush callback (dirtyfb ioctl). This was working fine with X scaling/transformation. Now we are just enabling continuous full frame (cff) in PSR invalidate callback. Enabling cff doesn't trigger any updates. It just configures PSR to send full frame when updates are sent. I.e. there are no updates on screen before PSR flush callback is made. X seems to be doing several updates in frontbuffer before doing dirtyfb ioctl. Fix this by sending single update on every invalidate callback. Cc: José Roberto de Souza Cc: Ville Syrjälä Cc: Mika Kahola Fixes: 805f04d42a6b ("drm/i915/display/psr: Use continuos full frame to handle frontbuffer invalidations") Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6679 Signed-off-by: Jouni Högander Reported-by: Brian J. Tarricone Tested-by: Brian J. Tarricone Reviewed-by: Mika Kahola Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20221024054649.31299-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 904a1049eff3..564d4fd94048 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -2209,8 +2209,11 @@ static void _psr_invalidate_handle(struct intel_dp *intel_dp) if (intel_dp->psr.psr2_sel_fetch_enabled) { u32 val; - if (intel_dp->psr.psr2_sel_fetch_cff_enabled) + if (intel_dp->psr.psr2_sel_fetch_cff_enabled) { + /* Send one update otherwise lag is observed in screen */ + intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0); return; + } val = man_trk_ctl_enable_bit_get(dev_priv) | man_trk_ctl_partial_frame_bit_get(dev_priv) | -- cgit v1.2.3 From ff52fe006fdeacee49745dabed26154db52a6343 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Sun, 9 Oct 2022 10:35:27 +0800 Subject: drm/imx: Kconfig: Remove duplicated 'select DRM_KMS_HELPER' line A duplicated line 'select DRM_KMS_HELPER' was introduced in Kconfig file by commit 09717af7d13d ("drm: Remove CONFIG_DRM_KMS_CMA_HELPER option"), so remove it. Fixes: 09717af7d13d ("drm: Remove CONFIG_DRM_KMS_CMA_HELPER option") Signed-off-by: Liu Ying Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel Link: https://patchwork.freedesktop.org/patch/msgid/20221009023527.3669647-1-victor.liu@nxp.com --- drivers/gpu/drm/imx/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig index 975de4ff7313..fd5b2471fdf0 100644 --- a/drivers/gpu/drm/imx/Kconfig +++ b/drivers/gpu/drm/imx/Kconfig @@ -4,7 +4,6 @@ config DRM_IMX select DRM_KMS_HELPER select VIDEOMODE_HELPERS select DRM_GEM_DMA_HELPER - select DRM_KMS_HELPER depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST) depends on IMX_IPUV3_CORE help -- cgit v1.2.3 From fc007fb815ab5395c3962c09b79a1630b0fbed9c Mon Sep 17 00:00:00 2001 From: Nathan Huckleberry Date: Tue, 13 Sep 2022 13:55:44 -0700 Subject: drm/imx: imx-tve: Fix return type of imx_tve_connector_mode_valid The mode_valid field in drm_connector_helper_funcs is expected to be of type: enum drm_mode_status (* mode_valid) (struct drm_connector *connector, struct drm_display_mode *mode); The mismatched return type breaks forward edge kCFI since the underlying function definition does not match the function hook definition. The return type of imx_tve_connector_mode_valid should be changed from int to enum drm_mode_status. Reported-by: Dan Carpenter Link: https://github.com/ClangBuiltLinux/linux/issues/1703 Cc: llvm@lists.linux.dev Signed-off-by: Nathan Huckleberry Reviewed-by: Nathan Chancellor Reviewed-by: Fabio Estevam Reviewed-by: Philipp Zabel Signed-off-by: Philipp Zabel Link: https://patchwork.freedesktop.org/patch/msgid/20220913205544.155106-1-nhuck@google.com --- drivers/gpu/drm/imx/imx-tve.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index 6b34fac3f73a..ab4d1c878fda 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -218,8 +218,9 @@ static int imx_tve_connector_get_modes(struct drm_connector *connector) return ret; } -static int imx_tve_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +imx_tve_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct imx_tve *tve = con_to_tve(connector); unsigned long rate; -- cgit v1.2.3 From 9d1b073d018bcb1701a00cc3d4b8c6998cc34a4e Mon Sep 17 00:00:00 2001 From: Candice Li Date: Fri, 22 Jul 2022 20:39:12 +0800 Subject: drm/amdgpu: Enable GFX RAS feature for gfx v11_0_3 v1: Support gfx ras feature enablement for gfx v11_0_3. v2: Update function name and error message. Signed-off-by: Candice Li Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 5eefba2948a5..443ce664b663 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -4673,6 +4673,26 @@ static int gfx_v11_0_early_init(void *handle) return 0; } +static int gfx_v11_0_ras_late_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct ras_common_if *gfx_common_if; + int ret; + + gfx_common_if = kzalloc(sizeof(struct ras_common_if), GFP_KERNEL); + if (!gfx_common_if) + return -ENOMEM; + + gfx_common_if->block = AMDGPU_RAS_BLOCK__GFX; + + ret = amdgpu_ras_feature_enable(adev, gfx_common_if, true); + if (ret) + dev_err(adev->dev, "Failed to enable gfx11 ras feature\n"); + + kfree(gfx_common_if); + return ret; +} + static int gfx_v11_0_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -4686,6 +4706,12 @@ static int gfx_v11_0_late_init(void *handle) if (r) return r; + if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3)) { + r = gfx_v11_0_ras_late_init(handle); + if (r) + return r; + } + return 0; } -- cgit v1.2.3 From 2103c42198d38d6c02f8b9720c2a19cf3b4adddd Mon Sep 17 00:00:00 2001 From: Gavin Wan Date: Wed, 26 Oct 2022 13:45:25 -0400 Subject: drm/amdgpu: Disable GPU reset on SRIOV before remove pci. The recent change brought a bug on SRIOV envrionment. It caused unloading amdgpu failed on Guest VM. The reason is that the VF FLR was requested while unloading amdgpu driver, but the VF FLR of SRIOV sequence is wrong while removing PCI device. For SRIOV, the guest driver should not trigger the whole XGMI hive to do the reset. Host driver control how the device been reset. Fixes: f5c7e7797060 ("drm/amdgpu: Adjust removal control flow for smu v13_0_2") Acked-by: Alex Deucher Reviewed-by: Shaoyun Liu Signed-off-by: Gavin Wan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 3c9fecdd6b2f..bf2d50c8c92a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2201,7 +2201,8 @@ amdgpu_pci_remove(struct pci_dev *pdev) pm_runtime_forbid(dev->dev); } - if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)) { + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) && + !amdgpu_sriov_vf(adev)) { bool need_to_reset_gpu = false; if (adev->gmc.xgmi.num_physical_nodes > 1) { -- cgit v1.2.3 From 47a7470bb2ca2d2ccbd945082e5ebf0279a33fe5 Mon Sep 17 00:00:00 2001 From: Yifan Zha Date: Tue, 25 Oct 2022 16:55:05 +0800 Subject: drm/amdgpu: Skip access GRBM_CNTL under SRIOV on gfx_v11 [Why] GRBM_CNTL is a PF_only register on gfx_v11. RLCG interface will return "out of range" under SRIOV VF. [How] Skip access GRBM_CNTL under gfx_v11 SRIOV VF. Signed-off-by: Yifan Zha Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 443ce664b663..f68e13b6282c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1626,7 +1626,8 @@ static void gfx_v11_0_constants_init(struct amdgpu_device *adev) u32 tmp; int i; - WREG32_FIELD15_PREREG(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff); + if (!amdgpu_sriov_vf(adev)) + WREG32_FIELD15_PREREG(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff); gfx_v11_0_setup_rb(adev); gfx_v11_0_get_cu_info(adev, &adev->gfx.cu_info); -- cgit v1.2.3 From e1a29b28e70457549149d3b2c82e4333d68ac49d Mon Sep 17 00:00:00 2001 From: Yifan Zha Date: Tue, 25 Oct 2022 14:46:11 +0800 Subject: drm/amdgpu: Skip access SDMA0_F32_CNTL in sdma_v6_0_enable under SRIOV [Why] SDMA0_F32_CNTL is a PF_only regitser which will be blocked by L1. RLCG will not program the register as well. [How] Skip to program SDMA0_F32_CNTL under SRIOV VF. Signed-off-by: Yifan Zha Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c index d9ae69be5ea4..049c26a45d85 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c @@ -455,6 +455,9 @@ static void sdma_v6_0_enable(struct amdgpu_device *adev, bool enable) sdma_v6_0_rlc_stop(adev); } + if (amdgpu_sriov_vf(adev)) + return; + for (i = 0; i < adev->sdma.num_instances; i++) { f32_cntl = RREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_F32_CNTL)); f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1); -- cgit v1.2.3 From 2c763f37d0a08d39c1a0b1318fa82896c31a6c9d Mon Sep 17 00:00:00 2001 From: Yifan Zha Date: Tue, 25 Oct 2022 15:47:19 +0800 Subject: drm/amdgpu: Skip program gfxhub_v3_0_3 system aperture registers under SRIOV [Why] gfxhub_v3_0_3 system aperture registers are removed from RLCG register access range. [How] Skip access gfxhub_v3_0_3 system aperture registers under SRIOV VF. These registers will be programmed on host side. Signed-off-by: Yifan Zha Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c index 5d3fffd4929f..716ae6f2aefe 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c @@ -154,6 +154,9 @@ static void gfxhub_v3_0_3_init_system_aperture_regs(struct amdgpu_device *adev) { uint64_t value; + if (amdgpu_sriov_vf(adev)) + return; + /* Disable AGP. */ WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BASE, 0); WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, 0); -- cgit v1.2.3 From ee22f63b1085fd5cf1649e8915b1e2617cd33ca0 Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Wed, 26 Oct 2022 17:29:18 +0800 Subject: drm/amdkfd: Remove unused variable kfd_topology_device->cache_count is not used by other fucntions, so remove it. Signed-off-by: Ma Jun Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 1 - drivers/gpu/drm/amd/amdkfd/kfd_topology.h | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 339f60a4cddd..568cbf1d8259 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -1131,7 +1131,6 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache, if (cache->flags & CRAT_CACHE_FLAGS_SIMD_CACHE) props->cache_type |= HSA_CACHE_TYPE_HSACU; - dev->cache_count++; dev->node_props.caches_count++; list_add_tail(&props->list, &dev->cache_props); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h index 9f6c949186c1..90c069fbd581 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h @@ -128,7 +128,6 @@ struct kfd_topology_device { uint32_t proximity_domain; struct kfd_node_properties node_props; struct list_head mem_props; - uint32_t cache_count; struct list_head cache_props; struct list_head io_link_props; struct list_head p2p_link_props; -- cgit v1.2.3 From 26f2fe8608374e3dda39d01a6acd42d1f67b8ee1 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Mon, 31 Oct 2022 10:47:36 -0400 Subject: drm/amd/display: drop vblank_lock from struct amdgpu_display_manager As of commit 09a5df6c444c ("drm/amd/display: Fix multi-display support for idle opt workqueue"), vblank_lock is no longer being used. So, don't init it in amdgpu_dm_init() and remove it from struct amdgpu_display_manager. Reviewed-by: Harry Wentland Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 ------- 2 files changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 94620f9b166c..3130da83e17b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1399,7 +1399,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) mutex_init(&adev->dm.dc_lock); mutex_init(&adev->dm.audio_lock); - spin_lock_init(&adev->dm.vblank_lock); if(amdgpu_dm_irq_init(adev)) { DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index b5ce15c43bcc..b618b2586e7b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -365,13 +365,6 @@ struct amdgpu_display_manager { */ struct mutex audio_lock; - /** - * @vblank_lock: - * - * Guards access to deferred vblank work state. - */ - spinlock_t vblank_lock; - /** * @audio_component: * -- cgit v1.2.3 From 7fbf451e7639f4ce41e2e3e802e5c521c1827b48 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Mon, 17 Oct 2022 18:51:15 -0400 Subject: drm/amd/display: Reinit DPG when exiting dynamic ODM [WHY] DPG must be returned to initialized state when pipe is disabled. [HOW] Reinit DPG on unused pipes when exiting dynamic ODM. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Dillon Varone Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index feff834d5410..b465a83bde6f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1079,6 +1079,29 @@ void dcn20_blank_pixel_data( 0); } + if (!blank && dc->debug.enable_single_display_2to1_odm_policy) { + /* when exiting dynamic ODM need to reinit DPG state for unused pipes */ + struct pipe_ctx *old_odm_pipe = dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].next_odm_pipe; + + odm_pipe = pipe_ctx->next_odm_pipe; + + while (old_odm_pipe) { + if (!odm_pipe || old_odm_pipe->pipe_idx != odm_pipe->pipe_idx) + dc->hwss.set_disp_pattern_generator(dc, + old_odm_pipe, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + CONTROLLER_DP_COLOR_SPACE_UDEFINED, + COLOR_DEPTH_888, + NULL, + 0, + 0, + 0); + old_odm_pipe = old_odm_pipe->next_odm_pipe; + if (odm_pipe) + odm_pipe = odm_pipe->next_odm_pipe; + } + } + if (!blank) if (stream_res->abm) { dc->hwss.set_pipe(pipe_ctx); -- cgit v1.2.3 From 368307cef69ccd9bf5511f25e58e3a103be169fb Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Tue, 11 Oct 2022 14:28:47 -0400 Subject: drm/amd/display: Include virtual signal to set k1 and k2 values Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Eric Bernstein Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index cf5bd9713f54..aeb4822cebc8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -1186,7 +1186,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign *k2_div = PIXEL_RATE_DIV_BY_2; else *k2_div = PIXEL_RATE_DIV_BY_4; - } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { + } else if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) { if (two_pix_per_container) { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_2; -- cgit v1.2.3 From 667be3ef1bb93a599fd425acb914dfbbf433dda0 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 20 Oct 2022 16:07:07 -0400 Subject: drm/amd/display: Don't enable ODM + MPO [Description] Driver doesn't support ODM + MPO Reviewed-by: Dillon Varone Acked-by: Alex Hung Signed-off-by: Alvin Lee Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index aeb4822cebc8..5e0018efe055 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -989,10 +989,6 @@ void dcn32_init_hw(struct dc *dc) dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub); dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; } - - /* Enable support for ODM and windowed MPO if policy flag is set */ - if (dc->debug.enable_single_display_2to1_odm_policy) - dc->config.enable_windowed_mpo_odm = true; } static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream, -- cgit v1.2.3 From 6139ab41f26848c92fd20fd678e1b7e5fb17959c Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 20 Oct 2022 16:21:13 -0400 Subject: drm/amd/display: Update DML formula [why] This is to update SW DML implementation. Reviewed-by: Dmytro Laktyushkin Reviewed-by: Ariel Bernstein Acked-by: Alex Hung Signed-off-by: Charlene Liu Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c | 3 ++- drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c index b612edb14417..45ab0ce50860 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c @@ -1052,7 +1052,8 @@ static bool CalculatePrefetchSchedule( else bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC; /*rev 99*/ - prefetch_bw_pr = dml_min(1, bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane); + prefetch_bw_pr = bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane; + prefetch_bw_pr = dml_min(1, myPipe->VRatio) * prefetch_bw_pr; max_Tsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; prefetch_sw_bytes = PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC; prefetch_bw_oto = dml_max(bytes_pp * myPipe->PixelClock / myPipe->DPPPerPlane, prefetch_sw_bytes / (dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime)); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c index 0d12fd079cd6..53e3e7364ec6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c @@ -1074,7 +1074,8 @@ static bool CalculatePrefetchSchedule( else bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC; /*rev 99*/ - prefetch_bw_pr = dml_min(1, bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane); + prefetch_bw_pr = bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane; + prefetch_bw_pr = dml_min(1, myPipe->VRatio) * prefetch_bw_pr; max_Tsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; prefetch_sw_bytes = PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC; prefetch_bw_oto = dml_max(bytes_pp * myPipe->PixelClock / myPipe->DPPPerPlane, prefetch_sw_bytes / (dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime)); -- cgit v1.2.3 From c40f8b132e6014e3034926cc492f113d9d5ca85b Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Wed, 19 Oct 2022 18:42:49 -0400 Subject: drm/amd/display: Check validation passed after applying pipe split changes [WHY?] Validation can fail for configurations that were previously supported, by only changing parameters such as the DET allocations, which is currently unexpected. [HOW?] Add a check that validation passes after applying pipe split related changes. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Dillon Varone Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index b6cd10f3181c..9c03f62b9d19 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -1736,10 +1736,12 @@ bool dcn32_internal_validate_bw(struct dc *dc, * ensure all the params are calculated correctly. We do not need to run the * pipe split check again after this call (pipes are already split / merged). * */ - if (!fast_validate) { - context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = - dm_prefetch_support_uclk_fclk_and_stutter_if_possible; - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = + dm_prefetch_support_uclk_fclk_and_stutter_if_possible; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + if (vlevel == context->bw_ctx.dml.soc.num_states) { + /* failed after DET size changes */ + goto validate_fail; } } *vlevel_out = vlevel; -- cgit v1.2.3 From 14e1f089d5ee0519af0c646efbc3196d3e1674ba Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Fri, 21 Oct 2022 10:54:42 -0400 Subject: drm/amd/display: Remove rate check from pixel rate divider update [Why] This check is not needed, and can cause CRC mismatch. [How] Remove check and early exit from divider update. Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Hung Signed-off-by: Taimur Hassan Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c index 1bd7e0f327d8..367cb6e6d074 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c @@ -97,7 +97,7 @@ static void dccg314_set_pixel_rate_div( enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA; dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2); - if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA || (k1 == cur_k1 && k2 == cur_k2)) + if (k1 == cur_k1 && k2 == cur_k2) return; switch (otg_inst) { -- cgit v1.2.3 From 361edc61a05cdbc99c6b53264d42af1533e9c20c Mon Sep 17 00:00:00 2001 From: Iswara Nagulendran Date: Fri, 21 Oct 2022 12:27:12 -0400 Subject: drm/amd/display: Modify checks to enable TPS3 pattern when required [HOW&WHY] Checking if both DSC and FEC supported from sink and source before going with TPS3 pattern during link training. Reviewed-by: Anthony Koo Acked-by: Alex Hung Signed-off-by: Iswara Nagulendran Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index bec5e9f787fc..cda1592c3a5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -399,7 +399,11 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, link->psr_settings.force_ffu_mode = 0; copy_settings_data->force_ffu_mode = link->psr_settings.force_ffu_mode; - if (link->fec_state == dc_link_fec_enabled && + if (((link->dpcd_caps.fec_cap.bits.FEC_CAPABLE && + !link->dc->debug.disable_fec) && + (link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && + !link->panel_config.dsc.disable_dsc_edp && + link->dc->caps.edp_dsc_support)) && link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 && (!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1, sizeof(DP_SINK_DEVICE_STR_ID_1)) || -- cgit v1.2.3 From 935e35d8dbde76a02d00290cf4d9eb420514eaf3 Mon Sep 17 00:00:00 2001 From: Martin Leung Date: Fri, 21 Oct 2022 15:28:52 -0400 Subject: drm/amd/display: Stop waiting for vblank during pipe programming [why and how] This line was originally removed for a compliance issue, but then reverted as it caused a fringe underflow case. However, the addition of this line caused a underflow regression when subVP is on, and it needs to be removed again. We plan to fix subvp underflow and then re-add in this line. After that, we will investigate what to do next for the compliance issue. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Martin Leung Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index b465a83bde6f..f3334f513eb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1663,7 +1663,6 @@ static void dcn20_program_pipe( pipe_ctx->pipe_dlg_param.vupdate_width); if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { - pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); } -- cgit v1.2.3 From da339aa4573de3526890627490ee5f61c1de9c31 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Fri, 21 Oct 2022 18:24:02 -0400 Subject: drm/amd/display: Add a debug option HBR2CP2520 over TPS4 [Why & How] There are cases when we may need to override the hardcoded TPS4 test pattern. Added parameters and config option to be able to allow this. Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Leo Chen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 2 ++ 6 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2a6406440032..6be110b00b24 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -393,6 +393,7 @@ struct dc_config { bool disable_dmcu; bool enable_4to1MPC; bool enable_windowed_mpo_odm; + bool forceHBR2CP2520; // Used for switching between test patterns TPS4 and CP2520 uint32_t allow_edp_hotplug_detection; bool clamp_min_dcfclk; uint64_t vblank_alignment_dto_params; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 8729d6305996..8f5e89cb9d3e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1902,6 +1902,8 @@ static bool dcn31_resource_construct( dc->caps.max_slave_rgb_planes = 2; dc->caps.post_blend_color_processing = true; dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; dc->caps.dp_hpo = true; dc->caps.dp_hdmi21_pcon_support = true; dc->caps.edp_dsc_support = true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index 85e2d87a8e44..3b3e093e9447 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -1770,6 +1770,8 @@ static bool dcn314_resource_construct( dc->caps.max_slave_rgb_planes = 2; dc->caps.post_blend_color_processing = true; dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; dc->caps.dp_hpo = true; dc->caps.dp_hdmi21_pcon_support = true; dc->caps.edp_dsc_support = true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index 31cbc5762eab..96a3d41febff 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -1783,6 +1783,8 @@ static bool dcn315_resource_construct( dc->caps.max_slave_rgb_planes = 2; dc->caps.post_blend_color_processing = true; dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; dc->caps.dp_hpo = true; dc->caps.dp_hdmi21_pcon_support = true; dc->caps.edp_dsc_support = true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c index af3eddc0cf32..2f643cdaf59f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c @@ -1785,6 +1785,8 @@ static bool dcn316_resource_construct( dc->caps.max_slave_rgb_planes = 2; dc->caps.post_blend_color_processing = true; dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; dc->caps.dp_hpo = true; dc->caps.dp_hdmi21_pcon_support = true; dc->caps.edp_dsc_support = true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 287b7fa9bf41..4ba9a8662185 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -2126,6 +2126,8 @@ static bool dcn32_resource_construct( dc->caps.max_slave_rgb_planes = 2; dc->caps.post_blend_color_processing = true; dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; dc->caps.dp_hpo = true; dc->caps.dp_hdmi21_pcon_support = true; dc->caps.edp_dsc_support = true; -- cgit v1.2.3 From cf472dbdd7204e1aaaf587df067e8e986616788b Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 22 Oct 2022 22:18:19 -0400 Subject: drm/amd/display: [FW Promotion] Release 0.0.141.0 - Add flag as a status read back that indicates back to back flips detected during psr. Reviewed-by: Aric Cyr Acked-by: Alex Hung Signed-off-by: Anthony Koo Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index bc9344af1995..9df330c86a55 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -225,6 +225,12 @@ union dmub_psr_debug_flags { * Use TPS3 signal when restore main link. */ uint32_t force_wakeup_by_tps3 : 1; + + /** + * Back to back flip, therefore cannot power down PHY + */ + uint32_t back_to_back_flip : 1; + } bitfields; /** -- cgit v1.2.3 From 86975c34b6e2ce85b5b03f3b0a83333c97890ad7 Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 7 Oct 2022 12:43:26 -0400 Subject: drm/amd/display: Fix DCN32 DSC delay calculation [Why] DCN32 DSC delay calculation had an unintentional integer division, resulting in a mismatch against the DML spreadsheet. [How] Cast numerator to double before performing the division. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index ad66e241f9ae..4a3e7a5d2758 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -1746,7 +1746,7 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled, } DSCDelayRequirement_val = DSCDelayRequirement_val + (HTotal - HActive) * - dml_ceil(DSCDelayRequirement_val / HActive, 1); + dml_ceil((double)DSCDelayRequirement_val / HActive, 1); DSCDelayRequirement_val = DSCDelayRequirement_val * PixelClock / PixelClockBackEnd; -- cgit v1.2.3 From e70a70d0c03f5594cd09a1a2732c7e136f9c8edd Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Oct 2022 17:36:32 -0400 Subject: drm/amd/display: Use forced DSC bpp in DML [Why] DSC config is calculated separately from DML calculations. DML should use these separately calculated DSC params. The issue is that the calculated bpp is not properly propagated into DML. [How] Correctly used forced_bpp value in DML. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 5b91660a6496..60351b2891d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -1627,7 +1627,7 @@ static void mode_support_configuration(struct vba_vars_st *v, && !mode_lib->vba.MSOOrODMSplitWithNonDPLink && !mode_lib->vba.NotEnoughLanesForMSO && mode_lib->vba.LinkCapacitySupport[i] == true && !mode_lib->vba.P2IWith420 - && !mode_lib->vba.DSCOnlyIfNecessaryWithBPP + //&& !mode_lib->vba.DSCOnlyIfNecessaryWithBPP && !mode_lib->vba.DSC422NativeNotSupported && !mode_lib->vba.MPCCombineMethodIncompatible && mode_lib->vba.ODMCombine2To1SupportCheckOK[i] == true diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 03924aed8d5c..8e6585dab20e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -625,7 +625,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.skip_dio_check[mode_lib->vba.NumberOfActivePlanes] = dout->is_virtual; - if (!dout->dsc_enable) + if (dout->dsc_enable) mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp; else mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = 0.0; -- cgit v1.2.3 From fa7e2b031faf84a607c2b81c15328314b286bc6a Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Oct 2022 17:40:08 -0400 Subject: drm/amd/display: Round up DST_after_scaler to nearest int [Why] The DST_after_scaler value that DML spreadsheet outputs is generally the driver value round up to the nearest int. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c index a1276f6b9581..395ae8761980 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c @@ -291,8 +291,8 @@ void dml32_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, dml_print("DML_DLG: %s: vready_after_vcount0 = %d\n", __func__, dlg_regs->vready_after_vcount0); - dst_x_after_scaler = get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); - dst_y_after_scaler = get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dst_x_after_scaler = dml_ceil(get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx), 1); + dst_y_after_scaler = dml_ceil(get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx), 1); // do some adjustment on the dst_after scaler to account for odm combine mode dml_print("DML_DLG: %s: input dst_x_after_scaler = %d\n", __func__, dst_x_after_scaler); -- cgit v1.2.3 From f30508e918b4011f44f617f13f8251e72f1a5661 Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Oct 2022 17:46:03 -0400 Subject: drm/amd/display: Add DSC delay factor workaround [Why] Certain 4K high refresh rate modes requiring DSC are exhibiting top of screen underflow corruption. Increasing the DSC delay by a factor of 6 percent stops the underflow for most use cases. [How] Multiply DSC delay requirement in DML by a factor. Add debug option to make this DSC delay factor configurable. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 4 +++- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 5 +++-- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 5 +++-- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h | 3 ++- drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 3 +++ 7 files changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6be110b00b24..b2c1dcae4ca7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -863,6 +863,7 @@ struct dc_debug_options { bool enable_double_buffered_dsc_pg_support; bool enable_dp_dig_pixel_rate_div_policy; enum lttpr_mode lttpr_mode_override; + unsigned int dsc_delay_factor_wa_x1000; }; struct gpu_info_soc_bounding_box_v1_0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 9c03f62b9d19..0d704e302d03 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -2346,9 +2346,11 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; - } + /* DML DSC delay factor workaround */ + dcn3_2_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0; + /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */ dcn3_2_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 60351b2891d0..47ff0a8bd105 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -367,7 +367,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.OutputBpp[k], mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k], mode_lib->vba.NumberOfDSCSlices[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.Output[k], mode_lib->vba.PixelClock[k], - mode_lib->vba.PixelClockBackEnd[k]); + mode_lib->vba.PixelClockBackEnd[k], mode_lib->vba.ip.dsc_delay_factor_wa); } for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) @@ -2475,7 +2475,8 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.OutputBppPerState[i][k], mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k], mode_lib->vba.NumberOfDSCSlices[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.Output[k], - mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k]); + mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k], + mode_lib->vba.ip.dsc_delay_factor_wa); } for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 4a3e7a5d2758..968924c491c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -1726,7 +1726,8 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled, enum output_format_class OutputFormat, enum output_encoder_class Output, double PixelClock, - double PixelClockBackEnd) + double PixelClockBackEnd, + double dsc_delay_factor_wa) { unsigned int DSCDelayRequirement_val; @@ -1764,7 +1765,7 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled, dml_print("DML::%s: DSCDelayRequirement_val = %d\n", __func__, DSCDelayRequirement_val); #endif - return DSCDelayRequirement_val; + return dml_ceil(DSCDelayRequirement_val * dsc_delay_factor_wa, 1); } void dml32_CalculateSurfaceSizeInMall( diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index 55cead0d4237..2c3827546ac7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -327,7 +327,8 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled, enum output_format_class OutputFormat, enum output_encoder_class Output, double PixelClock, - double PixelClockBackEnd); + double PixelClockBackEnd, + double dsc_delay_factor_wa); void dml32_CalculateSurfaceSizeInMall( unsigned int NumberOfActiveSurfaces, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index 7352f7514410..ec0486efab14 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -29,6 +29,7 @@ #include "dcn321_fpu.h" #include "dcn32/dcn32_resource.h" #include "dcn321/dcn321_resource.h" +#include "dml/dcn32/display_mode_vba_util_32.h" #define DCN3_2_DEFAULT_DET_SIZE 256 @@ -538,9 +539,11 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) dcn3_21_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; - } + /* DML DSC delay factor workaround */ + dcn3_21_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0; + /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */ dcn3_21_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index f33a8879b05a..d7be01ac0751 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -364,6 +364,9 @@ struct _vcs_dpi_ip_params_st { unsigned int max_num_dp2p0_outputs; unsigned int max_num_dp2p0_streams; unsigned int VBlankNomDefaultUS; + + /* DM workarounds */ + double dsc_delay_factor_wa; // TODO: Remove after implementing root cause fix }; struct _vcs_dpi_display_xfc_params_st { -- cgit v1.2.3 From 6818f755f737758211d196cf7015628a88622d85 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 21 Oct 2022 15:39:09 -0400 Subject: drm/amd/display: Fix null pointer issues found in emulation [why] fix null point issues found in emulation Reviewed-by: Chris Park Acked-by: Alex Hung Signed-off-by: Charlene Liu Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index bdf101547484..165c920ca776 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -89,7 +89,8 @@ static void enable_memory_low_power(struct dc *dc) REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1); } - if (dc->debug.enable_mem_low_power.bits.mpc) + if (dc->debug.enable_mem_low_power.bits.mpc && + dc->res_pool->mpc->funcs->set_mpc_mem_lp_mode) dc->res_pool->mpc->funcs->set_mpc_mem_lp_mode(dc->res_pool->mpc); @@ -141,7 +142,8 @@ void dcn31_init_hw(struct dc *dc) if (!dcb->funcs->is_accelerated_mode(dcb)) { hws->funcs.bios_golden_init(dc); - hws->funcs.disable_vga(dc->hwseq); + if (hws->funcs.disable_vga) + hws->funcs.disable_vga(dc->hwseq); } // Initialize the dccg if (res_pool->dccg->funcs->dccg_init) -- cgit v1.2.3 From 9ee8b902b891723237e3aace0c2ec640327f31d2 Mon Sep 17 00:00:00 2001 From: Nevenko Stupar Date: Fri, 6 May 2022 16:32:38 -0400 Subject: drm/amd/display: Investigate tool reported FCLK P-state deviations [Why] Fix for some of the tool reported modes for FCLK P-state deviations and UCLK P-state deviations that are coming from DSC terms and/or Scaling terms causing MinActiveFCLKChangeLatencySupported and MaxActiveDRAMClockChangeLatencySupported incorrectly calculated in DML for these configurations. Reviewed-by: Chaitanya Dhere Acked-by: Jasdeep Dhillon Acked-by: Alex Hung Signed-off-by: Nevenko Stupar Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 47ff0a8bd105..3d184679f129 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -364,7 +364,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) { v->DSCDelay[k] = dml32_DSCDelayRequirement(mode_lib->vba.DSCEnabled[k], mode_lib->vba.ODMCombineEnabled[k], mode_lib->vba.DSCInputBitPerComponent[k], - mode_lib->vba.OutputBpp[k], mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k], + mode_lib->vba.OutputBppPerState[mode_lib->vba.VoltageLevel][k], + mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k], mode_lib->vba.NumberOfDSCSlices[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.Output[k], mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k], mode_lib->vba.ip.dsc_delay_factor_wa); -- cgit v1.2.3 From ba6029726854e43e77fec05af5299a671e8483a0 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 23 Oct 2022 13:41:03 -0400 Subject: drm/amd/display: 3.2.210 DC version 3.2.210 brings along the following: - Investigate tool reported FCLK P-state deviations - Fix null pointer issues found in emulation - Add DSC delay factor workaround - Round up DST_after_scaler to nearest int - Use forced DSC bpp in DML - Fix DCN32 DSC delay calculation - Add a debug option HBR2CP2520 over TPS4 - Stop waiting for vblank during pipe programming - Modify checks to enable TPS3 pattern when required - Remove rate check from pixel rate divider update - Check validation passed after applying pipe split changes - Update DML formula - Don't enable ODM + MPO - Include virtual signal to set k1 and k2 values - Reinit DPG when exiting dynamic ODM Acked-by: Alex Hung Signed-off-by: Aric Cyr Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b2c1dcae4ca7..84c82d3a6761 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.209" +#define DC_VER "3.2.210" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From 545094d993f4639482018becda5f2a47d126f0ab Mon Sep 17 00:00:00 2001 From: "Jiri Slaby (SUSE)" Date: Mon, 31 Oct 2022 12:42:47 +0100 Subject: drm/amd/display (gcc13): fix enum mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rn_vbios_smu_set_dcn_low_power_state() produces a valid warning with gcc-13: drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:237:6: error: conflicting types for 'rn_vbios_smu_set_dcn_low_power_state' due to enum/integer mismatch; have 'void(struct clk_mgr_internal *, enum dcn_pwr_state)' drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h:36:6: note: previous declaration of 'rn_vbios_smu_set_dcn_low_power_state' with type 'void(struct clk_mgr_internal *, int)' I.e. the type of the 2nd parameter of rn_vbios_smu_set_dcn_low_power_state() in the declaration is int, while the definition spells enum dcn_pwr_state. Synchronize them to the latter (and add a forward enum declaration). Cc: Martin Liska Cc: Harry Wentland Cc: Leo Li Cc: Rodrigo Siqueira Cc: Alex Deucher Cc: "Christian König" Cc: "Pan, Xinhui" Cc: David Airlie Cc: Daniel Vetter Cc: amd-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Reviewed-by: Harry Wentland Signed-off-by: Jiri Slaby (SUSE) Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h index 3e5df27aa96f..1ce19d875358 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h @@ -26,6 +26,8 @@ #ifndef DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_ #define DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_ +enum dcn_pwr_state; + int rn_vbios_smu_get_smu_version(struct clk_mgr_internal *clk_mgr); int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz); int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr); @@ -33,7 +35,7 @@ int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int reque int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz); void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz); int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz); -void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal *clk_mgr, int display_count); +void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal *clk_mgr, enum dcn_pwr_state); void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable); void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr); int rn_vbios_smu_is_periodic_retraining_disabled(struct clk_mgr_internal *clk_mgr); -- cgit v1.2.3 From 6c412da54c80a54b1a8b7f89677f6e82f0fabec4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 29 Oct 2022 22:57:11 +0200 Subject: sfc: Fix an error handling path in efx_pci_probe() If an error occurs after the first kzalloc() the corresponding memory allocation is never freed. Add the missing kfree() in the error handling path, as already done in the remove() function. Fixes: 7e773594dada ("sfc: Separate efx_nic memory from net_device memory") Signed-off-by: Christophe JAILLET Acked-by: Martin Habets Link: https://lore.kernel.org/r/dc114193121c52c8fa3779e49bdd99d4b41344a9.1667077009.git.christophe.jaillet@wanadoo.fr Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/sfc/efx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 054d5ce6029e..0556542d7a6b 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1059,8 +1059,10 @@ static int efx_pci_probe(struct pci_dev *pci_dev, /* Allocate and initialise a struct net_device */ net_dev = alloc_etherdev_mq(sizeof(probe_data), EFX_MAX_CORE_TX_QUEUES); - if (!net_dev) - return -ENOMEM; + if (!net_dev) { + rc = -ENOMEM; + goto fail0; + } probe_ptr = netdev_priv(net_dev); *probe_ptr = probe_data; efx->net_dev = net_dev; @@ -1132,6 +1134,8 @@ static int efx_pci_probe(struct pci_dev *pci_dev, WARN_ON(rc > 0); netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc); free_netdev(net_dev); + fail0: + kfree(probe_data); return rc; } -- cgit v1.2.3 From 92a66cbf6b30eda5719fbdfb24cd15fb341bba32 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 25 Oct 2022 09:28:00 +0300 Subject: spi: intel: Use correct mask for flash and protected regions The flash and protected region mask is actually 0x7fff (30:16 and 14:0) and not 0x3fff so fix this accordingly. While there use GENMASK() instead. Cc: stable@vger.kernel.org Signed-off-by: Mika Westerberg Link: https://lore.kernel.org/r/20221025062800.22357-1-mika.westerberg@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-intel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c index 605acb1bf4b0..3ac73691fbb5 100644 --- a/drivers/spi/spi-intel.c +++ b/drivers/spi/spi-intel.c @@ -52,17 +52,17 @@ #define FRACC 0x50 #define FREG(n) (0x54 + ((n) * 4)) -#define FREG_BASE_MASK 0x3fff +#define FREG_BASE_MASK GENMASK(14, 0) #define FREG_LIMIT_SHIFT 16 -#define FREG_LIMIT_MASK (0x03fff << FREG_LIMIT_SHIFT) +#define FREG_LIMIT_MASK GENMASK(30, 16) /* Offset is from @ispi->pregs */ #define PR(n) ((n) * 4) #define PR_WPE BIT(31) #define PR_LIMIT_SHIFT 16 -#define PR_LIMIT_MASK (0x3fff << PR_LIMIT_SHIFT) +#define PR_LIMIT_MASK GENMASK(30, 16) #define PR_RPE BIT(15) -#define PR_BASE_MASK 0x3fff +#define PR_BASE_MASK GENMASK(14, 0) /* Offsets are from @ispi->sregs */ #define SSFSTS_CTL 0x00 -- cgit v1.2.3 From 57cadf5b77b5ff21ffba4b82bc1f24be62d361ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Tue, 1 Nov 2022 13:53:42 +0200 Subject: drm/i915/mtl: Fix PSR2_MAN_TRK_CTL bit getter functions for MTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MTL shares PSR2_MAN_TRK_CTL bits with ADL. Currently some bit getter functions are incorrect for MTL. This patch fixes those. Bspec: 49274 Cc: José Roberto de Souza Cc: Mika Kahola Cc: Radhakrishna Sripada Fixes: 47d4ae2192cb ("drm/i915/mtl: Extend PSR support") Signed-off-by: Jouni Högander Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20221101115342.1136720-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 564d4fd94048..e11b0592055f 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1470,7 +1470,8 @@ unlock: static u32 man_trk_ctl_enable_bit_get(struct drm_i915_private *dev_priv) { - return IS_ALDERLAKE_P(dev_priv) ? 0 : PSR2_MAN_TRK_CTL_ENABLE; + return IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14 ? 0 : + PSR2_MAN_TRK_CTL_ENABLE; } static u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private *dev_priv) @@ -1482,14 +1483,14 @@ static u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private *dev_pr static u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv) { - return IS_ALDERLAKE_P(dev_priv) ? + return IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14 ? ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE : PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE; } static u32 man_trk_ctl_continuos_full_frame(struct drm_i915_private *dev_priv) { - return IS_ALDERLAKE_P(dev_priv) ? + return IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14 ? ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME : PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME; } -- cgit v1.2.3 From 71ee71d7adcba648077997a29a91158d20c40b09 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Tue, 1 Nov 2022 01:41:00 -0600 Subject: cxl/region: Fix decoder allocation crash When an intermediate port's decoders have been exhausted by existing regions, and creating a new region with the port in question in it's hierarchical path is attempted, cxl_port_attach_region() fails to find a port decoder (as would be expected), and drops into the failure / cleanup path. However, during cleanup of the region reference, a sanity check attempts to dereference the decoder, which in the above case didn't exist. This causes a NULL pointer dereference BUG. To fix this, refactor the decoder allocation and de-allocation into helper routines, and in this 'free' routine, check that the decoder, @cxld, is valid before attempting any operations on it. Cc: Suggested-by: Dan Williams Signed-off-by: Vishal Verma Reviewed-by: Dave Jiang Fixes: 384e624bb211 ("cxl/region: Attach endpoint decoders") Link: https://lore.kernel.org/r/20221101074100.1732003-1-vishal.l.verma@intel.com Signed-off-by: Dan Williams --- drivers/cxl/core/region.c | 67 +++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index c49d9a5f1091..bb6f4fc84a3f 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -687,18 +687,27 @@ static struct cxl_region_ref *alloc_region_ref(struct cxl_port *port, return cxl_rr; } -static void free_region_ref(struct cxl_region_ref *cxl_rr) +static void cxl_rr_free_decoder(struct cxl_region_ref *cxl_rr) { - struct cxl_port *port = cxl_rr->port; struct cxl_region *cxlr = cxl_rr->region; struct cxl_decoder *cxld = cxl_rr->decoder; + if (!cxld) + return; + dev_WARN_ONCE(&cxlr->dev, cxld->region != cxlr, "region mismatch\n"); if (cxld->region == cxlr) { cxld->region = NULL; put_device(&cxlr->dev); } +} +static void free_region_ref(struct cxl_region_ref *cxl_rr) +{ + struct cxl_port *port = cxl_rr->port; + struct cxl_region *cxlr = cxl_rr->region; + + cxl_rr_free_decoder(cxl_rr); xa_erase(&port->regions, (unsigned long)cxlr); xa_destroy(&cxl_rr->endpoints); kfree(cxl_rr); @@ -729,6 +738,33 @@ static int cxl_rr_ep_add(struct cxl_region_ref *cxl_rr, return 0; } +static int cxl_rr_alloc_decoder(struct cxl_port *port, struct cxl_region *cxlr, + struct cxl_endpoint_decoder *cxled, + struct cxl_region_ref *cxl_rr) +{ + struct cxl_decoder *cxld; + + if (port == cxled_to_port(cxled)) + cxld = &cxled->cxld; + else + cxld = cxl_region_find_decoder(port, cxlr); + if (!cxld) { + dev_dbg(&cxlr->dev, "%s: no decoder available\n", + dev_name(&port->dev)); + return -EBUSY; + } + + if (cxld->region) { + dev_dbg(&cxlr->dev, "%s: %s already attached to %s\n", + dev_name(&port->dev), dev_name(&cxld->dev), + dev_name(&cxld->region->dev)); + return -EBUSY; + } + + cxl_rr->decoder = cxld; + return 0; +} + /** * cxl_port_attach_region() - track a region's interest in a port by endpoint * @port: port to add a new region reference 'struct cxl_region_ref' @@ -795,12 +831,6 @@ static int cxl_port_attach_region(struct cxl_port *port, cxl_rr->nr_targets++; nr_targets_inc = true; } - - /* - * The decoder for @cxlr was allocated when the region was first - * attached to @port. - */ - cxld = cxl_rr->decoder; } else { cxl_rr = alloc_region_ref(port, cxlr); if (IS_ERR(cxl_rr)) { @@ -811,26 +841,11 @@ static int cxl_port_attach_region(struct cxl_port *port, } nr_targets_inc = true; - if (port == cxled_to_port(cxled)) - cxld = &cxled->cxld; - else - cxld = cxl_region_find_decoder(port, cxlr); - if (!cxld) { - dev_dbg(&cxlr->dev, "%s: no decoder available\n", - dev_name(&port->dev)); - goto out_erase; - } - - if (cxld->region) { - dev_dbg(&cxlr->dev, "%s: %s already attached to %s\n", - dev_name(&port->dev), dev_name(&cxld->dev), - dev_name(&cxld->region->dev)); - rc = -EBUSY; + rc = cxl_rr_alloc_decoder(port, cxlr, cxled, cxl_rr); + if (rc) goto out_erase; - } - - cxl_rr->decoder = cxld; } + cxld = cxl_rr->decoder; rc = cxl_rr_ep_add(cxl_rr, cxled); if (rc) { -- cgit v1.2.3 From 486c292230166c2d61701d3c984bf9143588ea28 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Sun, 30 Oct 2022 22:36:34 +0100 Subject: net: lan966x: Fix the MTU calculation When the MTU was changed, the lan966x didn't take in consideration the L2 header and the FCS. So the HW was configured with a smaller value than what was desired. Therefore the correct value to configure the HW would be new_mtu + ETH_HLEN + ETH_FCS_LEN. The vlan tag is not considered here, because at the time when the blamed commit was added, there was no vlan filtering support. The vlan fix will be part of the next patch. Fixes: d28d6d2e37d1 ("net: lan966x: add port module support") Signed-off-by: Horatiu Vultur Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microchip/lan966x/lan966x_main.c | 2 +- drivers/net/ethernet/microchip/lan966x/lan966x_main.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index be2fd030cccb..b3070c3fcad0 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -386,7 +386,7 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu) int old_mtu = dev->mtu; int err; - lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(new_mtu), + lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(LAN966X_HW_MTU(new_mtu)), lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port)); dev->mtu = new_mtu; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index 9656071b8289..4ec33999e4df 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -26,6 +26,8 @@ #define LAN966X_BUFFER_MEMORY (160 * 1024) #define LAN966X_BUFFER_MIN_SZ 60 +#define LAN966X_HW_MTU(mtu) ((mtu) + ETH_HLEN + ETH_FCS_LEN) + #define PGID_AGGR 64 #define PGID_SRC 80 #define PGID_ENTRIES 89 -- cgit v1.2.3 From 25f28bb1b4a7717a9df3aa574d210374ebb6bb23 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Sun, 30 Oct 2022 22:36:35 +0100 Subject: net: lan966x: Adjust maximum frame size when vlan is enabled/disabled When vlan filtering is enabled/disabled, it is required to adjust the maximum received frame size that it can received. When vlan filtering is enabled, it would all to receive extra 4 bytes, that are the vlan tag. So the maximum frame size would be 1522 with a vlan tag. If vlan filtering is disabled then the maximum frame size would be 1518 regardless if there is or not a vlan tag. Fixes: 6d2c186afa5d ("net: lan966x: Add vlan support.") Signed-off-by: Horatiu Vultur Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microchip/lan966x/lan966x_regs.h | 15 +++++++++++++++ drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c | 6 ++++++ 2 files changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h index 1d90b93dd417..fb5087fef22e 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h @@ -585,6 +585,21 @@ enum lan966x_target { #define DEV_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\ FIELD_GET(DEV_MAC_MAXLEN_CFG_MAX_LEN, x) +/* DEV:MAC_CFG_STATUS:MAC_TAGS_CFG */ +#define DEV_MAC_TAGS_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 12, 0, 1, 4) + +#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA BIT(1) +#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(x)\ + FIELD_PREP(DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, x) +#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_GET(x)\ + FIELD_GET(DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, x) + +#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA BIT(0) +#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(x)\ + FIELD_PREP(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA, x) +#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_GET(x)\ + FIELD_GET(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA, x) + /* DEV:MAC_CFG_STATUS:MAC_IFG_CFG */ #define DEV_MAC_IFG_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 20, 0, 1, 4) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c index 8d7260cd7da9..3c44660128da 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c @@ -169,6 +169,12 @@ void lan966x_vlan_port_apply(struct lan966x_port *port) ANA_VLAN_CFG_VLAN_POP_CNT, lan966x, ANA_VLAN_CFG(port->chip_port)); + lan_rmw(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(port->vlan_aware) | + DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(port->vlan_aware), + DEV_MAC_TAGS_CFG_VLAN_AWR_ENA | + DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, + lan966x, DEV_MAC_TAGS_CFG(port->chip_port)); + /* Drop frames with multicast source address */ val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1); if (port->vlan_aware && !pvid) -- cgit v1.2.3 From 872ad758f9b7fb4eb42aebaf64e50c5b29b7ffe5 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Sun, 30 Oct 2022 22:36:36 +0100 Subject: net: lan966x: Fix FDMA when MTU is changed When MTU is changed, FDMA is required to calculate what is the maximum size of the frame that it can received. So it can calculate what is the page order needed to allocate for the received frames. The first problem was that, when the max MTU was calculated it was reading the value from dev and not from HW, so in this way it was missing L2 header + the FCS. The other problem was that once the skb is created using __build_skb_around, it would reserve some space for skb_shared_info. So if we received a frame which size is at the limit of the page order then the creating will failed because it would not have space to put all the data. Fixes: 2ea1cbac267e ("net: lan966x: Update FDMA to change MTU.") Signed-off-by: Horatiu Vultur Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c | 8 ++++++-- drivers/net/ethernet/microchip/lan966x/lan966x_main.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c index a42035cec611..c235edd2b182 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c @@ -668,12 +668,14 @@ static int lan966x_fdma_get_max_mtu(struct lan966x *lan966x) int i; for (i = 0; i < lan966x->num_phys_ports; ++i) { + struct lan966x_port *port; int mtu; - if (!lan966x->ports[i]) + port = lan966x->ports[i]; + if (!port) continue; - mtu = lan966x->ports[i]->dev->mtu; + mtu = lan_rd(lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port)); if (mtu > max_mtu) max_mtu = mtu; } @@ -733,6 +735,8 @@ int lan966x_fdma_change_mtu(struct lan966x *lan966x) max_mtu = lan966x_fdma_get_max_mtu(lan966x); max_mtu += IFH_LEN * sizeof(u32); + max_mtu += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + max_mtu += VLAN_HLEN * 2; if (round_up(max_mtu, PAGE_SIZE) / PAGE_SIZE - 1 == lan966x->rx.page_order) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index b3070c3fcad0..20ee5b28f70a 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -395,7 +395,7 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu) err = lan966x_fdma_change_mtu(lan966x); if (err) { - lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(old_mtu), + lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(LAN966X_HW_MTU(old_mtu)), lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port)); dev->mtu = old_mtu; } -- cgit v1.2.3 From fc57062f98b0b0ae52bc584d8fd5ac77c50df607 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Mon, 31 Oct 2022 14:34:21 +0100 Subject: net: lan966x: Fix unmapping of received frames using FDMA When lan966x was receiving a frame, then it was building the skb and after that it was calling dma_unmap_single with frame size as the length. This actually has 2 issues: 1. It is using a length to map and a different length to unmap. 2. When the unmap was happening, the data was sync for cpu but it could be that this will overwrite what build_skb was initializing. The fix for these two problems is to change the order of operations. First to sync the frame for cpu, then to build the skb and in the end to unmap using the correct size but without sync the frame again for cpu. Fixes: c8349639324a ("net: lan966x: Add FDMA functionality") Signed-off-by: Horatiu Vultur Link: https://lore.kernel.org/r/20221031133421.1283196-1-horatiu.vultur@microchip.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c index c235edd2b182..e6948939ccc2 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c @@ -414,13 +414,15 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx) /* Get the received frame and unmap it */ db = &rx->dcbs[rx->dcb_index].db[rx->db_index]; page = rx->page[rx->dcb_index][rx->db_index]; + + dma_sync_single_for_cpu(lan966x->dev, (dma_addr_t)db->dataptr, + FDMA_DCB_STATUS_BLOCKL(db->status), + DMA_FROM_DEVICE); + skb = build_skb(page_address(page), PAGE_SIZE << rx->page_order); if (unlikely(!skb)) goto unmap_page; - dma_unmap_single(lan966x->dev, (dma_addr_t)db->dataptr, - FDMA_DCB_STATUS_BLOCKL(db->status), - DMA_FROM_DEVICE); skb_put(skb, FDMA_DCB_STATUS_BLOCKL(db->status)); lan966x_ifh_get_src_port(skb->data, &src_port); @@ -429,6 +431,10 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx) if (WARN_ON(src_port >= lan966x->num_phys_ports)) goto free_skb; + dma_unmap_single_attrs(lan966x->dev, (dma_addr_t)db->dataptr, + PAGE_SIZE << rx->page_order, DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + skb->dev = lan966x->ports[src_port]->dev; skb_pull(skb, IFH_LEN * sizeof(u32)); @@ -454,9 +460,9 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx) free_skb: kfree_skb(skb); unmap_page: - dma_unmap_page(lan966x->dev, (dma_addr_t)db->dataptr, - FDMA_DCB_STATUS_BLOCKL(db->status), - DMA_FROM_DEVICE); + dma_unmap_single_attrs(lan966x->dev, (dma_addr_t)db->dataptr, + PAGE_SIZE << rx->page_order, DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); __free_pages(page, rx->page_order); return NULL; -- cgit v1.2.3 From 134af9aa88453aeb9224e407092530ebba366c6c Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 2 Nov 2022 09:46:01 +0100 Subject: spi: meson-spicc: fix do_div build error on non-arm64 This fixes : error: passing argument 1 of '__div64_32' from incompatible pointer type By passing an uint64_t as first variable to do_div(). Reported-by: kernel test robot Fixes: 04694e50020b ("spi: meson-spicc: move wait completion in driver to take bursts delay in account") Acked-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20221027-b4-spicc-burst-delay-fix-v2-0-8cc2bab3417a@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-meson-spicc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 52bffab18329..1b4195c54ee2 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -387,7 +387,7 @@ static int meson_spicc_transfer_one(struct spi_master *master, struct spi_transfer *xfer) { struct meson_spicc_device *spicc = spi_master_get_devdata(master); - unsigned long timeout; + uint64_t timeout; /* Store current transfer */ spicc->xfer = xfer; -- cgit v1.2.3 From e7d1d4d9ac0dfa40be4c2c8abd0731659869b297 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 31 Oct 2022 20:13:40 +0800 Subject: mISDN: fix possible memory leak in mISDN_register_device() Afer commit 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array"), the name of device is allocated dynamically, add put_device() to give up the reference, so that the name can be freed in kobject_cleanup() when the refcount is 0. Set device class before put_device() to avoid null release() function WARN message in device_release(). Fixes: 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array") Signed-off-by: Yang Yingliang Signed-off-by: David S. Miller --- drivers/isdn/mISDN/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c index a41b4b264594..7ea0100f218a 100644 --- a/drivers/isdn/mISDN/core.c +++ b/drivers/isdn/mISDN/core.c @@ -233,11 +233,12 @@ mISDN_register_device(struct mISDNdevice *dev, if (debug & DEBUG_CORE) printk(KERN_DEBUG "mISDN_register %s %d\n", dev_name(&dev->dev), dev->id); + dev->dev.class = &mISDN_class; + err = create_stack(dev); if (err) goto error1; - dev->dev.class = &mISDN_class; dev->dev.platform_data = dev; dev->dev.parent = parent; dev_set_drvdata(&dev->dev, dev); @@ -249,8 +250,8 @@ mISDN_register_device(struct mISDNdevice *dev, error3: delete_stack(dev); - return err; error1: + put_device(&dev->dev); return err; } -- cgit v1.2.3 From bf00f5426074249058a106a6edbb89e4b25a4d79 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 31 Oct 2022 20:13:41 +0800 Subject: isdn: mISDN: netjet: fix wrong check of device registration The class is set in mISDN_register_device(), but if device_add() returns error, it will lead to delete a device without added, fix this by using device_is_registered() to check if the device is registered. Fixes: a900845e5661 ("mISDN: Add support for Traverse Technologies NETJet PCI cards") Signed-off-by: Yang Yingliang Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/netjet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index a52f275f8263..f8447135a902 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -956,7 +956,7 @@ nj_release(struct tiger_hw *card) } if (card->irq > 0) free_irq(card->irq, card); - if (card->isac.dch.dev.dev.class) + if (device_is_registered(&card->isac.dch.dev.dev)) mISDN_unregister_device(&card->isac.dch.dev); for (i = 0; i < 2; i++) { -- cgit v1.2.3 From 7f9dbf54c3dc7170df86f7753abb41b5d7e8779e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 24 Oct 2022 17:11:02 +0100 Subject: HID: asus: Remove unused variable in asus_report_tool_width() Variable count is just being incremented and it's never used anywhere else. The variable and the increment are redundant so remove it. Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/hid/hid-asus.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index b59c3dafa6a4..f99752b998f3 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -219,14 +219,13 @@ static void asus_report_tool_width(struct asus_drvdata *drvdat) { struct input_mt *mt = drvdat->input->mt; struct input_mt_slot *oldest; - int oldid, count, i; + int oldid, i; if (drvdat->tp->contact_size < 5) return; oldest = NULL; oldid = mt->trkid; - count = 0; for (i = 0; i < mt->num_slots; ++i) { struct input_mt_slot *ps = &mt->slots[i]; @@ -238,7 +237,6 @@ static void asus_report_tool_width(struct asus_drvdata *drvdat) oldest = ps; oldid = id; } - count++; } if (oldest) { -- cgit v1.2.3 From b5bcb94b0954a026bbd671741fdb00e7141f9c91 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 28 Oct 2022 21:40:43 +0800 Subject: HID: hyperv: fix possible memory leak in mousevsc_probe() If hid_add_device() returns error, it should call hid_destroy_device() to free hid_dev which is allocated in hid_allocate_device(). Fixes: 74c4fb058083 ("HID: hv_mouse: Properly add the hid device") Signed-off-by: Yang Yingliang Reviewed-by: Wei Liu Signed-off-by: Jiri Kosina --- drivers/hid/hid-hyperv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index e0bc73124196..ab57b49a44ed 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -499,7 +499,7 @@ static int mousevsc_probe(struct hv_device *device, ret = hid_add_device(hid_dev); if (ret) - goto probe_err1; + goto probe_err2; ret = hid_parse(hid_dev); -- cgit v1.2.3 From 3a89b6dec9920026eaa90fe8457f4348d3388a98 Mon Sep 17 00:00:00 2001 From: "Tyler J. Stachecki" Date: Wed, 2 Nov 2022 18:56:39 +0200 Subject: wifi: ath11k: Fix QCN9074 firmware boot on x86 The 2.7.0 series of QCN9074's firmware requests 5 segments of memory instead of 3 (as in the 2.5.0 series). The first segment (11M) is too large to be kalloc'd in one go on x86 and requires piecemeal 1MB allocations, as was the case with the prior public firmware (2.5.0, 15M). Since f6f92968e1e5, ath11k will break the memory requests, but only if there were fewer than 3 segments requested by the firmware. It seems that 5 segments works fine and allows QCN9074 to boot on x86 with firmware 2.7.0, so change things accordingly. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1 Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.16 Signed-off-by: Tyler J. Stachecki Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20221022042728.43015-1-stachecki.tyler@gmail.com --- drivers/net/wireless/ath/ath11k/qmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h index 2ec56a34fa81..0909d53cefeb 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h @@ -27,7 +27,7 @@ #define ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 52 #define ATH11K_QMI_CALDB_SIZE 0x480000 #define ATH11K_QMI_BDF_EXT_STR_LENGTH 0x20 -#define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT 3 +#define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT 5 #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 -- cgit v1.2.3 From f45cb6b29cd36514e13f7519770873d8c0457008 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Wed, 2 Nov 2022 13:48:03 +0200 Subject: wifi: ath11k: avoid deadlock during regulatory update in ath11k_regd_update() (cherry picked from commit d99884ad9e3673a12879bc2830f6e5a66cccbd78 in ath-next as users are seeing this bug more now, also cc stable) Running this test in a loop it is easy to reproduce an rtnl deadlock: iw reg set FI ifconfig wlan0 down What happens is that thread A (workqueue) tries to update the regulatory: try to acquire the rtnl_lock of ar->regd_update_work rtnl_lock+0x17/0x20 ath11k_regd_update+0x15a/0x260 [ath11k] ath11k_regd_update_work+0x15/0x20 [ath11k] process_one_work+0x228/0x670 worker_thread+0x4d/0x440 kthread+0x16d/0x1b0 ret_from_fork+0x22/0x30 And thread B (ifconfig) tries to stop the interface: try to cancel_work_sync(&ar->regd_update_work) in ath11k_mac_op_stop(). ifconfig 3109 [003] 2414.232506: probe: ath11k_mac_op_stop: (ffffffffc14187a0) drv_stop+0x30 ([mac80211]) ieee80211_do_stop+0x5d2 ([mac80211]) ieee80211_stop+0x3e ([mac80211]) __dev_close_many+0x9e ([kernel.kallsyms]) __dev_change_flags+0xbe ([kernel.kallsyms]) dev_change_flags+0x23 ([kernel.kallsyms]) devinet_ioctl+0x5e3 ([kernel.kallsyms]) inet_ioctl+0x197 ([kernel.kallsyms]) sock_do_ioctl+0x4d ([kernel.kallsyms]) sock_ioctl+0x264 ([kernel.kallsyms]) __x64_sys_ioctl+0x92 ([kernel.kallsyms]) do_syscall_64+0x3a ([kernel.kallsyms]) entry_SYSCALL_64_after_hwframe+0x63 ([kernel.kallsyms]) __GI___ioctl+0x7 (/lib/x86_64-linux-gnu/libc-2.23.so) The sequence of deadlock is: 1. Thread B calls rtnl_lock(). 2. Thread A starts to run and calls rtnl_lock() from within ath11k_regd_update_work(), then enters wait state because the lock is owned by thread B. 3. Thread B continues to run and tries to call cancel_work_sync(&ar->regd_update_work), but thread A is in ath11k_regd_update_work() waiting for rtnl_lock(). So cancel_work_sync() forever waits for ath11k_regd_update_work() to finish and we have a deadlock. Fix this by switching from using regulatory_set_wiphy_regd_sync() to regulatory_set_wiphy_regd(). Now cfg80211 will schedule another workqueue which handles the locking on it's own. So the ath11k workqueue can simply exit without taking any locks, avoiding the deadlock. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 Cc: Signed-off-by: Wen Gong [kvalo: improve commit log] Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath11k/reg.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c index 7ee3ff69dfc8..6fae4e61ede7 100644 --- a/drivers/net/wireless/ath/ath11k/reg.c +++ b/drivers/net/wireless/ath/ath11k/reg.c @@ -287,11 +287,7 @@ int ath11k_regd_update(struct ath11k *ar) goto err; } - rtnl_lock(); - wiphy_lock(ar->hw->wiphy); - ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy); - wiphy_unlock(ar->hw->wiphy); - rtnl_unlock(); + ret = regulatory_set_wiphy_regd(ar->hw->wiphy, regd_copy); kfree(regd_copy); -- cgit v1.2.3 From 341421084d705475817f7f0d68e130370d10b20d Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Thu, 20 Oct 2022 11:46:40 -0400 Subject: drm/amd/display: Update DSC capabilitie for DCN314 dcn314 has 4 DSC - conflicted hardware document updated and confirmed. Tested-by: Mark Broadworth Reviewed-by: Charlene Liu Acked-by: Rodrigo Siqueira Signed-off-by: Leo Chen Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index d0ad72caead2..9066c511a052 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -847,7 +847,7 @@ static const struct resource_caps res_cap_dcn314 = { .num_ddc = 5, .num_vmid = 16, .num_mpc_3dlut = 2, - .num_dsc = 3, + .num_dsc = 4, }; static const struct dc_plane_cap plane_cap = { -- cgit v1.2.3 From 14aed119942f6c2f1286022323139f7404db5d2b Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Thu, 20 Oct 2022 11:46:41 -0400 Subject: drm/amd/display: Ignore Cable ID Feature Ignore cable ID for DP2 receivers that does not support the feature. Tested-by: Mark Broadworth Reviewed-by: Roman Li Acked-by: Rodrigo Siqueira Signed-off-by: Fangzhi Zuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c053cb79cd06..589bee9acf16 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1549,6 +1549,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm; + /* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */ + adev->dm.dc->debug.ignore_cable_id = true; + r = dm_dmub_hw_init(adev); if (r) { DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); -- cgit v1.2.3 From e59843c4cdd68a369591630088171eeacce9859f Mon Sep 17 00:00:00 2001 From: Jun Lei Date: Thu, 20 Oct 2022 11:46:44 -0400 Subject: drm/amd/display: Limit dcn32 to 1950Mhz display clock [why] Hardware team recommends we limit dispclock to 1950Mhz for all DCN3.2.x [how] Limit to 1950 when initializing clocks. Tested-by: Mark Broadworth Reviewed-by: Alvin Lee Acked-by: Rodrigo Siqueira Signed-off-by: Jun Lei Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index 1c612ccf1944..fd0313468fdb 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -157,6 +157,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); unsigned int num_levels; struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk; + unsigned int i; memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks)); clk_mgr_base->clks.p_state_change_support = true; @@ -205,18 +206,17 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) clk_mgr->dpm_present = true; if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) { - unsigned int i; - for (i = 0; i < num_levels; i++) if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz)) clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz = khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz); } + for (i = 0; i < num_levels; i++) + if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz > 1950) + clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz = 1950; if (clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz) { - unsigned int i; - for (i = 0; i < num_levels; i++) if (clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz)) -- cgit v1.2.3 From c580d758ba1b79de9ea7a475d95a6278736ae462 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 20 Oct 2022 11:46:47 -0400 Subject: drm/amd/display: Update latencies on DCN321 Update DF related latencies based on new measurements. Tested-by: Mark Broadworth Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Dillon Varone Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index dd90f241e906..7352f7514410 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -119,15 +119,15 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_21_soc = { }, }, .num_states = 1, - .sr_exit_time_us = 12.36, - .sr_enter_plus_exit_time_us = 16.72, + .sr_exit_time_us = 19.95, + .sr_enter_plus_exit_time_us = 24.36, .sr_exit_z8_time_us = 285.0, .sr_enter_plus_exit_z8_time_us = 320, .writeback_latency_us = 12.0, .round_trip_ping_latency_dcfclk_cycles = 263, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, + .urgent_latency_pixel_data_only_us = 9.35, + .urgent_latency_pixel_mixed_with_vm_data_us = 9.35, + .urgent_latency_vm_data_only_us = 9.35, .fclk_change_latency_us = 20, .usr_retraining_latency_us = 2, .smn_latency_us = 2, -- cgit v1.2.3 From 6cb5cec16c380be4cf9776a8c23b72e9fe742fd1 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 20 Oct 2022 11:46:48 -0400 Subject: drm/amd/display: Set memclk levels to be at least 1 for dcn32 [Why] Cannot report 0 memclk levels even when SMU does not provide any. [How] When memclk levels reported by SMU is 0, set levels to 1. Tested-by: Mark Broadworth Reviewed-by: Martin Leung Acked-by: Rodrigo Siqueira Signed-off-by: Dillon Varone Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index fd0313468fdb..6f77d8e538ab 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -669,6 +669,9 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) &clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz, &num_entries_per_clk->num_memclk_levels); + /* memclk must have at least one level */ + num_entries_per_clk->num_memclk_levels = num_entries_per_clk->num_memclk_levels ? num_entries_per_clk->num_memclk_levels : 1; + dcn32_init_single_clock(clk_mgr, PPCLK_FCLK, &clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz, &num_entries_per_clk->num_fclk_levels); -- cgit v1.2.3 From c3d3f35b725bf9c93bec6d3c056f6bb7cfd27403 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 20 Oct 2022 11:46:51 -0400 Subject: drm/amd/display: Enable timing sync on DCN32 Missed enabling timing sync on DCN32 because DCN32 has a different DML param. Tested-by: Mark Broadworth Reviewed-by: Martin Leung Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index d680f1c5b69f..45db40c41882 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -1228,6 +1228,7 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.src.dcc = false; pipes[pipe_cnt].pipe.src.dcc_rate = 1; pipes[pipe_cnt].pipe.dest.synchronized_vblank_all_planes = synchronized_vblank; + pipes[pipe_cnt].pipe.dest.synchronize_timings = synchronized_vblank; pipes[pipe_cnt].pipe.dest.hblank_start = timing->h_total - timing->h_front_porch; pipes[pipe_cnt].pipe.dest.hblank_end = pipes[pipe_cnt].pipe.dest.hblank_start - timing->h_addressable -- cgit v1.2.3 From 9cb0dc6ccb7df9abe1407574ed4ad84895822d11 Mon Sep 17 00:00:00 2001 From: Max Tseng Date: Thu, 20 Oct 2022 11:46:52 -0400 Subject: drm/amd/display: cursor update command incomplete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missing send cursor_rect width & Height into DMUB. PSR-SU would use these information. But missing these assignment in last refactor commit Reported-by: Timur Kristóf Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2227 Fixes: b73353f7f3d4 ("drm/amd/display: Use the same cursor info across features") Tested-by: Mark Broadworth Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Max Tseng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index 4996d2810edb..938dba5249d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -623,6 +623,10 @@ void hubp2_cursor_set_attributes( hubp->att.size.bits.width = attr->width; hubp->att.size.bits.height = attr->height; hubp->att.cur_ctl.bits.mode = attr->color_format; + + hubp->cur_rect.w = attr->width; + hubp->cur_rect.h = attr->height; + hubp->att.cur_ctl.bits.pitch = hw_pitch; hubp->att.cur_ctl.bits.line_per_chunk = lpc; hubp->att.cur_ctl.bits.cur_2x_magnify = attr->attribute_flags.bits.ENABLE_MAGNIFICATION; -- cgit v1.2.3 From 89b3554782e6b65894f0551e9e0a82ad02dac94d Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Mon, 24 Oct 2022 12:47:47 +0800 Subject: drm/amdgpu: set fb_modifiers_not_supported in vkms This patch to fix the gdm3 start failure with virual display: /usr/libexec/gdm-x-session[1711]: (II) AMDGPU(0): Setting screen physical size to 270 x 203 /usr/libexec/gdm-x-session[1711]: (EE) AMDGPU(0): Failed to make import prime FD as pixmap: 22 /usr/libexec/gdm-x-session[1711]: (EE) AMDGPU(0): failed to set mode: Invalid argument /usr/libexec/gdm-x-session[1711]: (WW) AMDGPU(0): Failed to set mode on CRTC 0 /usr/libexec/gdm-x-session[1711]: (EE) AMDGPU(0): Failed to enable any CRTC gnome-shell[1840]: Running GNOME Shell (using mutter 42.2) as a X11 window and compositing manager /usr/libexec/gdm-x-session[1711]: (EE) AMDGPU(0): failed to set mode: Invalid argument vkms doesn't have modifiers support, set fb_modifiers_not_supported to bring the gdm back. Signed-off-by: Yifan Zhang Acked-by: Guchun Chen Reviewed-by: Tim Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index f4b5301ea2a0..500a1dc4fe02 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -500,6 +500,8 @@ static int amdgpu_vkms_sw_init(void *handle) adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true; + r = amdgpu_display_modeset_create_props(adev); if (r) return r; -- cgit v1.2.3 From e542ca6e3e554bad53b2ea5741873b67f4585ea9 Mon Sep 17 00:00:00 2001 From: Graham Sider Date: Tue, 25 Oct 2022 14:42:13 -0400 Subject: drm/amdgpu: correct MES debugfs versions Use mes.sched_version, mes.kiq_version for debugfs as mes.ucode_fw_version does not contain correct versioning information. Signed-off-by: Graham Sider Reviewed-by: Jack Xiao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index bf1ff8f0e712..4e42dcb1950f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -337,12 +337,14 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, fw_info->feature = adev->psp.cap_feature_version; break; case AMDGPU_INFO_FW_MES_KIQ: - fw_info->ver = adev->mes.ucode_fw_version[0]; - fw_info->feature = 0; + fw_info->ver = adev->mes.kiq_version & AMDGPU_MES_VERSION_MASK; + fw_info->feature = (adev->mes.kiq_version & AMDGPU_MES_FEAT_VERSION_MASK) + >> AMDGPU_MES_FEAT_VERSION_SHIFT; break; case AMDGPU_INFO_FW_MES: - fw_info->ver = adev->mes.ucode_fw_version[1]; - fw_info->feature = 0; + fw_info->ver = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK; + fw_info->feature = (adev->mes.sched_version & AMDGPU_MES_FEAT_VERSION_MASK) + >> AMDGPU_MES_FEAT_VERSION_SHIFT; break; case AMDGPU_INFO_FW_IMU: fw_info->ver = adev->gfx.imu_fw_version; -- cgit v1.2.3 From 5b994354af3cab770bf13386469c5725713679af Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 26 Oct 2022 10:00:54 +0800 Subject: drm/amdkfd: Fix NULL pointer dereference in svm_migrate_to_ram() ./drivers/gpu/drm/amd/amdkfd/kfd_migrate.c:985:58-62: ERROR: p is NULL but dereferenced. Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=2549 Reported-by: Abaci Robot Signed-off-by: Yang Li Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 2797029bd500..22b077ac9a19 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -973,12 +973,10 @@ out_unlock_prange: out_unlock_svms: mutex_unlock(&p->svms.lock); out_unref_process: + pr_debug("CPU fault svms 0x%p address 0x%lx done\n", &p->svms, addr); kfd_unref_process(p); out_mmput: mmput(mm); - - pr_debug("CPU fault svms 0x%p address 0x%lx done\n", &p->svms, addr); - return r ? VM_FAULT_SIGBUS : 0; } -- cgit v1.2.3 From 8d4de331f1b24a22d18e3c6116aa25228cf54854 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 26 Oct 2022 14:03:55 -0500 Subject: drm/amd: Fail the suspend if resources can't be evicted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a system does not have swap and memory is under 100% usage, amdgpu will fail to evict resources. Currently the suspend carries on proceeding to reset the GPU: ``` [drm] evicting device resources failed [drm:amdgpu_device_ip_suspend_phase2 [amdgpu]] *ERROR* suspend of IP block failed -12 [drm] free PSP TMR buffer [TTM] Failed allocating page table [drm] evicting device resources failed amdgpu 0000:03:00.0: amdgpu: MODE1 reset amdgpu 0000:03:00.0: amdgpu: GPU mode1 reset amdgpu 0000:03:00.0: amdgpu: GPU smu mode1 reset ``` At this point if the suspend actually succeeded I think that amdgpu would have recovered because the GPU would have power cut off and restored. However the kernel fails to continue the suspend from the memory pressure and amdgpu fails to run the "resume" from the aborted suspend. ``` ACPI: PM: Preparing to enter system sleep state S3 SLUB: Unable to allocate memory on node -1, gfp=0xdc0(GFP_KERNEL|__GFP_ZERO) cache: Acpi-State, object size: 80, buffer size: 80, default order: 0, min order: 0 node 0: slabs: 22, objs: 1122, free: 0 ACPI Error: AE_NO_MEMORY, Could not update object reference count (20210730/utdelete-651) [drm:psp_hw_start [amdgpu]] *ERROR* PSP load kdb failed! [drm:psp_resume [amdgpu]] *ERROR* PSP resume failed [drm:amdgpu_device_fw_loading [amdgpu]] *ERROR* resume of IP block failed -62 amdgpu 0000:03:00.0: amdgpu: amdgpu_device_ip_resume failed (-62). PM: dpm_run_callback(): pci_pm_resume+0x0/0x100 returns -62 amdgpu 0000:03:00.0: PM: failed to resume async: error -62 ``` To avoid this series of unfortunate events, fail amdgpu's suspend when the memory eviction fails. This will let the system gracefully recover and the user can try suspend again when the memory pressure is relieved. Reported-by: post@davidak.de Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2223 Signed-off-by: Mario Limonciello Reviewed-by: Alex Deucher Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ddaecb2610c9..64510898eedd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4060,15 +4060,18 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev) * at suspend time. * */ -static void amdgpu_device_evict_resources(struct amdgpu_device *adev) +static int amdgpu_device_evict_resources(struct amdgpu_device *adev) { + int ret; + /* No need to evict vram on APUs for suspend to ram or s2idle */ if ((adev->in_s3 || adev->in_s0ix) && (adev->flags & AMD_IS_APU)) - return; + return 0; - if (amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM)) + ret = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM); + if (ret) DRM_WARN("evicting device resources failed\n"); - + return ret; } /* @@ -4118,7 +4121,9 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) if (!adev->in_s0ix) amdgpu_amdkfd_suspend(adev, adev->in_runpm); - amdgpu_device_evict_resources(adev); + r = amdgpu_device_evict_resources(adev); + if (r) + return r; amdgpu_fence_driver_hw_fini(adev); -- cgit v1.2.3 From 160fbcf3bfb93c3c086427f9f4c8bc70f217e9be Mon Sep 17 00:00:00 2001 From: Soenke Huster Date: Wed, 12 Oct 2022 09:45:06 +0200 Subject: Bluetooth: virtio_bt: Use skb_put to set length By using skb_put we ensure that skb->tail is set correctly. Currently, skb->tail is always zero, which leads to errors, such as the following page fault in rfcomm_recv_frame: BUG: unable to handle page fault for address: ffffed1021de29ff #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page RIP: 0010:rfcomm_run+0x831/0x4040 (net/bluetooth/rfcomm/core.c:1751) Fixes: afd2daa26c7a ("Bluetooth: Add support for virtio transport driver") Signed-off-by: Soenke Huster Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/virtio_bt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c index 67c21263f9e0..fd281d439505 100644 --- a/drivers/bluetooth/virtio_bt.c +++ b/drivers/bluetooth/virtio_bt.c @@ -219,7 +219,7 @@ static void virtbt_rx_work(struct work_struct *work) if (!skb) return; - skb->len = len; + skb_put(skb, len); virtbt_rx_handle(vbt, skb); if (virtbt_add_inbuf(vbt) < 0) -- cgit v1.2.3 From b43088f30db1a7bff61c8486238c195c77788d6d Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Tue, 25 Oct 2022 10:05:25 +0200 Subject: s390/zcrypt: fix warning about field-spanning write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the warning memcpy: detected field-spanning write (size 60) of single field "to" at drivers/s390/crypto/zcrypt_api.h:173 (size 2) WARNING: CPU: 1 PID: 2114 at drivers/s390/crypto/zcrypt_api.h:173 prep_ep11_ap_msg+0x2c6/0x2e0 [zcrypt] The code has been rewritten to use a union in combination with a flex array to clearly state which part of the buffer the payload is to be copied in via z_copy_from_user function (which may call memcpy() in case of in-kernel calls). Signed-off-by: Harald Freudenberger Suggested-by: Jürgen Christ Reviewed-by: Jürgen Christ Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/zcrypt_msgtype6.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index 8fb34b8eeb18..5ad251477593 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -342,7 +342,10 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg, }; struct { struct type6_hdr hdr; - struct CPRBX cprbx; + union { + struct CPRBX cprbx; + DECLARE_FLEX_ARRAY(u8, userdata); + }; } __packed * msg = ap_msg->msg; int rcblen = CEIL4(xcrb->request_control_blk_length); @@ -403,7 +406,8 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg, msg->hdr.fromcardlen2 = xcrb->reply_data_length; /* prepare CPRB */ - if (z_copy_from_user(userspace, &msg->cprbx, xcrb->request_control_blk_addr, + if (z_copy_from_user(userspace, msg->userdata, + xcrb->request_control_blk_addr, xcrb->request_control_blk_length)) return -EFAULT; if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) > @@ -469,9 +473,14 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(bool userspace, struct ap_message *ap struct { struct type6_hdr hdr; - struct ep11_cprb cprbx; - unsigned char pld_tag; /* fixed value 0x30 */ - unsigned char pld_lenfmt; /* payload length format */ + union { + struct { + struct ep11_cprb cprbx; + unsigned char pld_tag; /* fixed value 0x30 */ + unsigned char pld_lenfmt; /* length format */ + } __packed; + DECLARE_FLEX_ARRAY(u8, userdata); + }; } __packed * msg = ap_msg->msg; struct pld_hdr { @@ -500,7 +509,7 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(bool userspace, struct ap_message *ap msg->hdr.fromcardlen1 = xcrb->resp_len; /* Import CPRB data from the ioctl input parameter */ - if (z_copy_from_user(userspace, &msg->cprbx.cprb_len, + if (z_copy_from_user(userspace, msg->userdata, (char __force __user *)xcrb->req, xcrb->req_len)) { return -EFAULT; } -- cgit v1.2.3 From a3e5ce56f3d260f2ec8e5242c33f57e60ae9eba7 Mon Sep 17 00:00:00 2001 From: Graham Sider Date: Wed, 26 Oct 2022 15:08:24 -0400 Subject: drm/amdgpu: disable GFXOFF during compute for GFX11 Temporary workaround to fix issues observed in some compute applications when GFXOFF is enabled on GFX11. Signed-off-by: Graham Sider Acked-by: Alex Deucher Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 0561812aa0a4..5d9a34601a1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -706,6 +706,13 @@ err: void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle) { + /* Temporary workaround to fix issues observed in some + * compute applications when GFXOFF is enabled on GFX11. + */ + if (IP_VERSION_MAJ(adev->ip_versions[GC_HWIP][0]) == 11) { + pr_debug("GFXOFF is %s\n", idle ? "enabled" : "disabled"); + amdgpu_gfx_off_ctrl(adev, idle); + } amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_COMPUTE, !idle); -- cgit v1.2.3 From 8fe8ce896c1cc29d6bfebb3c7b3cc948f72cd32c Mon Sep 17 00:00:00 2001 From: Gavin Wan Date: Wed, 26 Oct 2022 13:45:25 -0400 Subject: drm/amdgpu: Disable GPU reset on SRIOV before remove pci. The recent change brought a bug on SRIOV envrionment. It caused unloading amdgpu failed on Guest VM. The reason is that the VF FLR was requested while unloading amdgpu driver, but the VF FLR of SRIOV sequence is wrong while removing PCI device. For SRIOV, the guest driver should not trigger the whole XGMI hive to do the reset. Host driver control how the device been reset. Fixes: f5c7e7797060 ("drm/amdgpu: Adjust removal control flow for smu v13_0_2") Acked-by: Alex Deucher Reviewed-by: Shaoyun Liu Signed-off-by: Gavin Wan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 3c9fecdd6b2f..bf2d50c8c92a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2201,7 +2201,8 @@ amdgpu_pci_remove(struct pci_dev *pdev) pm_runtime_forbid(dev->dev); } - if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)) { + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) && + !amdgpu_sriov_vf(adev)) { bool need_to_reset_gpu = false; if (adev->gmc.xgmi.num_physical_nodes > 1) { -- cgit v1.2.3 From bad610c97c08eef3ed1fa769a8b08b94f95b451e Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 7 Oct 2022 12:43:26 -0400 Subject: drm/amd/display: Fix DCN32 DSC delay calculation [Why] DCN32 DSC delay calculation had an unintentional integer division, resulting in a mismatch against the DML spreadsheet. [How] Cast numerator to double before performing the division. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index ad66e241f9ae..4a3e7a5d2758 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -1746,7 +1746,7 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled, } DSCDelayRequirement_val = DSCDelayRequirement_val + (HTotal - HActive) * - dml_ceil(DSCDelayRequirement_val / HActive, 1); + dml_ceil((double)DSCDelayRequirement_val / HActive, 1); DSCDelayRequirement_val = DSCDelayRequirement_val * PixelClock / PixelClockBackEnd; -- cgit v1.2.3 From ab007e5db5d3b8b8975c7eec69992ff38fe2a46c Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Oct 2022 17:36:32 -0400 Subject: drm/amd/display: Use forced DSC bpp in DML [Why] DSC config is calculated separately from DML calculations. DML should use these separately calculated DSC params. The issue is that the calculated bpp is not properly propagated into DML. [How] Correctly used forced_bpp value in DML. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 5b91660a6496..60351b2891d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -1627,7 +1627,7 @@ static void mode_support_configuration(struct vba_vars_st *v, && !mode_lib->vba.MSOOrODMSplitWithNonDPLink && !mode_lib->vba.NotEnoughLanesForMSO && mode_lib->vba.LinkCapacitySupport[i] == true && !mode_lib->vba.P2IWith420 - && !mode_lib->vba.DSCOnlyIfNecessaryWithBPP + //&& !mode_lib->vba.DSCOnlyIfNecessaryWithBPP && !mode_lib->vba.DSC422NativeNotSupported && !mode_lib->vba.MPCCombineMethodIncompatible && mode_lib->vba.ODMCombine2To1SupportCheckOK[i] == true diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 03924aed8d5c..8e6585dab20e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -625,7 +625,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.skip_dio_check[mode_lib->vba.NumberOfActivePlanes] = dout->is_virtual; - if (!dout->dsc_enable) + if (dout->dsc_enable) mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp; else mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = 0.0; -- cgit v1.2.3 From 8dc323133d74518e3b5b07242e2b2f088799ea6e Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Oct 2022 17:40:08 -0400 Subject: drm/amd/display: Round up DST_after_scaler to nearest int [Why] The DST_after_scaler value that DML spreadsheet outputs is generally the driver value round up to the nearest int. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c index a1276f6b9581..395ae8761980 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c @@ -291,8 +291,8 @@ void dml32_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, dml_print("DML_DLG: %s: vready_after_vcount0 = %d\n", __func__, dlg_regs->vready_after_vcount0); - dst_x_after_scaler = get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); - dst_y_after_scaler = get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dst_x_after_scaler = dml_ceil(get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx), 1); + dst_y_after_scaler = dml_ceil(get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx), 1); // do some adjustment on the dst_after scaler to account for odm combine mode dml_print("DML_DLG: %s: input dst_x_after_scaler = %d\n", __func__, dst_x_after_scaler); -- cgit v1.2.3 From d5e0fb0d9dea545defb963ec1073bd9a1a8b5395 Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 14 Oct 2022 17:46:03 -0400 Subject: drm/amd/display: Add DSC delay factor workaround [Why] Certain 4K high refresh rate modes requiring DSC are exhibiting top of screen underflow corruption. Increasing the DSC delay by a factor of 6 percent stops the underflow for most use cases. [How] Multiply DSC delay requirement in DML by a factor. Add debug option to make this DSC delay factor configurable. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 4 +++- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 5 +++-- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 5 +++-- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h | 3 ++- drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 3 +++ 7 files changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bfc5474c0f4c..737b221ca689 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -852,6 +852,7 @@ struct dc_debug_options { bool enable_double_buffered_dsc_pg_support; bool enable_dp_dig_pixel_rate_div_policy; enum lttpr_mode lttpr_mode_override; + unsigned int dsc_delay_factor_wa_x1000; }; struct gpu_info_soc_bounding_box_v1_0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 819de0f11012..f37c9a6b3b7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -2359,9 +2359,11 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; - } + /* DML DSC delay factor workaround */ + dcn3_2_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0; + /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */ dcn3_2_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 60351b2891d0..47ff0a8bd105 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -367,7 +367,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.OutputBpp[k], mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k], mode_lib->vba.NumberOfDSCSlices[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.Output[k], mode_lib->vba.PixelClock[k], - mode_lib->vba.PixelClockBackEnd[k]); + mode_lib->vba.PixelClockBackEnd[k], mode_lib->vba.ip.dsc_delay_factor_wa); } for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) @@ -2475,7 +2475,8 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.OutputBppPerState[i][k], mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k], mode_lib->vba.NumberOfDSCSlices[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.Output[k], - mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k]); + mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k], + mode_lib->vba.ip.dsc_delay_factor_wa); } for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 4a3e7a5d2758..968924c491c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -1726,7 +1726,8 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled, enum output_format_class OutputFormat, enum output_encoder_class Output, double PixelClock, - double PixelClockBackEnd) + double PixelClockBackEnd, + double dsc_delay_factor_wa) { unsigned int DSCDelayRequirement_val; @@ -1764,7 +1765,7 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled, dml_print("DML::%s: DSCDelayRequirement_val = %d\n", __func__, DSCDelayRequirement_val); #endif - return DSCDelayRequirement_val; + return dml_ceil(DSCDelayRequirement_val * dsc_delay_factor_wa, 1); } void dml32_CalculateSurfaceSizeInMall( diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index 55cead0d4237..2c3827546ac7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -327,7 +327,8 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled, enum output_format_class OutputFormat, enum output_encoder_class Output, double PixelClock, - double PixelClockBackEnd); + double PixelClockBackEnd, + double dsc_delay_factor_wa); void dml32_CalculateSurfaceSizeInMall( unsigned int NumberOfActiveSurfaces, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index 7352f7514410..ec0486efab14 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -29,6 +29,7 @@ #include "dcn321_fpu.h" #include "dcn32/dcn32_resource.h" #include "dcn321/dcn321_resource.h" +#include "dml/dcn32/display_mode_vba_util_32.h" #define DCN3_2_DEFAULT_DET_SIZE 256 @@ -538,9 +539,11 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) dcn3_21_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; - } + /* DML DSC delay factor workaround */ + dcn3_21_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0; + /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */ dcn3_21_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index f33a8879b05a..d7be01ac0751 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -364,6 +364,9 @@ struct _vcs_dpi_ip_params_st { unsigned int max_num_dp2p0_outputs; unsigned int max_num_dp2p0_streams; unsigned int VBlankNomDefaultUS; + + /* DM workarounds */ + double dsc_delay_factor_wa; // TODO: Remove after implementing root cause fix }; struct _vcs_dpi_display_xfc_params_st { -- cgit v1.2.3 From 7461016c5706eb8c477752bf69e5c9f5a38f502b Mon Sep 17 00:00:00 2001 From: Nevenko Stupar Date: Fri, 6 May 2022 16:32:38 -0400 Subject: drm/amd/display: Investigate tool reported FCLK P-state deviations [Why] Fix for some of the tool reported modes for FCLK P-state deviations and UCLK P-state deviations that are coming from DSC terms and/or Scaling terms causing MinActiveFCLKChangeLatencySupported and MaxActiveDRAMClockChangeLatencySupported incorrectly calculated in DML for these configurations. Reviewed-by: Chaitanya Dhere Acked-by: Jasdeep Dhillon Acked-by: Alex Hung Signed-off-by: Nevenko Stupar Tested-by: Mark Broadworth Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 47ff0a8bd105..3d184679f129 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -364,7 +364,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) { v->DSCDelay[k] = dml32_DSCDelayRequirement(mode_lib->vba.DSCEnabled[k], mode_lib->vba.ODMCombineEnabled[k], mode_lib->vba.DSCInputBitPerComponent[k], - mode_lib->vba.OutputBpp[k], mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k], + mode_lib->vba.OutputBppPerState[mode_lib->vba.VoltageLevel][k], + mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k], mode_lib->vba.NumberOfDSCSlices[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.Output[k], mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k], mode_lib->vba.ip.dsc_delay_factor_wa); -- cgit v1.2.3 From 6640f8e5adb69a0550fe1d224d3ac64c10f00eef Mon Sep 17 00:00:00 2001 From: Jay Cornwall Date: Thu, 13 Oct 2022 21:41:13 -0500 Subject: drm/amdkfd: update GFX11 CWSR trap handler With corresponding FW change fixes issue where triggering CWSR on a workgroup with waves in s_barrier wouldn't lead to a back-off and therefore cause a hang. Signed-off-by: Jay Cornwall Tested-by: Graham Sider Acked-by: Harish Kasiviswanathan Acked-by: Felix Kuehling Reviewed-by: Graham Sider Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 764 +++++++++++---------- .../gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm | 6 + 2 files changed, 389 insertions(+), 381 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index c7118843db05..0c4c5499bb5c 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -2495,442 +2495,444 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xbf9f0000, 0x00000000, }; static const uint32_t cwsr_trap_gfx11_hex[] = { - 0xbfa00001, 0xbfa0021e, + 0xbfa00001, 0xbfa00221, 0xb0804006, 0xb8f8f802, 0x9178ff78, 0x00020006, - 0xb8fbf803, 0xbf0d9f6d, - 0xbfa20006, 0x8b6eff78, - 0x00002000, 0xbfa10009, - 0x8b6eff6d, 0x00ff0000, - 0xbfa2001e, 0x8b6eff7b, - 0x00000400, 0xbfa20041, - 0xbf830010, 0xb8fbf803, - 0xbfa0fffa, 0x8b6eff7b, - 0x00000900, 0xbfa20015, - 0x8b6eff7b, 0x000071ff, - 0xbfa10008, 0x8b6fff7b, - 0x00007080, 0xbfa10001, - 0xbeee1287, 0xb8eff801, - 0x846e8c6e, 0x8b6e6f6e, - 0xbfa2000a, 0x8b6eff6d, - 0x00ff0000, 0xbfa20007, - 0xb8eef801, 0x8b6eff6e, - 0x00000800, 0xbfa20003, + 0xb8fbf803, 0xbf0d9e6d, + 0xbfa10001, 0xbfbd0000, + 0xbf0d9f6d, 0xbfa20006, + 0x8b6eff78, 0x00002000, + 0xbfa10009, 0x8b6eff6d, + 0x00ff0000, 0xbfa2001e, 0x8b6eff7b, 0x00000400, - 0xbfa20026, 0xbefa4d82, - 0xbf89fc07, 0x84fa887a, - 0xf4005bbd, 0xf8000010, - 0xbf89fc07, 0x846e976e, - 0x9177ff77, 0x00800000, - 0x8c776e77, 0xf4045bbd, - 0xf8000000, 0xbf89fc07, - 0xf4045ebd, 0xf8000008, - 0xbf89fc07, 0x8bee6e6e, - 0xbfa10001, 0xbe80486e, - 0x8b6eff6d, 0x01ff0000, - 0xbfa20005, 0x8c78ff78, - 0x00002000, 0x80ec886c, - 0x82ed806d, 0xbfa00005, - 0x8b6eff6d, 0x01000000, - 0xbfa20002, 0x806c846c, - 0x826d806d, 0x8b6dff6d, - 0x0000ffff, 0x8bfe7e7e, - 0x8bea6a6a, 0xb978f802, - 0xbe804a6c, 0x8b6dff6d, - 0x0000ffff, 0xbefa0080, - 0xb97a0283, 0xbeee007e, - 0xbeef007f, 0xbefe0180, - 0xbefe4d84, 0xbf89fc07, - 0x8b7aff7f, 0x04000000, - 0x847a857a, 0x8c6d7a6d, - 0xbefa007e, 0x8b7bff7f, - 0x0000ffff, 0xbefe00c1, - 0xbeff00c1, 0xdca6c000, - 0x007a0000, 0x7e000280, - 0xbefe007a, 0xbeff007b, - 0xb8fb02dc, 0x847b997b, - 0xb8fa3b05, 0x807a817a, - 0xbf0d997b, 0xbfa20002, - 0x847a897a, 0xbfa00001, - 0x847a8a7a, 0xb8fb1e06, - 0x847b8a7b, 0x807a7b7a, + 0xbfa20041, 0xbf830010, + 0xb8fbf803, 0xbfa0fffa, + 0x8b6eff7b, 0x00000900, + 0xbfa20015, 0x8b6eff7b, + 0x000071ff, 0xbfa10008, + 0x8b6fff7b, 0x00007080, + 0xbfa10001, 0xbeee1287, + 0xb8eff801, 0x846e8c6e, + 0x8b6e6f6e, 0xbfa2000a, + 0x8b6eff6d, 0x00ff0000, + 0xbfa20007, 0xb8eef801, + 0x8b6eff6e, 0x00000800, + 0xbfa20003, 0x8b6eff7b, + 0x00000400, 0xbfa20026, + 0xbefa4d82, 0xbf89fc07, + 0x84fa887a, 0xf4005bbd, + 0xf8000010, 0xbf89fc07, + 0x846e976e, 0x9177ff77, + 0x00800000, 0x8c776e77, + 0xf4045bbd, 0xf8000000, + 0xbf89fc07, 0xf4045ebd, + 0xf8000008, 0xbf89fc07, + 0x8bee6e6e, 0xbfa10001, + 0xbe80486e, 0x8b6eff6d, + 0x01ff0000, 0xbfa20005, + 0x8c78ff78, 0x00002000, + 0x80ec886c, 0x82ed806d, + 0xbfa00005, 0x8b6eff6d, + 0x01000000, 0xbfa20002, + 0x806c846c, 0x826d806d, + 0x8b6dff6d, 0x0000ffff, + 0x8bfe7e7e, 0x8bea6a6a, + 0xb978f802, 0xbe804a6c, + 0x8b6dff6d, 0x0000ffff, + 0xbefa0080, 0xb97a0283, + 0xbeee007e, 0xbeef007f, + 0xbefe0180, 0xbefe4d84, + 0xbf89fc07, 0x8b7aff7f, + 0x04000000, 0x847a857a, + 0x8c6d7a6d, 0xbefa007e, 0x8b7bff7f, 0x0000ffff, - 0x807aff7a, 0x00000200, - 0x807a7e7a, 0x827b807b, - 0xd7610000, 0x00010870, - 0xd7610000, 0x00010a71, - 0xd7610000, 0x00010c72, - 0xd7610000, 0x00010e73, - 0xd7610000, 0x00011074, - 0xd7610000, 0x00011275, - 0xd7610000, 0x00011476, - 0xd7610000, 0x00011677, - 0xd7610000, 0x00011a79, - 0xd7610000, 0x00011c7e, - 0xd7610000, 0x00011e7f, - 0xbefe00ff, 0x00003fff, - 0xbeff0080, 0xdca6c040, - 0x007a0000, 0xd760007a, - 0x00011d00, 0xd760007b, - 0x00011f00, 0xbefe007a, - 0xbeff007b, 0xbef4007e, - 0x8b75ff7f, 0x0000ffff, - 0x8c75ff75, 0x00040000, - 0xbef60080, 0xbef700ff, - 0x10807fac, 0xbef1007d, - 0xbef00080, 0xb8f302dc, - 0x84739973, 0xbefe00c1, - 0x857d9973, 0x8b7d817d, - 0xbf06817d, 0xbfa20002, - 0xbeff0080, 0xbfa00002, - 0xbeff00c1, 0xbfa00009, + 0xbefe00c1, 0xbeff00c1, + 0xdca6c000, 0x007a0000, + 0x7e000280, 0xbefe007a, + 0xbeff007b, 0xb8fb02dc, + 0x847b997b, 0xb8fa3b05, + 0x807a817a, 0xbf0d997b, + 0xbfa20002, 0x847a897a, + 0xbfa00001, 0x847a8a7a, + 0xb8fb1e06, 0x847b8a7b, + 0x807a7b7a, 0x8b7bff7f, + 0x0000ffff, 0x807aff7a, + 0x00000200, 0x807a7e7a, + 0x827b807b, 0xd7610000, + 0x00010870, 0xd7610000, + 0x00010a71, 0xd7610000, + 0x00010c72, 0xd7610000, + 0x00010e73, 0xd7610000, + 0x00011074, 0xd7610000, + 0x00011275, 0xd7610000, + 0x00011476, 0xd7610000, + 0x00011677, 0xd7610000, + 0x00011a79, 0xd7610000, + 0x00011c7e, 0xd7610000, + 0x00011e7f, 0xbefe00ff, + 0x00003fff, 0xbeff0080, + 0xdca6c040, 0x007a0000, + 0xd760007a, 0x00011d00, + 0xd760007b, 0x00011f00, + 0xbefe007a, 0xbeff007b, + 0xbef4007e, 0x8b75ff7f, + 0x0000ffff, 0x8c75ff75, + 0x00040000, 0xbef60080, + 0xbef700ff, 0x10807fac, + 0xbef1007d, 0xbef00080, + 0xb8f302dc, 0x84739973, + 0xbefe00c1, 0x857d9973, + 0x8b7d817d, 0xbf06817d, + 0xbfa20002, 0xbeff0080, + 0xbfa00002, 0xbeff00c1, + 0xbfa00009, 0xbef600ff, + 0x01000000, 0xe0685080, + 0x701d0100, 0xe0685100, + 0x701d0200, 0xe0685180, + 0x701d0300, 0xbfa00008, 0xbef600ff, 0x01000000, - 0xe0685080, 0x701d0100, - 0xe0685100, 0x701d0200, - 0xe0685180, 0x701d0300, - 0xbfa00008, 0xbef600ff, - 0x01000000, 0xe0685100, - 0x701d0100, 0xe0685200, - 0x701d0200, 0xe0685300, - 0x701d0300, 0xb8f03b05, - 0x80708170, 0xbf0d9973, - 0xbfa20002, 0x84708970, - 0xbfa00001, 0x84708a70, - 0xb8fa1e06, 0x847a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0xbef600ff, - 0x01000000, 0x7e000280, - 0x7e020280, 0x7e040280, - 0xbefd0080, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xd7610002, 0x0000fa6c, - 0x807d817d, 0x917aff6d, - 0x80000000, 0xd7610002, - 0x0000fa7a, 0x807d817d, - 0xd7610002, 0x0000fa6e, - 0x807d817d, 0xd7610002, - 0x0000fa6f, 0x807d817d, - 0xd7610002, 0x0000fa78, - 0x807d817d, 0xb8faf803, - 0xd7610002, 0x0000fa7a, - 0x807d817d, 0xd7610002, - 0x0000fa7b, 0x807d817d, - 0xb8f1f801, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xb8f1f814, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xb8f1f815, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xbefe00ff, 0x0000ffff, - 0xbeff0080, 0xe0685000, - 0x701d0200, 0xbefe00c1, + 0xe0685100, 0x701d0100, + 0xe0685200, 0x701d0200, + 0xe0685300, 0x701d0300, 0xb8f03b05, 0x80708170, 0xbf0d9973, 0xbfa20002, 0x84708970, 0xbfa00001, 0x84708a70, 0xb8fa1e06, 0x847a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, 0xbef600ff, 0x01000000, - 0xbef90080, 0xbefd0080, - 0xbf800000, 0xbe804100, - 0xbe824102, 0xbe844104, - 0xbe864106, 0xbe884108, - 0xbe8a410a, 0xbe8c410c, - 0xbe8e410e, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0x7e000280, 0x7e020280, + 0x7e040280, 0xbefd0080, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xd7610002, + 0x0000fa6c, 0x807d817d, + 0x917aff6d, 0x80000000, + 0xd7610002, 0x0000fa7a, + 0x807d817d, 0xd7610002, + 0x0000fa6e, 0x807d817d, + 0xd7610002, 0x0000fa6f, + 0x807d817d, 0xd7610002, + 0x0000fa78, 0x807d817d, + 0xb8faf803, 0xd7610002, + 0x0000fa7a, 0x807d817d, + 0xd7610002, 0x0000fa7b, + 0x807d817d, 0xb8f1f801, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xb8f1f814, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xb8f1f815, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xbefe00ff, + 0x0000ffff, 0xbeff0080, + 0xe0685000, 0x701d0200, + 0xbefe00c1, 0xb8f03b05, + 0x80708170, 0xbf0d9973, + 0xbfa20002, 0x84708970, + 0xbfa00001, 0x84708a70, + 0xb8fa1e06, 0x847a8a7a, + 0x80707a70, 0xbef600ff, + 0x01000000, 0xbef90080, + 0xbefd0080, 0xbf800000, + 0xbe804100, 0xbe824102, + 0xbe844104, 0xbe864106, + 0xbe884108, 0xbe8a410a, + 0xbe8c410c, 0xbe8e410e, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, 0x80798179, 0xd7610002, - 0x0000f20c, 0x80798179, - 0xd7610002, 0x0000f20d, + 0x0000f20b, 0x80798179, + 0xd7610002, 0x0000f20c, 0x80798179, 0xd7610002, - 0x0000f20e, 0x80798179, - 0xd7610002, 0x0000f20f, - 0x80798179, 0xbf06a079, - 0xbfa10006, 0xe0685000, - 0x701d0200, 0x8070ff70, - 0x00000080, 0xbef90080, - 0x7e040280, 0x807d907d, - 0xbf0aff7d, 0x00000060, - 0xbfa2ffbc, 0xbe804100, - 0xbe824102, 0xbe844104, - 0xbe864106, 0xbe884108, - 0xbe8a410a, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0x0000f20d, 0x80798179, + 0xd7610002, 0x0000f20e, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f20f, 0x80798179, + 0xbf06a079, 0xbfa10006, + 0xe0685000, 0x701d0200, + 0x8070ff70, 0x00000080, + 0xbef90080, 0x7e040280, + 0x807d907d, 0xbf0aff7d, + 0x00000060, 0xbfa2ffbc, + 0xbe804100, 0xbe824102, + 0xbe844104, 0xbe864106, + 0xbe884108, 0xbe8a410a, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, - 0x80798179, 0xe0685000, - 0x701d0200, 0xbefe00c1, - 0x857d9973, 0x8b7d817d, - 0xbf06817d, 0xbfa20002, - 0xbeff0080, 0xbfa00001, - 0xbeff00c1, 0xb8fb4306, - 0x8b7bc17b, 0xbfa10044, - 0xbfbd0000, 0x8b7aff6d, - 0x80000000, 0xbfa10040, - 0x847b867b, 0x847b827b, - 0xbef6007b, 0xb8f03b05, - 0x80708170, 0xbf0d9973, - 0xbfa20002, 0x84708970, - 0xbfa00001, 0x84708a70, - 0xb8fa1e06, 0x847a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0x8070ff70, - 0x00000080, 0xbef600ff, - 0x01000000, 0xd71f0000, - 0x000100c1, 0xd7200000, - 0x000200c1, 0x16000084, - 0x857d9973, 0x8b7d817d, - 0xbf06817d, 0xbefd0080, - 0xbfa20012, 0xbe8300ff, - 0x00000080, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf890000, 0xe0685000, - 0x701d0100, 0x807d037d, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000080, - 0xbf0a7b7d, 0xbfa2fff4, - 0xbfa00011, 0xbe8300ff, - 0x00000100, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf890000, 0xe0685000, - 0x701d0100, 0x807d037d, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000100, - 0xbf0a7b7d, 0xbfa2fff4, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, + 0x80798179, 0xd7610002, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, + 0x80798179, 0xd7610002, + 0x0000f20b, 0x80798179, + 0xe0685000, 0x701d0200, 0xbefe00c1, 0x857d9973, 0x8b7d817d, 0xbf06817d, - 0xbfa20004, 0xbef000ff, - 0x00000200, 0xbeff0080, - 0xbfa00003, 0xbef000ff, - 0x00000400, 0xbeff00c1, - 0xb8fb3b05, 0x807b817b, - 0x847b827b, 0x857d9973, + 0xbfa20002, 0xbeff0080, + 0xbfa00001, 0xbeff00c1, + 0xb8fb4306, 0x8b7bc17b, + 0xbfa10044, 0xbfbd0000, + 0x8b7aff6d, 0x80000000, + 0xbfa10040, 0x847b867b, + 0x847b827b, 0xbef6007b, + 0xb8f03b05, 0x80708170, + 0xbf0d9973, 0xbfa20002, + 0x84708970, 0xbfa00001, + 0x84708a70, 0xb8fa1e06, + 0x847a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000080, + 0xbef600ff, 0x01000000, + 0xd71f0000, 0x000100c1, + 0xd7200000, 0x000200c1, + 0x16000084, 0x857d9973, 0x8b7d817d, 0xbf06817d, - 0xbfa20017, 0xbef600ff, - 0x01000000, 0xbefd0084, - 0xbf0a7b7d, 0xbfa10037, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, - 0xe0685000, 0x701d0000, - 0xe0685080, 0x701d0100, - 0xe0685100, 0x701d0200, - 0xe0685180, 0x701d0300, - 0x807d847d, 0x8070ff70, - 0x00000200, 0xbf0a7b7d, - 0xbfa2ffef, 0xbfa00025, + 0xbefd0080, 0xbfa20012, + 0xbe8300ff, 0x00000080, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf890000, + 0xe0685000, 0x701d0100, + 0x807d037d, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000080, 0xbf0a7b7d, + 0xbfa2fff4, 0xbfa00011, + 0xbe8300ff, 0x00000100, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf890000, + 0xe0685000, 0x701d0100, + 0x807d037d, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000100, 0xbf0a7b7d, + 0xbfa2fff4, 0xbefe00c1, + 0x857d9973, 0x8b7d817d, + 0xbf06817d, 0xbfa20004, + 0xbef000ff, 0x00000200, + 0xbeff0080, 0xbfa00003, + 0xbef000ff, 0x00000400, + 0xbeff00c1, 0xb8fb3b05, + 0x807b817b, 0x847b827b, + 0x857d9973, 0x8b7d817d, + 0xbf06817d, 0xbfa20017, 0xbef600ff, 0x01000000, 0xbefd0084, 0xbf0a7b7d, - 0xbfa10011, 0x7e008700, + 0xbfa10037, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0685000, - 0x701d0000, 0xe0685100, - 0x701d0100, 0xe0685200, - 0x701d0200, 0xe0685300, + 0x701d0000, 0xe0685080, + 0x701d0100, 0xe0685100, + 0x701d0200, 0xe0685180, 0x701d0300, 0x807d847d, - 0x8070ff70, 0x00000400, + 0x8070ff70, 0x00000200, 0xbf0a7b7d, 0xbfa2ffef, - 0xb8fb1e06, 0x8b7bc17b, - 0xbfa1000c, 0x847b837b, - 0x807b7d7b, 0xbefe00c1, - 0xbeff0080, 0x7e008700, + 0xbfa00025, 0xbef600ff, + 0x01000000, 0xbefd0084, + 0xbf0a7b7d, 0xbfa10011, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, 0xe0685000, 0x701d0000, - 0x807d817d, 0x8070ff70, - 0x00000080, 0xbf0a7b7d, - 0xbfa2fff8, 0xbfa00146, - 0xbef4007e, 0x8b75ff7f, - 0x0000ffff, 0x8c75ff75, - 0x00040000, 0xbef60080, - 0xbef700ff, 0x10807fac, - 0xb8f202dc, 0x84729972, - 0x8b6eff7f, 0x04000000, - 0xbfa1003a, 0xbefe00c1, - 0x857d9972, 0x8b7d817d, - 0xbf06817d, 0xbfa20002, - 0xbeff0080, 0xbfa00001, - 0xbeff00c1, 0xb8ef4306, - 0x8b6fc16f, 0xbfa1002f, - 0x846f866f, 0x846f826f, - 0xbef6006f, 0xb8f83b05, - 0x80788178, 0xbf0d9972, - 0xbfa20002, 0x84788978, - 0xbfa00001, 0x84788a78, - 0xb8ee1e06, 0x846e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x8078ff78, - 0x00000080, 0xbef600ff, - 0x01000000, 0x857d9972, - 0x8b7d817d, 0xbf06817d, - 0xbefd0080, 0xbfa2000c, - 0xe0500000, 0x781d0000, - 0xbf8903f7, 0xdac00000, - 0x00000000, 0x807dff7d, - 0x00000080, 0x8078ff78, - 0x00000080, 0xbf0a6f7d, - 0xbfa2fff5, 0xbfa0000b, - 0xe0500000, 0x781d0000, - 0xbf8903f7, 0xdac00000, - 0x00000000, 0x807dff7d, - 0x00000100, 0x8078ff78, - 0x00000100, 0xbf0a6f7d, - 0xbfa2fff5, 0xbef80080, + 0xe0685100, 0x701d0100, + 0xe0685200, 0x701d0200, + 0xe0685300, 0x701d0300, + 0x807d847d, 0x8070ff70, + 0x00000400, 0xbf0a7b7d, + 0xbfa2ffef, 0xb8fb1e06, + 0x8b7bc17b, 0xbfa1000c, + 0x847b837b, 0x807b7d7b, + 0xbefe00c1, 0xbeff0080, + 0x7e008700, 0xe0685000, + 0x701d0000, 0x807d817d, + 0x8070ff70, 0x00000080, + 0xbf0a7b7d, 0xbfa2fff8, + 0xbfa00146, 0xbef4007e, + 0x8b75ff7f, 0x0000ffff, + 0x8c75ff75, 0x00040000, + 0xbef60080, 0xbef700ff, + 0x10807fac, 0xb8f202dc, + 0x84729972, 0x8b6eff7f, + 0x04000000, 0xbfa1003a, 0xbefe00c1, 0x857d9972, 0x8b7d817d, 0xbf06817d, 0xbfa20002, 0xbeff0080, 0xbfa00001, 0xbeff00c1, - 0xb8ef3b05, 0x806f816f, - 0x846f826f, 0x857d9972, - 0x8b7d817d, 0xbf06817d, - 0xbfa20024, 0xbef600ff, - 0x01000000, 0xbeee0078, + 0xb8ef4306, 0x8b6fc16f, + 0xbfa1002f, 0x846f866f, + 0x846f826f, 0xbef6006f, + 0xb8f83b05, 0x80788178, + 0xbf0d9972, 0xbfa20002, + 0x84788978, 0xbfa00001, + 0x84788a78, 0xb8ee1e06, + 0x846e8a6e, 0x80786e78, 0x8078ff78, 0x00000200, - 0xbefd0084, 0xbf0a6f7d, - 0xbfa10050, 0xe0505000, - 0x781d0000, 0xe0505080, - 0x781d0100, 0xe0505100, - 0x781d0200, 0xe0505180, - 0x781d0300, 0xbf8903f7, - 0x7e008500, 0x7e028501, - 0x7e048502, 0x7e068503, - 0x807d847d, 0x8078ff78, - 0x00000200, 0xbf0a6f7d, - 0xbfa2ffee, 0xe0505000, - 0x6e1d0000, 0xe0505080, - 0x6e1d0100, 0xe0505100, - 0x6e1d0200, 0xe0505180, - 0x6e1d0300, 0xbf8903f7, - 0xbfa00034, 0xbef600ff, - 0x01000000, 0xbeee0078, - 0x8078ff78, 0x00000400, - 0xbefd0084, 0xbf0a6f7d, - 0xbfa10012, 0xe0505000, - 0x781d0000, 0xe0505100, - 0x781d0100, 0xe0505200, - 0x781d0200, 0xe0505300, - 0x781d0300, 0xbf8903f7, - 0x7e008500, 0x7e028501, - 0x7e048502, 0x7e068503, - 0x807d847d, 0x8078ff78, - 0x00000400, 0xbf0a6f7d, - 0xbfa2ffee, 0xb8ef1e06, - 0x8b6fc16f, 0xbfa1000e, - 0x846f836f, 0x806f7d6f, - 0xbefe00c1, 0xbeff0080, + 0x8078ff78, 0x00000080, + 0xbef600ff, 0x01000000, + 0x857d9972, 0x8b7d817d, + 0xbf06817d, 0xbefd0080, + 0xbfa2000c, 0xe0500000, + 0x781d0000, 0xbf8903f7, + 0xdac00000, 0x00000000, + 0x807dff7d, 0x00000080, + 0x8078ff78, 0x00000080, + 0xbf0a6f7d, 0xbfa2fff5, + 0xbfa0000b, 0xe0500000, + 0x781d0000, 0xbf8903f7, + 0xdac00000, 0x00000000, + 0x807dff7d, 0x00000100, + 0x8078ff78, 0x00000100, + 0xbf0a6f7d, 0xbfa2fff5, + 0xbef80080, 0xbefe00c1, + 0x857d9972, 0x8b7d817d, + 0xbf06817d, 0xbfa20002, + 0xbeff0080, 0xbfa00001, + 0xbeff00c1, 0xb8ef3b05, + 0x806f816f, 0x846f826f, + 0x857d9972, 0x8b7d817d, + 0xbf06817d, 0xbfa20024, + 0xbef600ff, 0x01000000, + 0xbeee0078, 0x8078ff78, + 0x00000200, 0xbefd0084, + 0xbf0a6f7d, 0xbfa10050, 0xe0505000, 0x781d0000, + 0xe0505080, 0x781d0100, + 0xe0505100, 0x781d0200, + 0xe0505180, 0x781d0300, 0xbf8903f7, 0x7e008500, - 0x807d817d, 0x8078ff78, - 0x00000080, 0xbf0a6f7d, - 0xbfa2fff7, 0xbeff00c1, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807d847d, + 0x8078ff78, 0x00000200, + 0xbf0a6f7d, 0xbfa2ffee, 0xe0505000, 0x6e1d0000, - 0xe0505100, 0x6e1d0100, - 0xe0505200, 0x6e1d0200, - 0xe0505300, 0x6e1d0300, - 0xbf8903f7, 0xb8f83b05, - 0x80788178, 0xbf0d9972, - 0xbfa20002, 0x84788978, - 0xbfa00001, 0x84788a78, - 0xb8ee1e06, 0x846e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x80f8ff78, - 0x00000050, 0xbef600ff, - 0x01000000, 0xbefd00ff, - 0x0000006c, 0x80f89078, - 0xf428403a, 0xf0000000, - 0xbf89fc07, 0x80fd847d, - 0xbf800000, 0xbe804300, - 0xbe824302, 0x80f8a078, - 0xf42c403a, 0xf0000000, - 0xbf89fc07, 0x80fd887d, - 0xbf800000, 0xbe804300, - 0xbe824302, 0xbe844304, - 0xbe864306, 0x80f8c078, - 0xf430403a, 0xf0000000, - 0xbf89fc07, 0x80fd907d, - 0xbf800000, 0xbe804300, - 0xbe824302, 0xbe844304, - 0xbe864306, 0xbe884308, - 0xbe8a430a, 0xbe8c430c, - 0xbe8e430e, 0xbf06807d, - 0xbfa1fff0, 0xb980f801, - 0x00000000, 0xbfbd0000, + 0xe0505080, 0x6e1d0100, + 0xe0505100, 0x6e1d0200, + 0xe0505180, 0x6e1d0300, + 0xbf8903f7, 0xbfa00034, + 0xbef600ff, 0x01000000, + 0xbeee0078, 0x8078ff78, + 0x00000400, 0xbefd0084, + 0xbf0a6f7d, 0xbfa10012, + 0xe0505000, 0x781d0000, + 0xe0505100, 0x781d0100, + 0xe0505200, 0x781d0200, + 0xe0505300, 0x781d0300, + 0xbf8903f7, 0x7e008500, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807d847d, + 0x8078ff78, 0x00000400, + 0xbf0a6f7d, 0xbfa2ffee, + 0xb8ef1e06, 0x8b6fc16f, + 0xbfa1000e, 0x846f836f, + 0x806f7d6f, 0xbefe00c1, + 0xbeff0080, 0xe0505000, + 0x781d0000, 0xbf8903f7, + 0x7e008500, 0x807d817d, + 0x8078ff78, 0x00000080, + 0xbf0a6f7d, 0xbfa2fff7, + 0xbeff00c1, 0xe0505000, + 0x6e1d0000, 0xe0505100, + 0x6e1d0100, 0xe0505200, + 0x6e1d0200, 0xe0505300, + 0x6e1d0300, 0xbf8903f7, 0xb8f83b05, 0x80788178, 0xbf0d9972, 0xbfa20002, 0x84788978, 0xbfa00001, 0x84788a78, 0xb8ee1e06, 0x846e8a6e, 0x80786e78, 0x8078ff78, 0x00000200, + 0x80f8ff78, 0x00000050, 0xbef600ff, 0x01000000, - 0xf4205bfa, 0xf0000000, - 0x80788478, 0xf4205b3a, + 0xbefd00ff, 0x0000006c, + 0x80f89078, 0xf428403a, + 0xf0000000, 0xbf89fc07, + 0x80fd847d, 0xbf800000, + 0xbe804300, 0xbe824302, + 0x80f8a078, 0xf42c403a, + 0xf0000000, 0xbf89fc07, + 0x80fd887d, 0xbf800000, + 0xbe804300, 0xbe824302, + 0xbe844304, 0xbe864306, + 0x80f8c078, 0xf430403a, + 0xf0000000, 0xbf89fc07, + 0x80fd907d, 0xbf800000, + 0xbe804300, 0xbe824302, + 0xbe844304, 0xbe864306, + 0xbe884308, 0xbe8a430a, + 0xbe8c430c, 0xbe8e430e, + 0xbf06807d, 0xbfa1fff0, + 0xb980f801, 0x00000000, + 0xbfbd0000, 0xb8f83b05, + 0x80788178, 0xbf0d9972, + 0xbfa20002, 0x84788978, + 0xbfa00001, 0x84788a78, + 0xb8ee1e06, 0x846e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef600ff, + 0x01000000, 0xf4205bfa, 0xf0000000, 0x80788478, - 0xf4205b7a, 0xf0000000, - 0x80788478, 0xf4205c3a, + 0xf4205b3a, 0xf0000000, + 0x80788478, 0xf4205b7a, 0xf0000000, 0x80788478, - 0xf4205c7a, 0xf0000000, - 0x80788478, 0xf4205eba, + 0xf4205c3a, 0xf0000000, + 0x80788478, 0xf4205c7a, 0xf0000000, 0x80788478, - 0xf4205efa, 0xf0000000, - 0x80788478, 0xf4205e7a, + 0xf4205eba, 0xf0000000, + 0x80788478, 0xf4205efa, 0xf0000000, 0x80788478, - 0xf4205cfa, 0xf0000000, - 0x80788478, 0xf4205bba, + 0xf4205e7a, 0xf0000000, + 0x80788478, 0xf4205cfa, 0xf0000000, 0x80788478, - 0xbf89fc07, 0xb96ef814, 0xf4205bba, 0xf0000000, 0x80788478, 0xbf89fc07, - 0xb96ef815, 0xbefd006f, - 0xbefe0070, 0xbeff0071, - 0x8b6f7bff, 0x000003ff, - 0xb96f4803, 0x8b6f7bff, - 0xfffff800, 0x856f8b6f, - 0xb96fa2c3, 0xb973f801, - 0xb8ee3b05, 0x806e816e, - 0xbf0d9972, 0xbfa20002, - 0x846e896e, 0xbfa00001, - 0x846e8a6e, 0xb8ef1e06, - 0x846f8a6f, 0x806e6f6e, - 0x806eff6e, 0x00000200, - 0x806e746e, 0x826f8075, - 0x8b6fff6f, 0x0000ffff, - 0xf4085c37, 0xf8000050, - 0xf4085d37, 0xf8000060, - 0xf4005e77, 0xf8000074, - 0xbf89fc07, 0x8b6dff6d, - 0x0000ffff, 0x8bfe7e7e, - 0x8bea6a6a, 0xb8eef802, - 0xbf0d866e, 0xbfa20002, - 0xb97af802, 0xbe80486c, - 0xb97af802, 0xbe804a6c, - 0xbfb00000, 0xbf9f0000, + 0xb96ef814, 0xf4205bba, + 0xf0000000, 0x80788478, + 0xbf89fc07, 0xb96ef815, + 0xbefd006f, 0xbefe0070, + 0xbeff0071, 0x8b6f7bff, + 0x000003ff, 0xb96f4803, + 0x8b6f7bff, 0xfffff800, + 0x856f8b6f, 0xb96fa2c3, + 0xb973f801, 0xb8ee3b05, + 0x806e816e, 0xbf0d9972, + 0xbfa20002, 0x846e896e, + 0xbfa00001, 0x846e8a6e, + 0xb8ef1e06, 0x846f8a6f, + 0x806e6f6e, 0x806eff6e, + 0x00000200, 0x806e746e, + 0x826f8075, 0x8b6fff6f, + 0x0000ffff, 0xf4085c37, + 0xf8000050, 0xf4085d37, + 0xf8000060, 0xf4005e77, + 0xf8000074, 0xbf89fc07, + 0x8b6dff6d, 0x0000ffff, + 0x8bfe7e7e, 0x8bea6a6a, + 0xb8eef802, 0xbf0d866e, + 0xbfa20002, 0xb97af802, + 0xbe80486c, 0xb97af802, + 0xbe804a6c, 0xbfb00000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, + 0xbf9f0000, 0x00000000, }; diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 0f81670f6f9c..8b92c33c2a7c 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -186,6 +186,12 @@ L_SKIP_RESTORE: s_getreg_b32 s_save_trapsts, hwreg(HW_REG_TRAPSTS) #if SW_SA_TRAP + // If ttmp1[30] is set then issue s_barrier to unblock dependent waves. + s_bitcmp1_b32 s_save_pc_hi, 30 + s_cbranch_scc0 L_TRAP_NO_BARRIER + s_barrier + +L_TRAP_NO_BARRIER: // If ttmp1[31] is set then trap may occur early. // Spin wait until SAVECTX exception is raised. s_bitcmp1_b32 s_save_pc_hi, 31 -- cgit v1.2.3 From 038ee49fef18710bedd38b531d173ccd746b2d8d Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Tue, 27 Sep 2022 13:52:34 +0200 Subject: serial: 8250: 8250_omap: Avoid RS485 RTS glitch on ->set_termios() RS485-enabled UART ports on TI Sitara SoCs with active-low polarity exhibit a Transmit Enable glitch on ->set_termios(): omap8250_restore_regs(), which is called from omap_8250_set_termios(), sets the TCRTLR bit in the MCR register and clears all other bits, including RTS. If RTS uses active-low polarity, it is now asserted for no reason. The TCRTLR bit is subsequently cleared by writing up->mcr to the MCR register. That variable is always zero, so the RTS bit is still cleared (incorrectly so if RTS is active-high). (up->mcr is not, as one might think, a cache of the MCR register's current value. Rather, it only caches a single bit of that register, the AFE bit. And it only does so if the UART supports the AFE bit, which OMAP does not. For details see serial8250_do_set_termios() and serial8250_do_set_mctrl().) Finally at the end of omap8250_restore_regs(), the MCR register is restored (and RTS deasserted) by a call to up->port.ops->set_mctrl() (which equals serial8250_set_mctrl()) and serial8250_em485_stop_tx(). So there's an RTS glitch between setting TCRTLR and calling serial8250_em485_stop_tx(). Avoid by using a read-modify-write when setting TCRTLR. While at it, drop a redundant initialization of up->mcr. As explained above, the variable isn't used by the driver and it is already initialized to zero because it is part of the static struct serial8250_ports[] declared in 8250_core.c. (Static structs are initialized to zero per section 6.7.8 nr. 10 of the C99 standard.) Cc: Jan Kiszka Cc: Su Bao Cheng Tested-by: Matthias Schiffer Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/6554b0241a2c7fd50f32576fdbafed96709e11e8.1664278942.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 41b8c6b27136..68f5a167377f 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -292,6 +292,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) { struct omap8250_priv *priv = up->port.private_data; struct uart_8250_dma *dma = up->dma; + u8 mcr = serial8250_in_MCR(up); if (dma && dma->tx_running) { /* @@ -308,7 +309,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); - serial8250_out_MCR(up, UART_MCR_TCRTLR); + serial8250_out_MCR(up, mcr | UART_MCR_TCRTLR); serial_out(up, UART_FCR, up->fcr); omap8250_update_scr(up, priv); @@ -324,7 +325,8 @@ static void omap8250_restore_regs(struct uart_8250_port *up) serial_out(up, UART_LCR, 0); /* drop TCR + TLR access, we setup XON/XOFF later */ - serial8250_out_MCR(up, up->mcr); + serial8250_out_MCR(up, mcr); + serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); @@ -669,7 +671,6 @@ static int omap_8250_startup(struct uart_port *port) pm_runtime_get_sync(port->dev); - up->mcr = 0; serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); serial_out(up, UART_LCR, UART_LCR_WLEN8); -- cgit v1.2.3 From 93810191f5d23652c0b8a1a9b3a4a89d6fd5063e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Oct 2022 09:36:13 +0300 Subject: serial: 8250: omap: Fix missing PM runtime calls for omap8250_set_mctrl() There are cases where omap8250_set_mctrl() may get called after the UART has already autoidled causing an asynchronous external abort. This can happen on ttyport_open(): mem_serial_in from omap8250_set_mctrl+0x38/0xa0 omap8250_set_mctrl from uart_update_mctrl+0x4c/0x58 uart_update_mctrl from uart_dtr_rts+0x60/0xa8 uart_dtr_rts from tty_port_block_til_ready+0xd0/0x2a8 tty_port_block_til_ready from uart_open+0x14/0x1c uart_open from ttyport_open+0x64/0x148 And on ttyport_close(): omap8250_set_mctrl from uart_update_mctrl+0x3c/0x48 uart_update_mctrl from uart_dtr_rts+0x54/0x9c uart_dtr_rts from tty_port_shutdown+0x78/0x9c tty_port_shutdown from tty_port_close+0x3c/0x74 tty_port_close from ttyport_close+0x40/0x58 It can also happen on disassociate_ctty() calling uart_shutdown() that ends up calling omap8250_set_mctrl(). Let's fix the issue by adding missing PM runtime calls to omap8250_set_mctrl(). To do this, we need to add __omap8250_set_mctrl() that can be called from both omap8250_set_mctrl(), and from runtime PM resume path when restoring the registers. Fixes: 61929cf0169d ("tty: serial: Add 8250-core based omap driver") Reported-by: Merlijn Wajer Reported-by: Romain Naour Reported-by: Ivaylo Dimitrov Tested-by: Ivaylo Dimitrov Signed-off-by: Tony Lindgren Depends-on: dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter") Link: https://lore.kernel.org/r/20221024063613.25943-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 68f5a167377f..7bfa87094125 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -157,7 +157,11 @@ static u32 uart_read(struct uart_8250_port *up, u32 reg) return readl(up->port.membase + (reg << up->port.regshift)); } -static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) +/* + * Called on runtime PM resume path from omap8250_restore_regs(), and + * omap8250_set_mctrl(). + */ +static void __omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_8250_port *up = up_to_u8250p(port); struct omap8250_priv *priv = up->port.private_data; @@ -181,6 +185,20 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) } } +static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + int err; + + err = pm_runtime_resume_and_get(port->dev); + if (err) + return; + + __omap8250_set_mctrl(port, mctrl); + + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put_autosuspend(port->dev); +} + /* * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460) * The access to uart register after MDR1 Access @@ -343,7 +361,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) omap8250_update_mdr1(up, priv); - up->port.ops->set_mctrl(&up->port, up->port.mctrl); + __omap8250_set_mctrl(&up->port, up->port.mctrl); if (up->port.rs485.flags & SER_RS485_ENABLED) serial8250_em485_stop_tx(up); -- cgit v1.2.3 From e828e56684d61b17317e0cfdef83791fa61cb76b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 13 Oct 2022 13:23:39 +0200 Subject: serial: 8250_omap: remove wait loop from Errata i202 workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were occasionally seeing the "Errata i202: timedout" on an AM335x board when repeatedly opening and closing a UART connected to an active sender. As new input may arrive at any time, it is possible to miss the "RX FIFO empty" condition, forcing the loop to wait until it times out. Nothing in the i202 Advisory states that such a wait is even necessary; other FIFO clear functions like serial8250_clear_fifos() do not wait either. For this reason, it seems safe to remove the wait, fixing the mentioned issue. Fixes: 61929cf0169d ("tty: serial: Add 8250-core based omap driver") Reviewed-by: Ilpo Järvinen Signed-off-by: Matthias Schiffer Link: https://lore.kernel.org/r/20221013112339.2540767-1-matthias.schiffer@ew.tq-group.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 7bfa87094125..766c57d50b4c 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -211,27 +211,10 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) static void omap_8250_mdr1_errataset(struct uart_8250_port *up, struct omap8250_priv *priv) { - u8 timeout = 255; - serial_out(up, UART_OMAP_MDR1, priv->mdr1); udelay(2); serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); - /* - * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and - * TX_FIFO_E bit is 1. - */ - while (UART_LSR_THRE != (serial_in(up, UART_LSR) & - (UART_LSR_THRE | UART_LSR_DR))) { - timeout--; - if (!timeout) { - /* Should *never* happen. we warn and carry on */ - dev_crit(up->port.dev, "Errata i202: timedout %x\n", - serial_in(up, UART_LSR)); - break; - } - udelay(1); - } } static void omap_8250_get_divisor(struct uart_port *port, unsigned int baud, -- cgit v1.2.3 From e3f0c638f428fd66b5871154b62706772045f91a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 28 Oct 2022 13:58:13 +0300 Subject: serial: 8250: omap: Fix unpaired pm_runtime_put_sync() in omap8250_remove() On remove, we get an error for "Runtime PM usage count underflow!". I guess this driver is mostly built-in, and this issue has gone unnoticed for a while. Somehow I did not catch this issue with my earlier fix done with commit 4e0f5cc65098 ("serial: 8250_omap: Fix probe and remove for PM runtime"). Fixes: 4e0f5cc65098 ("serial: 8250_omap: Fix probe and remove for PM runtime") Signed-off-by: Tony Lindgren Depends-on: dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter") Link: https://lore.kernel.org/r/20221028105813.54290-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 766c57d50b4c..c6ec6eb7ee21 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1460,6 +1460,11 @@ err: static int omap8250_remove(struct platform_device *pdev) { struct omap8250_priv *priv = platform_get_drvdata(pdev); + int err; + + err = pm_runtime_resume_and_get(&pdev->dev); + if (err) + return err; pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); -- cgit v1.2.3 From d0b68629bd2fb61e0171a62f2e8da3db322f5cf6 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 28 Oct 2022 14:00:44 +0300 Subject: serial: 8250: omap: Flush PM QOS work on remove Rebinding 8250_omap in a loop will at some point produce a warning for kernel/power/qos.c:296 cpu_latency_qos_update_request() with error "cpu_latency_qos_update_request called for unknown object". Let's flush the possibly pending PM QOS work scheduled from omap8250_runtime_suspend() before we disable runtime PM. Fixes: 61929cf0169d ("tty: serial: Add 8250-core based omap driver") Signed-off-by: Tony Lindgren Link: https://lore.kernel.org/r/20221028110044.54719-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index c6ec6eb7ee21..3f33014022f0 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1468,6 +1468,7 @@ static int omap8250_remove(struct platform_device *pdev) pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); + flush_work(&priv->qos_work); pm_runtime_disable(&pdev->dev); serial8250_unregister_port(priv->line); cpu_latency_qos_remove_request(&priv->pm_qos_request); -- cgit v1.2.3 From 76bad3f88750f8cc465c489e6846249e0bc3d8f5 Mon Sep 17 00:00:00 2001 From: Sherry Sun Date: Mon, 24 Oct 2022 16:58:44 +0800 Subject: tty: serial: fsl_lpuart: don't break the on-going transfer when global reset lpuart_global_reset() shouldn't break the on-going transmit engine, need to recover the on-going data transfer after reset. This can help earlycon here, since commit 60f361722ad2 ("serial: fsl_lpuart: Reset prior to registration") moved lpuart_global_reset() before uart_add_one_port(), earlycon is writing during global reset, as global reset will disable the TX and clear the baud rate register, which caused the earlycon cannot work any more after reset, needs to restore the baud rate and re-enable the transmitter to recover the earlycon write. Also move the lpuart_global_reset() down, then we can reuse the lpuart32_tx_empty() without declaration. Fixes: bd5305dcabbc ("tty: serial: fsl_lpuart: do software reset for imx7ulp and imx8qxp") Signed-off-by: Sherry Sun Link: https://lore.kernel.org/r/20221024085844.22786-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 76 ++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 67fa113f77d4..888e01fbd9c5 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -404,33 +405,6 @@ static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport) #define lpuart_enable_clks(x) __lpuart_enable_clks(x, true) #define lpuart_disable_clks(x) __lpuart_enable_clks(x, false) -static int lpuart_global_reset(struct lpuart_port *sport) -{ - struct uart_port *port = &sport->port; - void __iomem *global_addr; - int ret; - - if (uart_console(port)) - return 0; - - ret = clk_prepare_enable(sport->ipg_clk); - if (ret) { - dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret); - return ret; - } - - if (is_imx7ulp_lpuart(sport) || is_imx8qxp_lpuart(sport)) { - global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF; - writel(UART_GLOBAL_RST, global_addr); - usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US); - writel(0, global_addr); - usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US); - } - - clk_disable_unprepare(sport->ipg_clk); - return 0; -} - static void lpuart_stop_tx(struct uart_port *port) { unsigned char temp; @@ -2636,6 +2610,54 @@ static const struct serial_rs485 lpuart_rs485_supported = { /* delay_rts_* and RX_DURING_TX are not supported */ }; +static int lpuart_global_reset(struct lpuart_port *sport) +{ + struct uart_port *port = &sport->port; + void __iomem *global_addr; + unsigned long ctrl, bd; + unsigned int val = 0; + int ret; + + ret = clk_prepare_enable(sport->ipg_clk); + if (ret) { + dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret); + return ret; + } + + if (is_imx7ulp_lpuart(sport) || is_imx8qxp_lpuart(sport)) { + /* + * If the transmitter is used by earlycon, wait for transmit engine to + * complete and then reset. + */ + ctrl = lpuart32_read(port, UARTCTRL); + if (ctrl & UARTCTRL_TE) { + bd = lpuart32_read(&sport->port, UARTBAUD); + if (read_poll_timeout(lpuart32_tx_empty, val, val, 1, 100000, false, + port)) { + dev_warn(sport->port.dev, + "timeout waiting for transmit engine to complete\n"); + clk_disable_unprepare(sport->ipg_clk); + return 0; + } + } + + global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF; + writel(UART_GLOBAL_RST, global_addr); + usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US); + writel(0, global_addr); + usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US); + + /* Recover the transmitter for earlycon. */ + if (ctrl & UARTCTRL_TE) { + lpuart32_write(port, bd, UARTBAUD); + lpuart32_write(port, ctrl, UARTCTRL); + } + } + + clk_disable_unprepare(sport->ipg_clk); + return 0; +} + static int lpuart_probe(struct platform_device *pdev) { const struct lpuart_soc_data *sdata = of_device_get_match_data(&pdev->dev); -- cgit v1.2.3 From 4561d8008a467cb05ac632a215391d6b787f40aa Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 12 Oct 2022 20:13:53 +0800 Subject: serial: imx: Add missing .thaw_noirq hook The following warning is seen with non-console UART instance when system hibernates. [ 37.371969] ------------[ cut here ]------------ [ 37.376599] uart3_root_clk already disabled [ 37.380810] WARNING: CPU: 0 PID: 296 at drivers/clk/clk.c:952 clk_core_disable+0xa4/0xb0 ... [ 37.506986] Call trace: [ 37.509432] clk_core_disable+0xa4/0xb0 [ 37.513270] clk_disable+0x34/0x50 [ 37.516672] imx_uart_thaw+0x38/0x5c [ 37.520250] platform_pm_thaw+0x30/0x6c [ 37.524089] dpm_run_callback.constprop.0+0x3c/0xd4 [ 37.528972] device_resume+0x7c/0x160 [ 37.532633] dpm_resume+0xe8/0x230 [ 37.536036] hibernation_snapshot+0x288/0x430 [ 37.540397] hibernate+0x10c/0x2e0 [ 37.543798] state_store+0xc4/0xd0 [ 37.547203] kobj_attr_store+0x1c/0x30 [ 37.550953] sysfs_kf_write+0x48/0x60 [ 37.554619] kernfs_fop_write_iter+0x118/0x1ac [ 37.559063] new_sync_write+0xe8/0x184 [ 37.562812] vfs_write+0x230/0x290 [ 37.566214] ksys_write+0x68/0xf4 [ 37.569529] __arm64_sys_write+0x20/0x2c [ 37.573452] invoke_syscall.constprop.0+0x50/0xf0 [ 37.578156] do_el0_svc+0x11c/0x150 [ 37.581648] el0_svc+0x30/0x140 [ 37.584792] el0t_64_sync_handler+0xe8/0xf0 [ 37.588976] el0t_64_sync+0x1a0/0x1a4 [ 37.592639] ---[ end trace 56e22eec54676d75 ]--- On hibernating, pm core calls into related hooks in sequence like: .freeze .freeze_noirq .thaw_noirq .thaw With .thaw_noirq hook being absent, the clock will be disabled in a unbalanced call which results the warning above. imx_uart_freeze() clk_prepare_enable() imx_uart_suspend_noirq() clk_disable() imx_uart_thaw clk_disable_unprepare() Adding the missing .thaw_noirq hook as imx_uart_resume_noirq() will have the call sequence corrected as below and thus fix the warning. imx_uart_freeze() clk_prepare_enable() imx_uart_suspend_noirq() clk_disable() imx_uart_resume_noirq() clk_enable() imx_uart_thaw clk_disable_unprepare() Fixes: 09df0b3464e5 ("serial: imx: fix endless loop during suspend") Reviewed-by: Martin Kaiser Signed-off-by: Shawn Guo Link: https://lore.kernel.org/r/20221012121353.2346280-1-shawn.guo@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 05b432dc7a85..aadda66405b4 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2594,6 +2594,7 @@ static const struct dev_pm_ops imx_uart_pm_ops = { .suspend_noirq = imx_uart_suspend_noirq, .resume_noirq = imx_uart_resume_noirq, .freeze_noirq = imx_uart_suspend_noirq, + .thaw_noirq = imx_uart_resume_noirq, .restore_noirq = imx_uart_resume_noirq, .suspend = imx_uart_suspend, .resume = imx_uart_resume, -- cgit v1.2.3 From acdab4cb4ba7e5f94d2b422ebd7bf4bf68178fb2 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Sat, 8 Oct 2022 14:02:20 +0300 Subject: Revert "tty: n_gsm: avoid call of sleeping functions from atomic context" This reverts commit 902e02ea9385373ce4b142576eef41c642703955. The above commit is reverted as the usage of tx_mutex seems not to solve the problem described in 902e02ea9385 ("tty: n_gsm: avoid call of sleeping functions from atomic context") and just moves the bug to another place. Signed-off-by: Fedor Pchelkin Signed-off-by: Alexey Khoroshilov Reviewed-by: Daniel Starke Link: https://lore.kernel.org/r/20221008110221.13645-2-pchelkin@ispras.ru Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 53 +++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 5e516f5cac5a..b66e08f3d006 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -264,7 +264,7 @@ struct gsm_mux { bool constipated; /* Asked by remote to shut up */ bool has_devices; /* Devices were registered */ - struct mutex tx_mutex; + spinlock_t tx_lock; unsigned int tx_bytes; /* TX data outstanding */ #define TX_THRESH_HI 8192 #define TX_THRESH_LO 2048 @@ -700,6 +700,7 @@ static int gsm_send(struct gsm_mux *gsm, int addr, int cr, int control) struct gsm_msg *msg; u8 *dp; int ocr; + unsigned long flags; msg = gsm_data_alloc(gsm, addr, 0, control); if (!msg) @@ -721,10 +722,10 @@ static int gsm_send(struct gsm_mux *gsm, int addr, int cr, int control) gsm_print_packet("Q->", addr, cr, control, NULL, 0); - mutex_lock(&gsm->tx_mutex); + spin_lock_irqsave(&gsm->tx_lock, flags); list_add_tail(&msg->list, &gsm->tx_ctrl_list); gsm->tx_bytes += msg->len; - mutex_unlock(&gsm->tx_mutex); + spin_unlock_irqrestore(&gsm->tx_lock, flags); gsmld_write_trigger(gsm); return 0; @@ -749,7 +750,7 @@ static void gsm_dlci_clear_queues(struct gsm_mux *gsm, struct gsm_dlci *dlci) spin_unlock_irqrestore(&dlci->lock, flags); /* Clear data packets in MUX write queue */ - mutex_lock(&gsm->tx_mutex); + spin_lock_irqsave(&gsm->tx_lock, flags); list_for_each_entry_safe(msg, nmsg, &gsm->tx_data_list, list) { if (msg->addr != addr) continue; @@ -757,7 +758,7 @@ static void gsm_dlci_clear_queues(struct gsm_mux *gsm, struct gsm_dlci *dlci) list_del(&msg->list); kfree(msg); } - mutex_unlock(&gsm->tx_mutex); + spin_unlock_irqrestore(&gsm->tx_lock, flags); } /** @@ -1043,9 +1044,10 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) static void gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) { - mutex_lock(&dlci->gsm->tx_mutex); + unsigned long flags; + spin_lock_irqsave(&dlci->gsm->tx_lock, flags); __gsm_data_queue(dlci, msg); - mutex_unlock(&dlci->gsm->tx_mutex); + spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); } /** @@ -1057,7 +1059,7 @@ static void gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) * is data. Keep to the MRU of the mux. This path handles the usual tty * interface which is a byte stream with optional modem data. * - * Caller must hold the tx_mutex of the mux. + * Caller must hold the tx_lock of the mux. */ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) @@ -1117,7 +1119,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) * is data. Keep to the MRU of the mux. This path handles framed data * queued as skbuffs to the DLCI. * - * Caller must hold the tx_mutex of the mux. + * Caller must hold the tx_lock of the mux. */ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, @@ -1133,7 +1135,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, if (dlci->adaption == 4) overhead = 1; - /* dlci->skb is locked by tx_mutex */ + /* dlci->skb is locked by tx_lock */ if (dlci->skb == NULL) { dlci->skb = skb_dequeue_tail(&dlci->skb_list); if (dlci->skb == NULL) @@ -1187,7 +1189,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, * Push an empty frame in to the transmit queue to update the modem status * bits and to transmit an optional break. * - * Caller must hold the tx_mutex of the mux. + * Caller must hold the tx_lock of the mux. */ static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci, @@ -1301,12 +1303,13 @@ static int gsm_dlci_data_sweep(struct gsm_mux *gsm) static void gsm_dlci_data_kick(struct gsm_dlci *dlci) { + unsigned long flags; int sweep; if (dlci->constipated) return; - mutex_lock(&dlci->gsm->tx_mutex); + spin_lock_irqsave(&dlci->gsm->tx_lock, flags); /* If we have nothing running then we need to fire up */ sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO); if (dlci->gsm->tx_bytes == 0) { @@ -1317,7 +1320,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci) } if (sweep) gsm_dlci_data_sweep(dlci->gsm); - mutex_unlock(&dlci->gsm->tx_mutex); + spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); } /* @@ -2029,13 +2032,14 @@ static void gsm_dlci_command(struct gsm_dlci *dlci, const u8 *data, int len) static void gsm_kick_timeout(struct work_struct *work) { struct gsm_mux *gsm = container_of(work, struct gsm_mux, kick_timeout.work); + unsigned long flags; int sent = 0; - mutex_lock(&gsm->tx_mutex); + spin_lock_irqsave(&gsm->tx_lock, flags); /* If we have nothing running then we need to fire up */ if (gsm->tx_bytes < TX_THRESH_LO) sent = gsm_dlci_data_sweep(gsm); - mutex_unlock(&gsm->tx_mutex); + spin_unlock_irqrestore(&gsm->tx_lock, flags); if (sent && debug & DBG_DATA) pr_info("%s TX queue stalled\n", __func__); @@ -2565,7 +2569,6 @@ static void gsm_free_mux(struct gsm_mux *gsm) break; } } - mutex_destroy(&gsm->tx_mutex); mutex_destroy(&gsm->mutex); kfree(gsm->txframe); kfree(gsm->buf); @@ -2637,7 +2640,6 @@ static struct gsm_mux *gsm_alloc_mux(void) } spin_lock_init(&gsm->lock); mutex_init(&gsm->mutex); - mutex_init(&gsm->tx_mutex); kref_init(&gsm->ref); INIT_LIST_HEAD(&gsm->tx_ctrl_list); INIT_LIST_HEAD(&gsm->tx_data_list); @@ -2646,6 +2648,7 @@ static struct gsm_mux *gsm_alloc_mux(void) INIT_WORK(&gsm->tx_work, gsmld_write_task); init_waitqueue_head(&gsm->event); spin_lock_init(&gsm->control_lock); + spin_lock_init(&gsm->tx_lock); gsm->t1 = T1; gsm->t2 = T2; @@ -2670,7 +2673,6 @@ static struct gsm_mux *gsm_alloc_mux(void) } spin_unlock(&gsm_mux_lock); if (i == MAX_MUX) { - mutex_destroy(&gsm->tx_mutex); mutex_destroy(&gsm->mutex); kfree(gsm->txframe); kfree(gsm->buf); @@ -2826,16 +2828,17 @@ static void gsmld_write_trigger(struct gsm_mux *gsm) static void gsmld_write_task(struct work_struct *work) { struct gsm_mux *gsm = container_of(work, struct gsm_mux, tx_work); + unsigned long flags; int i, ret; /* All outstanding control channel and control messages and one data * frame is sent. */ ret = -ENODEV; - mutex_lock(&gsm->tx_mutex); + spin_lock_irqsave(&gsm->tx_lock, flags); if (gsm->tty) ret = gsm_data_kick(gsm); - mutex_unlock(&gsm->tx_mutex); + spin_unlock_irqrestore(&gsm->tx_lock, flags); if (ret >= 0) for (i = 0; i < NUM_DLCI; i++) @@ -3042,6 +3045,7 @@ static ssize_t gsmld_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t nr) { struct gsm_mux *gsm = tty->disc_data; + unsigned long flags; int space; int ret; @@ -3049,13 +3053,13 @@ static ssize_t gsmld_write(struct tty_struct *tty, struct file *file, return -ENODEV; ret = -ENOBUFS; - mutex_lock(&gsm->tx_mutex); + spin_lock_irqsave(&gsm->tx_lock, flags); space = tty_write_room(tty); if (space >= nr) ret = tty->ops->write(tty, buf, nr); else set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - mutex_unlock(&gsm->tx_mutex); + spin_unlock_irqrestore(&gsm->tx_lock, flags); return ret; } @@ -3352,13 +3356,14 @@ static struct tty_ldisc_ops tty_ldisc_packet = { static void gsm_modem_upd_via_data(struct gsm_dlci *dlci, u8 brk) { struct gsm_mux *gsm = dlci->gsm; + unsigned long flags; if (dlci->state != DLCI_OPEN || dlci->adaption != 2) return; - mutex_lock(&gsm->tx_mutex); + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_dlci_modem_output(gsm, dlci, brk); - mutex_unlock(&gsm->tx_mutex); + spin_unlock_irqrestore(&gsm->tx_lock, flags); } /** -- cgit v1.2.3 From 15743ae50e04aa907131e3ae8d66e9a2964ea232 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Sat, 8 Oct 2022 14:02:21 +0300 Subject: Revert "tty: n_gsm: replace kicktimer with delayed_work" This reverts commit c9ab053e56ce13a949977398c8edc12e6c02fc95. The above commit is reverted as it was a prerequisite for tx_mutex introduction and tx_mutex has been removed as it does not correctly work in order to protect tx data. Signed-off-by: Fedor Pchelkin Signed-off-by: Alexey Khoroshilov Reviewed-by: Daniel Starke Link: https://lore.kernel.org/r/20221008110221.13645-3-pchelkin@ispras.ru Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index b66e08f3d006..5c9f76073fcd 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -272,7 +272,7 @@ struct gsm_mux { struct list_head tx_data_list; /* Pending data packets */ /* Control messages */ - struct delayed_work kick_timeout; /* Kick TX queuing on timeout */ + struct timer_list kick_timer; /* Kick TX queuing on timeout */ struct timer_list t2_timer; /* Retransmit timer for commands */ int cretries; /* Command retry counter */ struct gsm_control *pending_cmd;/* Our current pending command */ @@ -1029,7 +1029,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) gsm->tx_bytes += msg->len; gsmld_write_trigger(gsm); - schedule_delayed_work(&gsm->kick_timeout, 10 * gsm->t1 * HZ / 100); + mod_timer(&gsm->kick_timer, jiffies + 10 * gsm->t1 * HZ / 100); } /** @@ -2022,16 +2022,16 @@ static void gsm_dlci_command(struct gsm_dlci *dlci, const u8 *data, int len) } /** - * gsm_kick_timeout - transmit if possible - * @work: work contained in our gsm object + * gsm_kick_timer - transmit if possible + * @t: timer contained in our gsm object * * Transmit data from DLCIs if the queue is empty. We can't rely on * a tty wakeup except when we filled the pipe so we need to fire off * new data ourselves in other cases. */ -static void gsm_kick_timeout(struct work_struct *work) +static void gsm_kick_timer(struct timer_list *t) { - struct gsm_mux *gsm = container_of(work, struct gsm_mux, kick_timeout.work); + struct gsm_mux *gsm = from_timer(gsm, t, kick_timer); unsigned long flags; int sent = 0; @@ -2496,7 +2496,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) } /* Finish outstanding timers, making sure they are done */ - cancel_delayed_work_sync(&gsm->kick_timeout); + del_timer_sync(&gsm->kick_timer); del_timer_sync(&gsm->t2_timer); /* Finish writing to ldisc */ @@ -2643,7 +2643,7 @@ static struct gsm_mux *gsm_alloc_mux(void) kref_init(&gsm->ref); INIT_LIST_HEAD(&gsm->tx_ctrl_list); INIT_LIST_HEAD(&gsm->tx_data_list); - INIT_DELAYED_WORK(&gsm->kick_timeout, gsm_kick_timeout); + timer_setup(&gsm->kick_timer, gsm_kick_timer, 0); timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0); INIT_WORK(&gsm->tx_work, gsmld_write_task); init_waitqueue_head(&gsm->event); -- cgit v1.2.3 From 7b7dfe4833c70a11cdfa51b38705103bd31eddaa Mon Sep 17 00:00:00 2001 From: Duoming Zhou Date: Sun, 2 Oct 2022 12:07:09 +0800 Subject: tty: n_gsm: fix sleep-in-atomic-context bug in gsm_control_send The function gsm_dlci_t1() is a timer handler that runs in an atomic context, but it calls "kzalloc(..., GFP_KERNEL)" that may sleep. As a result, the sleep-in-atomic-context bug will happen. The process is shown below: gsm_dlci_t1() gsm_dlci_open() gsm_modem_update() gsm_modem_upd_via_msc() gsm_control_send() kzalloc(sizeof(.., GFP_KERNEL) //may sleep This patch changes the gfp_t parameter of kzalloc() from GFP_KERNEL to GFP_ATOMIC in order to mitigate the bug. Fixes: e1eaea46bb40 ("tty: n_gsm line discipline") Signed-off-by: Duoming Zhou Link: https://lore.kernel.org/r/20221002040709.27849-1-duoming@zju.edu.cn Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 5c9f76073fcd..b6e0cc4571ea 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1711,7 +1711,7 @@ static struct gsm_control *gsm_control_send(struct gsm_mux *gsm, unsigned int command, u8 *data, int clen) { struct gsm_control *ctrl = kzalloc(sizeof(struct gsm_control), - GFP_KERNEL); + GFP_ATOMIC); unsigned long flags; if (ctrl == NULL) return NULL; -- cgit v1.2.3 From 40e4eb324c59e11fcb927aa46742d28aba6ecb8a Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Mon, 31 Oct 2022 21:26:45 +0800 Subject: net: mdio: fix undefined behavior in bit shift for __mdiobus_register Shifting signed 32-bit value by 31 bits is undefined, so changing significant bit to unsigned. The UBSAN warning calltrace like below: UBSAN: shift-out-of-bounds in drivers/net/phy/mdio_bus.c:586:27 left shift of 1 by 31 places cannot be represented in type 'int' Call Trace: dump_stack_lvl+0x7d/0xa5 dump_stack+0x15/0x1b ubsan_epilogue+0xe/0x4e __ubsan_handle_shift_out_of_bounds+0x1e7/0x20c __mdiobus_register+0x49d/0x4e0 fixed_mdio_bus_init+0xd8/0x12d do_one_initcall+0x76/0x430 kernel_init_freeable+0x3b3/0x422 kernel_init+0x24/0x1e0 ret_from_fork+0x1f/0x30 Fixes: 4fd5f812c23c ("phylib: allow incremental scanning of an mii bus") Signed-off-by: Gaosheng Cui Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20221031132645.168421-1-cuigaosheng1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/mdio_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index f82090bdf7ab..1cd604cd1fa1 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -583,7 +583,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) } for (i = 0; i < PHY_MAX_ADDR; i++) { - if ((bus->phy_mask & (1 << i)) == 0) { + if ((bus->phy_mask & BIT(i)) == 0) { struct phy_device *phydev; phydev = mdiobus_scan(bus, i); -- cgit v1.2.3 From d6dd2fe71153f0ff748bf188bd4af076fe09a0a6 Mon Sep 17 00:00:00 2001 From: Nick Child Date: Mon, 31 Oct 2022 10:06:42 -0500 Subject: ibmvnic: Free rwi on reset success Free the rwi structure in the event that the last rwi in the list processed successfully. The logic in commit 4f408e1fa6e1 ("ibmvnic: retry reset if there are no other resets") introduces an issue that results in a 32 byte memory leak whenever the last rwi in the list gets processed. Fixes: 4f408e1fa6e1 ("ibmvnic: retry reset if there are no other resets") Signed-off-by: Nick Child Link: https://lore.kernel.org/r/20221031150642.13356-1-nnac123@linux.ibm.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ibm/ibmvnic.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 65dbfbec487a..9282381a438f 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -3007,19 +3007,19 @@ static void __ibmvnic_reset(struct work_struct *work) rwi = get_next_rwi(adapter); /* - * If there is another reset queued, free the previous rwi - * and process the new reset even if previous reset failed - * (the previous reset could have failed because of a fail - * over for instance, so process the fail over). - * * If there are no resets queued and the previous reset failed, * the adapter would be in an undefined state. So retry the * previous reset as a hard reset. + * + * Else, free the previous rwi and, if there is another reset + * queued, process the new reset even if previous reset failed + * (the previous reset could have failed because of a fail + * over for instance, so process the fail over). */ - if (rwi) - kfree(tmprwi); - else if (rc) + if (!rwi && rc) rwi = tmprwi; + else + kfree(tmprwi); if (rwi && (rwi->reset_reason == VNIC_RESET_FAILOVER || rwi->reset_reason == VNIC_RESET_MOBILITY || rc)) -- cgit v1.2.3 From 2ae34111fe4eebb69986f6490015b57c88804373 Mon Sep 17 00:00:00 2001 From: Liu Peibao Date: Tue, 1 Nov 2022 14:02:18 +0800 Subject: stmmac: dwmac-loongson: fix invalid mdio_node In current code "plat->mdio_node" is always NULL, the mdio support is lost as there is no "mdio_bus_data". The original driver could work as the "mdio" variable is never set to false, which is described in commit ("stmmac: dwmac-loongson: fix uninitialized variable ......"). And after this commit merged, the "mdio" variable is always false, causing the mdio supoort logic lost. Fixes: 30bba69d7db4 ("stmmac: pci: Add dwmac support for Loongson") Signed-off-by: Liu Peibao Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20221101060218.16453-1-liupeibao@loongson.cn Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 017dbbda0c1c..79fa7870563b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -51,7 +51,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id struct stmmac_resources res; struct device_node *np; int ret, i, phy_mode; - bool mdio = false; np = dev_of_node(&pdev->dev); @@ -69,12 +68,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id if (!plat) return -ENOMEM; + plat->mdio_node = of_get_child_by_name(np, "mdio"); if (plat->mdio_node) { - dev_err(&pdev->dev, "Found MDIO subnode\n"); - mdio = true; - } + dev_info(&pdev->dev, "Found MDIO subnode\n"); - if (mdio) { plat->mdio_bus_data = devm_kzalloc(&pdev->dev, sizeof(*plat->mdio_bus_data), GFP_KERNEL); -- cgit v1.2.3 From 682f99b8ae886c22ba9f16df454aecc8c6d803ba Mon Sep 17 00:00:00 2001 From: "maxime@cerno.tech" Date: Mon, 24 Oct 2022 11:36:33 +0200 Subject: drm/vc4: hdmi: Take our lock to reset the link We access some fields protected by our internal mutex in vc4_hdmi_reset_link() (saved_adjusted_mode, output_bpc, output_format) and are calling functions that need to have that lock taken (vc4_hdmi_supports_scrambling()). However, the current code doesn't lock that mutex. Let's make sure it does. Fixes: 6bed2ea3cb38 ("drm/vc4: hdmi: Reset link on hotplug") Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20221024093634.118190-1-maxime@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/vc4/vc4_hdmi.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 596e311d6e58..9e549fa07467 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -349,27 +349,40 @@ static int vc4_hdmi_reset_link(struct drm_connector *connector, if (!crtc_state->active) return 0; - if (!vc4_hdmi_supports_scrambling(encoder)) + mutex_lock(&vc4_hdmi->mutex); + + if (!vc4_hdmi_supports_scrambling(encoder)) { + mutex_unlock(&vc4_hdmi->mutex); return 0; + } scrambling_needed = vc4_hdmi_mode_needs_scrambling(&vc4_hdmi->saved_adjusted_mode, vc4_hdmi->output_bpc, vc4_hdmi->output_format); - if (!scrambling_needed) + if (!scrambling_needed) { + mutex_unlock(&vc4_hdmi->mutex); return 0; + } if (conn_state->commit && - !try_wait_for_completion(&conn_state->commit->hw_done)) + !try_wait_for_completion(&conn_state->commit->hw_done)) { + mutex_unlock(&vc4_hdmi->mutex); return 0; + } ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config); if (ret < 0) { drm_err(drm, "Failed to read TMDS config: %d\n", ret); + mutex_unlock(&vc4_hdmi->mutex); return 0; } - if (!!(config & SCDC_SCRAMBLING_ENABLE) == scrambling_needed) + if (!!(config & SCDC_SCRAMBLING_ENABLE) == scrambling_needed) { + mutex_unlock(&vc4_hdmi->mutex); return 0; + } + + mutex_unlock(&vc4_hdmi->mutex); /* * HDMI 2.0 says that one should not send scrambled data -- cgit v1.2.3 From 76ffa2af16c67bbb806b8224a5289eb03f7a537d Mon Sep 17 00:00:00 2001 From: "maxime@cerno.tech" Date: Mon, 24 Oct 2022 11:36:34 +0200 Subject: drm/vc4: hdmi: Fix outdated function name in comment A comment introduced by commit 6bed2ea3cb38 ("drm/vc4: hdmi: Reset link on hotplug") mentions a drm_atomic_helper_connector_hdmi_reset_link() function that was part of the earlier versions but got moved internally and is now named vc4_hdmi_reset_link(). Let's fix the function name. Fixes: 6bed2ea3cb38 ("drm/vc4: hdmi: Reset link on hotplug") Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20221024093634.118190-2-maxime@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 9e549fa07467..79eda8f5fea0 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -410,9 +410,8 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, * .adap_enable, which leads to that funtion being called with * our mutex held. * - * A similar situation occurs with - * drm_atomic_helper_connector_hdmi_reset_link() that will call - * into our KMS hooks if the scrambling was enabled. + * A similar situation occurs with vc4_hdmi_reset_link() that + * will call into our KMS hooks if the scrambling was enabled. * * Concurrency isn't an issue at the moment since we don't share * any state with any of the other frameworks so we can ignore -- cgit v1.2.3 From 3bc6a37f59f21a8bfaf74d0975b2eb0b2d52a065 Mon Sep 17 00:00:00 2001 From: "maxime@cerno.tech" Date: Fri, 21 Oct 2022 15:13:39 +0200 Subject: drm/vc4: hdmi: Fix HSM clock too low on Pi4 Commit ae71ab585c81 ("drm/vc4: hdmi: Enforce the minimum rate at runtime_resume") reintroduced the call to clk_set_min_rate in an attempt to fix the boot without a monitor connected on the RaspberryPi3. However, that introduced a regression breaking the display output entirely (black screen but no vblank timeout) on the Pi4. This is due to the fact that we now have in a typical modeset at boot, in vc4_hdmi_encoder_pre_crtc_configure(), we have a first call to clk_set_min_rate() asking for the minimum rate of the HSM clock for our given resolution, and then a call to pm_runtime_resume_and_get(). We will thus execute vc4_hdmi_runtime_resume() which, since the commit mentioned above, will call clk_set_min_rate() a second time with the absolute minimum rate we want to enforce on the HSM clock. We're thus effectively erasing the minimum mandated by the mode we're trying to set. The fact that only the Pi4 is affected is due to the fact that it uses a different clock driver that tries to minimize the HSM clock at all time. It will thus lower the HSM clock rate to 120MHz on the second clk_set_min_rate() call. The Pi3 doesn't use the same driver and will not change the frequency on the second clk_set_min_rate() call since it's still within the new boundaries and it doesn't have the code to minimize the clock rate as needed. So even though the boundaries are still off, the clock rate is still the right one for our given mode, so everything works. There is a lot of moving parts, so I couldn't find any obvious solution: - Reverting the original is not an option, as that would break the Pi3 again. - We can't move the clk_set_min_rate() call in _pre_crtc_configure() since because, on the Pi3, the HSM clock has the CLK_SET_RATE_GATE flag which prevents the clock rate from being changed after it's been enabled. Our calls to clk_set_min_rate() can change it, so they need to be done before clk_prepare_enable(). - We can't remove the call to clk_prepare_enable() from the runtime_resume hook to put it into _pre_crtc_configure() either, since we need that clock to be enabled to access the registers, and we can't count on the fact that the display will be active in all situations (doing any CEC operation, or listing the modes while inactive are valid for example()). - We can't drop the call to clk_set_min_rate() in _pre_crtc_configure() since we would need to still enforce the minimum rate for a given resolution, and runtime_resume doesn't have access to the current mode, if there's any. - We can't copy the TMDS character rate into vc4_hdmi and reuse it since, because it's part of the KMS atomic state, it needs to be protected by a mutex. Unfortunately, some functions (CEC operations, mostly) can be reentrant (through the CEC framework) and still need a pm_runtime_get. However, we can work around this issue by leveraging the fact that the clk_set_min_rate() calls set boundaries for its given struct clk, and that each different clk_get() call will return a different instance of struct clk. The clock framework will then aggregate the boundaries for each struct clk instances linked to a given clock, plus its hardware boundaries, and will use that. We can thus get an extra HSM clock user for runtime_pm use only, and use our different clock instances depending on the context: runtime_pm will use its own to set the absolute minimum clock setup so that we never lock the CPU waiting for a register access, and the modeset part will set its requirement for the current resolution. And we let the CCF do the coordination. It's not an ideal solution, but it's fairly unintrusive and doesn't really change any part of the logic so it looks like a rather safe fix. Link: https://bugzilla.redhat.com/show_bug.cgi?id=2136234 Fixes: ae71ab585c81 ("drm/vc4: hdmi: Enforce the minimum rate at runtime_resume") Reported-by: Peter Robinson Reviewed-by: Javier Martinez Canillas Tested-by: Peter Robinson Link: https://lore.kernel.org/r/20221021131339.2203291-1-maxime@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/vc4/vc4_hdmi.c | 21 +++++++++++++++++---- drivers/gpu/drm/vc4/vc4_hdmi.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 79eda8f5fea0..470432c8fd70 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -3172,9 +3172,16 @@ static int vc4_hdmi_init_resources(struct drm_device *drm, DRM_ERROR("Failed to get HDMI state machine clock\n"); return PTR_ERR(vc4_hdmi->hsm_clock); } + vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock; + vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi"); + if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) { + DRM_ERROR("Failed to get HDMI state machine clock\n"); + return PTR_ERR(vc4_hdmi->hsm_rpm_clock); + } + return 0; } @@ -3257,6 +3264,12 @@ static int vc5_hdmi_init_resources(struct drm_device *drm, return PTR_ERR(vc4_hdmi->hsm_clock); } + vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi"); + if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) { + DRM_ERROR("Failed to get HDMI state machine clock\n"); + return PTR_ERR(vc4_hdmi->hsm_rpm_clock); + } + vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { DRM_ERROR("Failed to get pixel bvb clock\n"); @@ -3320,7 +3333,7 @@ static int vc4_hdmi_runtime_suspend(struct device *dev) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - clk_disable_unprepare(vc4_hdmi->hsm_clock); + clk_disable_unprepare(vc4_hdmi->hsm_rpm_clock); return 0; } @@ -3338,11 +3351,11 @@ static int vc4_hdmi_runtime_resume(struct device *dev) * its frequency while the power domain is active so that it * keeps its rate. */ - ret = clk_set_min_rate(vc4_hdmi->hsm_clock, HSM_MIN_CLOCK_FREQ); + ret = clk_set_min_rate(vc4_hdmi->hsm_rpm_clock, HSM_MIN_CLOCK_FREQ); if (ret) return ret; - ret = clk_prepare_enable(vc4_hdmi->hsm_clock); + ret = clk_prepare_enable(vc4_hdmi->hsm_rpm_clock); if (ret) return ret; @@ -3355,7 +3368,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev) * case, it will lead to a silent CPU stall. Let's make sure we * prevent such a case. */ - rate = clk_get_rate(vc4_hdmi->hsm_clock); + rate = clk_get_rate(vc4_hdmi->hsm_rpm_clock); if (!rate) { ret = -EINVAL; goto err_disable_clk; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index db823efb2563..1ad8e8c377e2 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -172,6 +172,7 @@ struct vc4_hdmi { struct clk *cec_clock; struct clk *pixel_clock; struct clk *hsm_clock; + struct clk *hsm_rpm_clock; struct clk *audio_clock; struct clk *pixel_bvb_clock; -- cgit v1.2.3 From 639325e4269750fbd3ccc2c4beb7e5cc40e2c4fd Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 11 Oct 2022 12:30:48 +0300 Subject: drm/i915: update DSC feature flag handling during device init DSC feature information is no longer part of the DFSM register in some display generations. Bspec:50075 Signed-off-by: Vinod Govindapillai Reviewed-by: Stanislav Lisovskiy Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221011093048.447177-1-vinod.govindapillai@intel.com --- drivers/gpu/drm/i915/intel_device_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 1dc1fb29a776..e0cc0227b4d7 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -488,7 +488,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) if (DISPLAY_VER(dev_priv) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE)) runtime->has_dmc = 0; - if (DISPLAY_VER(dev_priv) >= 10 && + if (IS_DISPLAY_VER(dev_priv, 10, 12) && (dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE)) runtime->has_dsc = 0; } -- cgit v1.2.3 From 6f85403ef4d0034fff11c77ed170aa2130329544 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 2 Nov 2022 16:57:09 +0100 Subject: drm/i915/selftests: Reduce oversaturation of request smoketesting The goal in launching the request smoketest is to have sufficient tasks running across the system such that we are likely to detect concurrency issues. We aim to have 2 tasks using the same engine, gt, device (each level of locking around submission and signaling) running at the same time. While tasks may not be running all the time as they synchronise with the gpu, they will be running most of the time, in which case having many more tasks than cores available is wasteful (and dramatically increases the workload causing excess runtime). Aim to limit the number of tasks such that there is at least 2 running per engine, spreading surplus cores around the engines (rather than running a task per core per engine.) Signed-off-by: Chris Wilson Reviewed-by: Nirmoy Das Tested-by: Nirmoy Das Signed-off-by: Nirmoy Das Reviewed-by: Tvrtko Ursulin Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20221102155709.31717-1-nirmoy.das@intel.com --- drivers/gpu/drm/i915/selftests/i915_request.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index a46350c37e9d..4380473ceb98 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -1710,7 +1710,8 @@ static int live_breadcrumbs_smoketest(void *arg) { struct drm_i915_private *i915 = arg; const unsigned int nengines = num_uabi_engines(i915); - const unsigned int ncpus = num_online_cpus(); + const unsigned int ncpus = /* saturate with nengines * ncpus */ + max_t(int, 2, DIV_ROUND_UP(num_online_cpus(), nengines)); unsigned long num_waits, num_fences; struct intel_engine_cs *engine; struct smoke_thread *threads; @@ -1782,7 +1783,7 @@ static int live_breadcrumbs_smoketest(void *arg) goto out_flush; } /* One ring interleaved between requests from all cpus */ - smoke[idx].max_batch /= num_online_cpus() + 1; + smoke[idx].max_batch /= ncpus + 1; pr_debug("Limiting batches to %d requests on %s\n", smoke[idx].max_batch, engine->name); -- cgit v1.2.3 From b9a2b0944cf77aadbeb82b05c3d1faa472d83778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Wed, 2 Nov 2022 19:45:43 +0200 Subject: drm/i915/psr: Ensure panel granularity aligns with DSC slice height MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not enable psr2 if panel ganularity is not aligned with DSC slice height when DSC is enabled Cc: José Roberto de Souza Cc: Mika Kahola Signed-off-by: Jouni Högander Reviewed-by: José Roberto de Souza Reviewed-by: Manasi Navare Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20221102174544.2288205-2-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index e11b0592055f..57575b5c6d48 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -779,6 +779,7 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; const int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay; const int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay; u16 y_granularity = 0; @@ -809,6 +810,10 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp, if (y_granularity == 0 || crtc_vdisplay % y_granularity) return false; + if (crtc_state->dsc.compression_enable && + vdsc_cfg->slice_height % y_granularity) + return false; + crtc_state->su_y_granularity = y_granularity; return true; } -- cgit v1.2.3 From f46e3f5ffc0fff6224a27117126008b2f4d94eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Wed, 2 Nov 2022 19:45:44 +0200 Subject: drm/i915/psr: Remove inappropriate DSC slice alignment warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Selective update area is now aligned with DSC slice height when DSC is enabled. Remove inappropriate warning about missing DSC alignment. Cc: José Roberto de Souza Cc: Mika Kahola Fixes: 47d4ae2192cb ("drm/i915/mtl: Extend PSR support") Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/7212 Signed-off-by: Jouni Högander Signed-off-by: Anshuman Gupta Reviewed-by: Mika Kahola Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20221102174544.2288205-3-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 57575b5c6d48..a75b37851504 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1684,9 +1684,6 @@ static void intel_psr2_sel_fetch_pipe_alignment(const struct intel_crtc_state *c pipe_clip->y1 -= pipe_clip->y1 % y_alignment; if (pipe_clip->y2 % y_alignment) pipe_clip->y2 = ((pipe_clip->y2 / y_alignment) + 1) * y_alignment; - - if (IS_ALDERLAKE_P(dev_priv) && crtc_state->dsc.compression_enable) - drm_warn(&dev_priv->drm, "Missing PSR2 sel fetch alignment with DSC\n"); } /* -- cgit v1.2.3 From 62aa1a344b0904549f6de7af958e8a1136fd5228 Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Thu, 3 Nov 2022 09:00:42 +0100 Subject: spi: stm32: fix stm32_spi_prepare_mbr() that halves spi clk for every run When this driver is used with a driver that uses preallocated spi_transfer structs. The speed_hz is halved by every run. This results in: spi_stm32 44004000.spi: SPI transfer setup failed ads7846 spi0.0: SPI transfer failed: -22 Example when running with DIV_ROUND_UP(): - First run; speed_hz = 1000000, spi->clk_rate 125000000 div 125 -> mbrdiv = 7, cur_speed = 976562 - Second run; speed_hz = 976562 div 128,00007 (roundup to 129) -> mbrdiv = 8, cur_speed = 488281 - Third run; speed_hz = 488281 div 256,000131072067109 (roundup to 257) and then -EINVAL is returned. Use DIV_ROUND_CLOSEST to allow to round down and allow us to keep the set speed. Signed-off-by: Sean Nyekjaer Link: https://lore.kernel.org/r/20221103080043.3033414-1-sean@geanix.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 3c2fa2e2f94a..def09cf0dc14 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -434,7 +434,7 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, u32 div, mbrdiv; /* Ensure spi->clk_rate is even */ - div = DIV_ROUND_UP(spi->clk_rate & ~0x1, speed_hz); + div = DIV_ROUND_CLOSEST(spi->clk_rate & ~0x1, speed_hz); /* * SPI framework set xfer->speed_hz to master->max_speed_hz if -- cgit v1.2.3 From 507d7c17cab274016dd43c8661d4586ba7504972 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:09 +0200 Subject: drm/i915/gmbus: move GPIO enum to gmbus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GPIO enum is only used in intel_gmbus.c, hide it there. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/3c386ce08d7d53a45c14c2e7519e4cc78a8161be.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.h | 18 ------------------ drivers/gpu/drm/i915/display/intel_gmbus.c | 20 +++++++++++++++++++- 2 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 918c8f432172..3cc85ef3b111 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -61,24 +61,6 @@ struct intel_remapped_info; struct intel_rotation_info; struct pci_dev; -enum i915_gpio { - GPIOA, - GPIOB, - GPIOC, - GPIOD, - GPIOE, - GPIOF, - GPIOG, - GPIOH, - __GPIOI_UNUSED, - GPIOJ, - GPIOK, - GPIOL, - GPIOM, - GPION, - GPIOO, -}; - /* * Keep the pipe enum values fixed: the code assumes that PIPE_A=0, the * rest have consecutive values and match the enum values of transcoders diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 74443f57f62d..860e0f8b6b19 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -49,9 +49,27 @@ struct intel_gmbus { struct drm_i915_private *i915; }; +enum gmbus_gpio { + GPIOA, + GPIOB, + GPIOC, + GPIOD, + GPIOE, + GPIOF, + GPIOG, + GPIOH, + __GPIOI_UNUSED, + GPIOJ, + GPIOK, + GPIOL, + GPIOM, + GPION, + GPIOO, +}; + struct gmbus_pin { const char *name; - enum i915_gpio gpio; + enum gmbus_gpio gpio; }; /* Map gmbus pin pairs to names and registers. */ -- cgit v1.2.3 From 10b60b56a05b495a5ba0ced173ba995e8a373f39 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:10 +0200 Subject: drm/i915: reduce includes in intel_connector.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only include what's needed. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/3aa1e27284e0ac308938978ae7da9ea9fbacad9e.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_connector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_connector.h b/drivers/gpu/drm/i915/display/intel_connector.h index 7d7b588d2286..9d2bc261b204 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.h +++ b/drivers/gpu/drm/i915/display/intel_connector.h @@ -6,7 +6,7 @@ #ifndef __INTEL_CONNECTOR_H__ #define __INTEL_CONNECTOR_H__ -#include "intel_display.h" +#include struct drm_connector; struct edid; -- cgit v1.2.3 From 19cfeb414ea3d7d1beba0dadc466618e5671805e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:11 +0200 Subject: drm/i915: reduce includes in intel_fifo_underrun.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only include what's needed. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/29b57e168e8af842baad2626959cea258402a2c1.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_fifo_underrun.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.h b/drivers/gpu/drm/i915/display/intel_fifo_underrun.h index e04f22ac1f49..2e47d7d3c101 100644 --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.h +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.h @@ -8,9 +8,8 @@ #include -#include "intel_display.h" - struct drm_i915_private; +enum pipe; bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv, enum pipe pipe, bool enable); -- cgit v1.2.3 From d29c410f77fd3f7dc632f5f153f455e6163d5449 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:12 +0200 Subject: drm/i915: un-inline icl_hdr_plane_mask() to simplify includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This lets us drop the heavy intel_display.h include from intel_sprite.h. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/16e13b6f207f52f8810a06f71a08e637f6397dc8.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_sprite.h | 9 +-------- drivers/gpu/drm/i915/display/skl_universal_plane.c | 5 +++++ drivers/gpu/drm/i915/display/skl_universal_plane.h | 1 + 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_sprite.h b/drivers/gpu/drm/i915/display/intel_sprite.h index 4f63e4967731..4635c7ad23f9 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.h +++ b/drivers/gpu/drm/i915/display/intel_sprite.h @@ -8,14 +8,13 @@ #include -#include "intel_display.h" - struct drm_device; struct drm_display_mode; struct drm_file; struct drm_i915_private; struct intel_crtc_state; struct intel_plane_state; +enum pipe; /* * FIXME: We should instead only take spinlocks once for the entire update @@ -34,12 +33,6 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); int chv_plane_check_rotation(const struct intel_plane_state *plane_state); -static inline u8 icl_hdr_plane_mask(void) -{ - return BIT(PLANE_PRIMARY) | - BIT(PLANE_SPRITE0) | BIT(PLANE_SPRITE1); -} - int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 7cb713043408..46e10b369a3d 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -246,6 +246,11 @@ bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id); } +u8 icl_hdr_plane_mask(void) +{ + return BIT(PLANE_PRIMARY) | BIT(PLANE_SPRITE0) | BIT(PLANE_SPRITE1); +} + bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id) { return DISPLAY_VER(dev_priv) >= 11 && diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.h b/drivers/gpu/drm/i915/display/skl_universal_plane.h index 351040b64dc7..be64c201f9b3 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.h +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.h @@ -30,6 +30,7 @@ int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state, bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id); +u8 icl_hdr_plane_mask(void); bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id); #endif -- cgit v1.2.3 From 2461bdb35e8ac4c7943d8277c118d5bba719d99c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:13 +0200 Subject: drm/i915/dpio: un-inline the vlv phy/channel mapping functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the heavy intel_display_types.h header. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/943dd3e9812138b1cf3ddcfde896cfec006f3847.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_display_types.h | 45 ---------------------- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 42 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dpio_phy.h | 6 +++ drivers/gpu/drm/i915/display/intel_dpll.c | 1 + drivers/gpu/drm/i915/display/intel_pps.c | 1 + 6 files changed, 51 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0691b49f38f1..31e91dbaa368 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -90,6 +90,7 @@ #include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dp_link_training.h" +#include "intel_dpio_phy.h" #include "intel_dpt.h" #include "intel_dsb.h" #include "intel_fbc.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5b38937c6bbd..64314273995d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1803,51 +1803,6 @@ struct intel_dp_mst_encoder { struct intel_connector *connector; }; -static inline enum dpio_channel -vlv_dig_port_to_channel(struct intel_digital_port *dig_port) -{ - switch (dig_port->base.port) { - default: - MISSING_CASE(dig_port->base.port); - fallthrough; - case PORT_B: - case PORT_D: - return DPIO_CH0; - case PORT_C: - return DPIO_CH1; - } -} - -static inline enum dpio_phy -vlv_dig_port_to_phy(struct intel_digital_port *dig_port) -{ - switch (dig_port->base.port) { - default: - MISSING_CASE(dig_port->base.port); - fallthrough; - case PORT_B: - case PORT_C: - return DPIO_PHY0; - case PORT_D: - return DPIO_PHY1; - } -} - -static inline enum dpio_channel -vlv_pipe_to_channel(enum pipe pipe) -{ - switch (pipe) { - default: - MISSING_CASE(pipe); - fallthrough; - case PIPE_A: - case PIPE_C: - return DPIO_CH0; - case PIPE_B: - return DPIO_CH1; - } -} - struct intel_load_detect_pipe { struct drm_atomic_state *restore_state; }; diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 8732b8722ed7..6fc5b9e58152 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -655,6 +655,48 @@ bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) return mask; } +enum dpio_channel vlv_dig_port_to_channel(struct intel_digital_port *dig_port) +{ + switch (dig_port->base.port) { + default: + MISSING_CASE(dig_port->base.port); + fallthrough; + case PORT_B: + case PORT_D: + return DPIO_CH0; + case PORT_C: + return DPIO_CH1; + } +} + +enum dpio_phy vlv_dig_port_to_phy(struct intel_digital_port *dig_port) +{ + switch (dig_port->base.port) { + default: + MISSING_CASE(dig_port->base.port); + fallthrough; + case PORT_B: + case PORT_C: + return DPIO_PHY0; + case PORT_D: + return DPIO_PHY1; + } +} + +enum dpio_channel vlv_pipe_to_channel(enum pipe pipe) +{ + switch (pipe) { + default: + MISSING_CASE(pipe); + fallthrough; + case PIPE_A: + case PIPE_C: + return DPIO_CH0; + case PIPE_B: + return DPIO_CH1; + } +} + void chv_set_phy_signal_level(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, u32 deemph_reg_value, u32 margin_reg_value, diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.h b/drivers/gpu/drm/i915/display/intel_dpio_phy.h index 9c3d008e8e1a..828ad58624d8 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.h +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.h @@ -10,9 +10,11 @@ enum dpio_channel; enum dpio_phy; +enum pipe; enum port; struct drm_i915_private; struct intel_crtc_state; +struct intel_digital_port; struct intel_encoder; void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port, @@ -30,6 +32,10 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, u8 lane_lat_optim_mask); u8 bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder); +enum dpio_channel vlv_dig_port_to_channel(struct intel_digital_port *dig_port); +enum dpio_phy vlv_dig_port_to_phy(struct intel_digital_port *dig_port); +enum dpio_channel vlv_pipe_to_channel(enum pipe pipe); + void chv_set_phy_signal_level(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, u32 deemph_reg_value, u32 margin_reg_value, diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index b15ba78d64d6..fdc6fa4f2ed9 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -10,6 +10,7 @@ #include "intel_de.h" #include "intel_display.h" #include "intel_display_types.h" +#include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_lvds.h" #include "intel_panel.h" diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 21944f5bf3a8..22f5e08d396b 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -9,6 +9,7 @@ #include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_dp.h" +#include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_lvds.h" #include "intel_pps.h" -- cgit v1.2.3 From 99417adb60e0d2fada04f57074358fba98e13c4a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:14 +0200 Subject: drm/i915/dpio: move dpio_channel and dpio_phy enums to intel_dpio_phy.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the size of intel_display.h by moving out the dpio_channel and dpio_phy enums. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/7c3ee7a6482540a0267f7b2974d22cab8188707a.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.h | 11 ----------- drivers/gpu/drm/i915/display/intel_display_power_well.h | 2 +- drivers/gpu/drm/i915/display/intel_dpio_phy.h | 13 +++++++++++-- drivers/gpu/drm/i915/gvt/display.c | 2 ++ drivers/gpu/drm/i915/gvt/handlers.c | 1 + drivers/gpu/drm/i915/gvt/mmio.c | 1 + drivers/gpu/drm/i915/intel_gvt_mmio_table.c | 1 + drivers/gpu/drm/i915/vlv_sideband.c | 2 ++ 8 files changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 3cc85ef3b111..d9c8b8447f9e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -261,17 +261,6 @@ enum tc_port_mode { TC_PORT_LEGACY, }; -enum dpio_channel { - DPIO_CH0, - DPIO_CH1 -}; - -enum dpio_phy { - DPIO_PHY0, - DPIO_PHY1, - DPIO_PHY2, -}; - enum aux_ch { AUX_CH_A, AUX_CH_B, diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h index e13b521e322a..ba7cb977e7c7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.h +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -7,8 +7,8 @@ #include -#include "intel_display.h" #include "intel_display_power.h" +#include "intel_dpio_phy.h" struct drm_i915_private; struct i915_power_well; diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.h b/drivers/gpu/drm/i915/display/intel_dpio_phy.h index 828ad58624d8..9c7725dacb47 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.h +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.h @@ -8,8 +8,6 @@ #include -enum dpio_channel; -enum dpio_phy; enum pipe; enum port; struct drm_i915_private; @@ -17,6 +15,17 @@ struct intel_crtc_state; struct intel_digital_port; struct intel_encoder; +enum dpio_channel { + DPIO_CH0, + DPIO_CH1, +}; + +enum dpio_phy { + DPIO_PHY0, + DPIO_PHY1, + DPIO_PHY2, +}; + void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port, enum dpio_phy *phy, enum dpio_channel *ch); void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index c7722c818b4d..c033249e73f4 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -36,6 +36,8 @@ #include "i915_reg.h" #include "gvt.h" +#include "display/intel_dpio_phy.h" + static int get_edp_pipe(struct intel_vgpu *vgpu) { u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP); diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index e7e33f95cc51..a2439a009cad 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -43,6 +43,7 @@ #include "intel_mchbar_regs.h" #include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" +#include "display/intel_dpio_phy.h" #include "display/intel_fbc.h" #include "display/vlv_dsi_pll_regs.h" #include "gt/intel_gt_regs.h" diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 9acc00505fde..5b5def6ddef7 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -37,6 +37,7 @@ #include "i915_reg.h" #include "gvt.h" +#include "display/intel_dpio_phy.h" #include "gt/intel_gt_regs.h" /** diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index e015bc91a26f..26f6418af2f7 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -6,6 +6,7 @@ #include "display/intel_audio_regs.h" #include "display/intel_backlight_regs.h" #include "display/intel_dmc_regs.h" +#include "display/intel_dpio_phy.h" #include "display/vlv_dsi_pll_regs.h" #include "gt/intel_gt_regs.h" #include "gvt/gvt.h" diff --git a/drivers/gpu/drm/i915/vlv_sideband.c b/drivers/gpu/drm/i915/vlv_sideband.c index c26001300ebd..6eea6e1a99c0 100644 --- a/drivers/gpu/drm/i915/vlv_sideband.c +++ b/drivers/gpu/drm/i915/vlv_sideband.c @@ -8,6 +8,8 @@ #include "i915_reg.h" #include "vlv_sideband.h" +#include "display/intel_dpio_phy.h" + /* * IOSF sideband, see VLV2_SidebandMsg_HAS.docx and * VLV_VLV2_PUNIT_HAS_0.8.docx -- cgit v1.2.3 From 50ae1a1c5edee3c6dfa3b7db7379ac0c4466051b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:15 +0200 Subject: drm/i915: reduce includes in intel_display_power.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only include what's needed. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/a7f41cf6d13ee78c0b3a7c5927680bb94edfc5fb.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 7136ea3f233e..1e77e52c87fe 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -6,11 +6,12 @@ #ifndef __INTEL_DISPLAY_POWER_H__ #define __INTEL_DISPLAY_POWER_H__ -#include "intel_runtime_pm.h" +#include "intel_wakeref.h" enum aux_ch; enum dpio_channel; enum dpio_phy; +enum i915_drm_suspend_mode; enum port; struct drm_i915_private; struct i915_power_well; -- cgit v1.2.3 From 356d725d62fe9d60157fcfd482ccc3fc70ee1c6c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:16 +0200 Subject: drm/i915/display: reduce the includes in intel_dvo_dev.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only include what's needed. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/8523aa88daaf2dbf0ce138980142dbcd6d1ae0bc.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dvo_dev.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dvo_dev.h b/drivers/gpu/drm/i915/display/intel_dvo_dev.h index 50205f064d93..ecff7b190856 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo_dev.h +++ b/drivers/gpu/drm/i915/display/intel_dvo_dev.h @@ -23,12 +23,12 @@ #ifndef __INTEL_DVO_DEV_H__ #define __INTEL_DVO_DEV_H__ -#include - -#include - #include "i915_reg_defs.h" +enum drm_connector_status; +struct drm_display_mode; +struct i2c_adapter; + struct intel_dvo_device { const char *name; int type; -- cgit v1.2.3 From 22b2c7691cace5928fffef878a0d2d7435abbf51 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:17 +0200 Subject: drm/i915/display: reduce includes in intel_hdmi.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only include what's needed. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/5949a57979dae615731b6ff54d5d150b91e34d27.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_hdmi.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index 93f65a917c36..774dda2376ed 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -6,20 +6,20 @@ #ifndef __INTEL_HDMI_H__ #define __INTEL_HDMI_H__ -#include #include +enum hdmi_infoframe_type; +enum port; struct drm_connector; +struct drm_connector_state; struct drm_encoder; struct drm_i915_private; struct intel_connector; +struct intel_crtc_state; struct intel_digital_port; struct intel_encoder; -struct intel_crtc_state; struct intel_hdmi; -struct drm_connector_state; union hdmi_infoframe; -enum port; void intel_hdmi_init_connector(struct intel_digital_port *dig_port, struct intel_connector *intel_connector); -- cgit v1.2.3 From 831209ec305ee9984a5036695cf73a9eb3f755bd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:18 +0200 Subject: drm/i915/display: reduce includes in g4x_dp.h includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only include what's needed. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/e68c71ad1c1c1de7f5bc659edeb208818cddde72.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/g4x_dp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/g4x_dp.h b/drivers/gpu/drm/i915/display/g4x_dp.h index e1f50263a725..a38b3e1e01d3 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.h +++ b/drivers/gpu/drm/i915/display/g4x_dp.h @@ -8,7 +8,7 @@ #include -#include "i915_reg.h" +#include "i915_reg_defs.h" enum pipe; enum port; -- cgit v1.2.3 From ad7632ff0ebfacab5936e70a4187c2f0fa789627 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:19 +0200 Subject: drm/i915/irq: make gen2_irq_init()/gen2_irq_reset() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gen2 irq functions aren't used outside of i915_irq.h. Make them static, and remove the useless macro wrappers. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/b28f45ef4ef69ab7a6f96ffa3fa3118994667332.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 10 +++++----- drivers/gpu/drm/i915/i915_irq.h | 9 --------- 2 files changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b141001a090a..b232a96478f6 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -248,7 +248,7 @@ void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, intel_uncore_posting_read(uncore, iir); } -void gen2_irq_reset(struct intel_uncore *uncore) +static void gen2_irq_reset(struct intel_uncore *uncore) { intel_uncore_write16(uncore, GEN2_IMR, 0xffff); intel_uncore_posting_read16(uncore, GEN2_IMR); @@ -309,8 +309,8 @@ void gen3_irq_init(struct intel_uncore *uncore, intel_uncore_posting_read(uncore, imr); } -void gen2_irq_init(struct intel_uncore *uncore, - u32 imr_val, u32 ier_val) +static void gen2_irq_init(struct intel_uncore *uncore, + u32 imr_val, u32 ier_val) { gen2_assert_iir_is_zero(uncore); @@ -3871,7 +3871,7 @@ static void i8xx_irq_reset(struct drm_i915_private *dev_priv) i9xx_pipestat_irq_reset(dev_priv); - GEN2_IRQ_RESET(uncore); + gen2_irq_reset(uncore); dev_priv->irq_mask = ~0u; } @@ -3897,7 +3897,7 @@ static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv) I915_MASTER_ERROR_INTERRUPT | I915_USER_INTERRUPT; - GEN2_IRQ_INIT(uncore, dev_priv->irq_mask, enable_mask); + gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask); /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h index 82639d9d7e82..9b004fc3444e 100644 --- a/drivers/gpu/drm/i915/i915_irq.h +++ b/drivers/gpu/drm/i915/i915_irq.h @@ -90,12 +90,9 @@ void i965_disable_vblank(struct drm_crtc *crtc); void ilk_disable_vblank(struct drm_crtc *crtc); void bdw_disable_vblank(struct drm_crtc *crtc); -void gen2_irq_reset(struct intel_uncore *uncore); void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, i915_reg_t iir, i915_reg_t ier); -void gen2_irq_init(struct intel_uncore *uncore, - u32 imr_val, u32 ier_val); void gen3_irq_init(struct intel_uncore *uncore, i915_reg_t imr, u32 imr_val, i915_reg_t ier, u32 ier_val, @@ -111,9 +108,6 @@ void gen3_irq_init(struct intel_uncore *uncore, #define GEN3_IRQ_RESET(uncore, type) \ gen3_irq_reset((uncore), type##IMR, type##IIR, type##IER) -#define GEN2_IRQ_RESET(uncore) \ - gen2_irq_reset(uncore) - #define GEN8_IRQ_INIT_NDX(uncore, type, which, imr_val, ier_val) \ ({ \ unsigned int which_ = which; \ @@ -129,7 +123,4 @@ void gen3_irq_init(struct intel_uncore *uncore, type##IER, ier_val, \ type##IIR) -#define GEN2_IRQ_INIT(uncore, imr_val, ier_val) \ - gen2_irq_init((uncore), imr_val, ier_val) - #endif /* __I915_IRQ_H__ */ -- cgit v1.2.3 From a4df7ac78513131abcaeafd9dc12467e2463f573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:38:56 +0300 Subject: drm/i915: Use sizeof(variable) instead sizeof(type) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use sizeof(variable) instead of sizeof(type) in the hopes of less chance of screwing things up. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-2-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 4bb113c39f4b..92cc43d5bad6 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -565,7 +565,7 @@ create_linear_lut(struct drm_i915_private *i915, int lut_size) int i; blob = drm_property_create_blob(&i915->drm, - sizeof(struct drm_color_lut) * lut_size, + sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) return blob; @@ -1895,7 +1895,7 @@ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc) int i; blob = drm_property_create_blob(&dev_priv->drm, - sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH, + sizeof(lut[0]) * LEGACY_LUT_LENGTH, NULL); if (IS_ERR(blob)) return NULL; @@ -1930,7 +1930,7 @@ static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc) struct drm_color_lut *lut; blob = drm_property_create_blob(&dev_priv->drm, - sizeof(struct drm_color_lut) * lut_size, + sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) return NULL; @@ -1973,7 +1973,7 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc) struct drm_color_lut *lut; blob = drm_property_create_blob(&dev_priv->drm, - sizeof(struct drm_color_lut) * lut_size, + sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) return NULL; @@ -2009,7 +2009,7 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc) int i; blob = drm_property_create_blob(&dev_priv->drm, - sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH, + sizeof(lut[0]) * LEGACY_LUT_LENGTH, NULL); if (IS_ERR(blob)) return NULL; @@ -2034,7 +2034,7 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc) struct drm_color_lut *lut; blob = drm_property_create_blob(&dev_priv->drm, - sizeof(struct drm_color_lut) * lut_size, + sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) return NULL; @@ -2087,7 +2087,7 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, drm_WARN_ON(&dev_priv->drm, lut_size != hw_lut_size); blob = drm_property_create_blob(&dev_priv->drm, - sizeof(struct drm_color_lut) * lut_size, + sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) return NULL; @@ -2138,7 +2138,7 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) struct drm_color_lut *lut; blob = drm_property_create_blob(&dev_priv->drm, - sizeof(struct drm_color_lut) * lut_size, + sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) return NULL; -- cgit v1.2.3 From 05ca98523481aa687c5a8dce8939fec539632153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:38:57 +0300 Subject: drm/i915: Use _MMIO_PIPE() for SKL_BOTTOM_COLOR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to use _MMIO_PIPE2() for SKL_BOTTOM_COLOR since all pipe registers are evenly spread on skl+. Switch to _MMIO_PIPE() and thus avoid the hidden dev_priv. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-3-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/i915_reg.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c5e180aec344..5a062ee46ed1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3747,9 +3747,10 @@ /* Skylake+ pipe bottom (background) color */ #define _SKL_BOTTOM_COLOR_A 0x70034 +#define _SKL_BOTTOM_COLOR_B 0x71034 #define SKL_BOTTOM_COLOR_GAMMA_ENABLE REG_BIT(31) #define SKL_BOTTOM_COLOR_CSC_ENABLE REG_BIT(30) -#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE2(pipe, _SKL_BOTTOM_COLOR_A) +#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE(pipe, _SKL_BOTTOM_COLOR_A, _SKL_BOTTOM_COLOR_B) #define _ICL_PIPE_A_STATUS 0x70058 #define ICL_PIPESTATUS(pipe) _MMIO_PIPE2(pipe, _ICL_PIPE_A_STATUS) -- cgit v1.2.3 From c9d4911cab39a7d91c5115c1f8c0414a69d27974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:38:58 +0300 Subject: drm/i915: s/dev_priv/i915/ in intel_color.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch intel_color.c over to the modern 'i915' variable naming scehme. The only exceptions are the i9xx LUT access functions which still need the magic 'dev_priv' for the register macros. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-4-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 278 ++++++++++++++--------------- 1 file changed, 139 insertions(+), 139 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 92cc43d5bad6..415e0a6839a4 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -184,31 +184,31 @@ static void ilk_update_pipe_csc(struct intel_crtc *crtc, const u16 coeff[9], const u16 postoff[3]) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - intel_de_write_fw(dev_priv, PIPE_CSC_PREOFF_HI(pipe), preoff[0]); - intel_de_write_fw(dev_priv, PIPE_CSC_PREOFF_ME(pipe), preoff[1]); - intel_de_write_fw(dev_priv, PIPE_CSC_PREOFF_LO(pipe), preoff[2]); + intel_de_write_fw(i915, PIPE_CSC_PREOFF_HI(pipe), preoff[0]); + intel_de_write_fw(i915, PIPE_CSC_PREOFF_ME(pipe), preoff[1]); + intel_de_write_fw(i915, PIPE_CSC_PREOFF_LO(pipe), preoff[2]); - intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_RY_GY(pipe), + intel_de_write_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe), coeff[0] << 16 | coeff[1]); - intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_BY(pipe), coeff[2] << 16); + intel_de_write_fw(i915, PIPE_CSC_COEFF_BY(pipe), coeff[2] << 16); - intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_RU_GU(pipe), + intel_de_write_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe), coeff[3] << 16 | coeff[4]); - intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_BU(pipe), coeff[5] << 16); + intel_de_write_fw(i915, PIPE_CSC_COEFF_BU(pipe), coeff[5] << 16); - intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_RV_GV(pipe), + intel_de_write_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe), coeff[6] << 16 | coeff[7]); - intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_BV(pipe), coeff[8] << 16); + intel_de_write_fw(i915, PIPE_CSC_COEFF_BV(pipe), coeff[8] << 16); - if (DISPLAY_VER(dev_priv) >= 7) { - intel_de_write_fw(dev_priv, PIPE_CSC_POSTOFF_HI(pipe), + if (DISPLAY_VER(i915) >= 7) { + intel_de_write_fw(i915, PIPE_CSC_POSTOFF_HI(pipe), postoff[0]); - intel_de_write_fw(dev_priv, PIPE_CSC_POSTOFF_ME(pipe), + intel_de_write_fw(i915, PIPE_CSC_POSTOFF_ME(pipe), postoff[1]); - intel_de_write_fw(dev_priv, PIPE_CSC_POSTOFF_LO(pipe), + intel_de_write_fw(i915, PIPE_CSC_POSTOFF_LO(pipe), postoff[2]); } } @@ -218,44 +218,44 @@ static void icl_update_output_csc(struct intel_crtc *crtc, const u16 coeff[9], const u16 postoff[3]) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_PREOFF_HI(pipe), preoff[0]); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_PREOFF_ME(pipe), preoff[1]); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_PREOFF_LO(pipe), preoff[2]); + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_HI(pipe), preoff[0]); + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_ME(pipe), preoff[1]); + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_LO(pipe), preoff[2]); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe), + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe), coeff[0] << 16 | coeff[1]); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_BY(pipe), + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BY(pipe), coeff[2] << 16); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe), + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe), coeff[3] << 16 | coeff[4]); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_BU(pipe), + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BU(pipe), coeff[5] << 16); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe), + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe), coeff[6] << 16 | coeff[7]); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_BV(pipe), + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BV(pipe), coeff[8] << 16); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), postoff[0]); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), postoff[1]); - intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), postoff[2]); + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), postoff[0]); + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), postoff[1]); + intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), postoff[2]); } static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); /* * FIXME if there's a gamma LUT after the CSC, we should * do the range compression using the gamma LUT instead. */ return crtc_state->limited_color_range && - (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) || - IS_DISPLAY_VER(dev_priv, 9, 10)); + (IS_HASWELL(i915) || IS_BROADWELL(i915) || + IS_DISPLAY_VER(i915, 9, 10)); } static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state, @@ -313,7 +313,7 @@ static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state, static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); bool limited_color_range = ilk_csc_limited_range(crtc_state); if (crtc_state->hw.ctm) { @@ -339,7 +339,7 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state) * LUT is needed but CSC is not we need to load an * identity matrix. */ - drm_WARN_ON(&dev_priv->drm, !IS_GEMINILAKE(dev_priv)); + drm_WARN_ON(&i915->drm, !IS_GEMINILAKE(i915)); ilk_update_pipe_csc(crtc, ilk_csc_off_zero, ilk_csc_coeff_identity, @@ -373,7 +373,7 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state) static void chv_load_cgm_csc(struct intel_crtc *crtc, const struct drm_property_blob *blob) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct drm_color_ctm *ctm = blob->data; enum pipe pipe = crtc->pipe; u16 coeffs[9]; @@ -397,15 +397,15 @@ static void chv_load_cgm_csc(struct intel_crtc *crtc, coeffs[i] |= (abs_coeff >> 20) & 0xfff; } - intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF01(pipe), + intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF01(pipe), coeffs[1] << 16 | coeffs[0]); - intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF23(pipe), + intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF23(pipe), coeffs[3] << 16 | coeffs[2]); - intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF45(pipe), + intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF45(pipe), coeffs[5] << 16 | coeffs[4]); - intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF67(pipe), + intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF67(pipe), coeffs[7] << 16 | coeffs[6]); - intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF8(pipe), + intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]); } @@ -511,31 +511,31 @@ static void i9xx_color_commit_arm(const struct intel_crtc_state *crtc_state) static void ilk_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); /* update PIPECONF GAMMA_MODE */ ilk_set_pipeconf(crtc_state); - intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe), + intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode); } static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); - intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe), + intel_de_write(i915, GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode); - intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe), + intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode); } static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; u32 val = 0; @@ -548,12 +548,12 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state) val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE; if (crtc_state->csc_enable) val |= SKL_BOTTOM_COLOR_CSC_ENABLE; - intel_de_write(dev_priv, SKL_BOTTOM_COLOR(pipe), val); + intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), val); - intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe), + intel_de_write(i915, GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode); - intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe), + intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode); } @@ -643,7 +643,7 @@ static void i965_load_luts(const struct intel_crtc_state *crtc_state) static void ilk_load_lut_8(struct intel_crtc *crtc, const struct drm_property_blob *blob) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct drm_color_lut *lut; enum pipe pipe = crtc->pipe; int i; @@ -654,20 +654,20 @@ static void ilk_load_lut_8(struct intel_crtc *crtc, lut = blob->data; for (i = 0; i < 256; i++) - intel_de_write_fw(dev_priv, LGC_PALETTE(pipe, i), + intel_de_write_fw(i915, LGC_PALETTE(pipe, i), i9xx_lut_8(&lut[i])); } static void ilk_load_lut_10(struct intel_crtc *crtc, const struct drm_property_blob *blob) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) - intel_de_write_fw(dev_priv, PREC_PALETTE(pipe, i), + intel_de_write_fw(i915, PREC_PALETTE(pipe, i), ilk_lut_10(&lut[i])); } @@ -708,7 +708,7 @@ static void ivb_load_lut_10(struct intel_crtc *crtc, const struct drm_property_blob *blob, u32 prec_index) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); int hw_lut_size = ivb_lut_10_size(prec_index); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); @@ -719,8 +719,8 @@ static void ivb_load_lut_10(struct intel_crtc *crtc, const struct drm_color_lut *entry = &lut[i * (lut_size - 1) / (hw_lut_size - 1)]; - intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), prec_index++); - intel_de_write_fw(dev_priv, PREC_PAL_DATA(pipe), + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), prec_index++); + intel_de_write_fw(i915, PREC_PAL_DATA(pipe), ilk_lut_10(entry)); } @@ -728,7 +728,7 @@ static void ivb_load_lut_10(struct intel_crtc *crtc, * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); } /* On BDW+ the index auto increment mode actually works */ @@ -736,13 +736,13 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, const struct drm_property_blob *blob, u32 prec_index) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); int hw_lut_size = ivb_lut_10_size(prec_index); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; - intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), prec_index | PAL_PREC_AUTO_INCREMENT); for (i = 0; i < hw_lut_size; i++) { @@ -750,7 +750,7 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, const struct drm_color_lut *entry = &lut[i * (lut_size - 1) / (hw_lut_size - 1)]; - intel_de_write_fw(dev_priv, PREC_PAL_DATA(pipe), + intel_de_write_fw(i915, PREC_PAL_DATA(pipe), ilk_lut_10(entry)); } @@ -758,13 +758,13 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); } static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; /* Program the max register to clamp values > 1.0. */ @@ -777,7 +777,7 @@ static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) * ToDo: Extend the ABI to be able to program values * from 3.0 to 7.0 */ - if (DISPLAY_VER(dev_priv) >= 10) { + if (DISPLAY_VER(i915) >= 10) { intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), 1 << 16); intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), @@ -858,7 +858,7 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; @@ -868,8 +868,8 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ignore the index bits, so we need to reset it to index 0 * separately. */ - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), PRE_CSC_GAMC_AUTO_INCREMENT); for (i = 0; i < lut_size; i++) { @@ -886,15 +886,15 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ToDo: Extend to max 7.0. Enable 32 bit input value * as compared to just 16 to achieve this. */ - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), + intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), lut[i].green); } /* Clamp values > 1.0. */ - while (i++ < glk_degamma_lut_size(dev_priv)) - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16); + while (i++ < glk_degamma_lut_size(i915)) + intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), 1 << 16); - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0); } static void glk_load_luts(const struct intel_crtc_state *crtc_state) @@ -1075,15 +1075,15 @@ static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color) static void chv_load_cgm_degamma(struct intel_crtc *crtc, const struct drm_property_blob *blob) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) { - intel_de_write_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0), + intel_de_write_fw(i915, CGM_PIPE_DEGAMMA(pipe, i, 0), chv_cgm_degamma_ldw(&lut[i])); - intel_de_write_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1), + intel_de_write_fw(i915, CGM_PIPE_DEGAMMA(pipe, i, 1), chv_cgm_degamma_udw(&lut[i])); } } @@ -1109,15 +1109,15 @@ static void chv_cgm_gamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw) static void chv_load_cgm_gamma(struct intel_crtc *crtc, const struct drm_property_blob *blob) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) { - intel_de_write_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0), + intel_de_write_fw(i915, CGM_PIPE_GAMMA(pipe, i, 0), chv_cgm_gamma_ldw(&lut[i])); - intel_de_write_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1), + intel_de_write_fw(i915, CGM_PIPE_GAMMA(pipe, i, 1), chv_cgm_gamma_udw(&lut[i])); } } @@ -1125,7 +1125,7 @@ static void chv_load_cgm_gamma(struct intel_crtc *crtc, static void chv_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; const struct drm_property_blob *ctm = crtc_state->hw.ctm; @@ -1141,30 +1141,30 @@ static void chv_load_luts(const struct intel_crtc_state *crtc_state) else i965_load_luts(crtc_state); - intel_de_write_fw(dev_priv, CGM_PIPE_MODE(crtc->pipe), + intel_de_write_fw(i915, CGM_PIPE_MODE(crtc->pipe), crtc_state->cgm_mode); } void intel_color_load_luts(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - dev_priv->display.funcs.color->load_luts(crtc_state); + i915->display.funcs.color->load_luts(crtc_state); } void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - if (dev_priv->display.funcs.color->color_commit_noarm) - dev_priv->display.funcs.color->color_commit_noarm(crtc_state); + if (i915->display.funcs.color->color_commit_noarm) + i915->display.funcs.color->color_commit_noarm(crtc_state); } void intel_color_commit_arm(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - dev_priv->display.funcs.color->color_commit_arm(crtc_state); + i915->display.funcs.color->color_commit_arm(crtc_state); } static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state) @@ -1200,23 +1200,23 @@ static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state) int intel_color_check(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - return dev_priv->display.funcs.color->color_check(crtc_state); + return i915->display.funcs.color->color_check(crtc_state); } void intel_color_get_config(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - if (dev_priv->display.funcs.color->read_luts) - dev_priv->display.funcs.color->read_luts(crtc_state); + if (i915->display.funcs.color->read_luts) + i915->display.funcs.color->read_luts(crtc_state); } static bool need_plane_update(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct drm_i915_private *i915 = to_i915(plane->base.dev); /* * On pre-SKL the pipe gamma enable and pipe csc enable for @@ -1224,7 +1224,7 @@ static bool need_plane_update(struct intel_plane *plane, * We have to reconfigure that even if the plane is inactive. */ return crtc_state->active_planes & BIT(plane->id) || - (DISPLAY_VER(dev_priv) < 9 && + (DISPLAY_VER(i915) < 9 && plane->id == PLANE_PRIMARY); } @@ -1232,7 +1232,7 @@ static int intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_atomic_state *state = to_intel_atomic_state(new_crtc_state->uapi.state); const struct intel_crtc_state *old_crtc_state = @@ -1247,7 +1247,7 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) new_crtc_state->csc_enable == old_crtc_state->csc_enable) return 0; - for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { + for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { struct intel_plane_state *plane_state; if (!need_plane_update(plane, new_crtc_state)) @@ -1260,7 +1260,7 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) new_crtc_state->update_planes |= BIT(plane->id); /* plane control register changes blocked by CxSR */ - if (HAS_GMCH(dev_priv)) + if (HAS_GMCH(i915)) new_crtc_state->disable_cxsr = true; } @@ -1286,7 +1286,7 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected) static int check_luts(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; @@ -1298,15 +1298,15 @@ static int check_luts(const struct intel_crtc_state *crtc_state) /* C8 relies on its palette being stored in the legacy LUT */ if (crtc_state->c8_planes) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "C8 pixelformat requires the legacy LUT\n"); return -EINVAL; } - degamma_length = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; - gamma_length = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; - degamma_tests = INTEL_INFO(dev_priv)->display.color.degamma_lut_tests; - gamma_tests = INTEL_INFO(dev_priv)->display.color.gamma_lut_tests; + degamma_length = INTEL_INFO(i915)->display.color.degamma_lut_size; + gamma_length = INTEL_INFO(i915)->display.color.gamma_lut_size; + degamma_tests = INTEL_INFO(i915)->display.color.degamma_lut_tests; + gamma_tests = INTEL_INFO(i915)->display.color.gamma_lut_tests; if (check_lut_size(degamma_lut, degamma_length) || check_lut_size(gamma_lut, gamma_length)) @@ -1550,7 +1550,7 @@ static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state) static int ivb_color_check(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); bool limited_color_range = ilk_csc_limited_range(crtc_state); int ret; @@ -1560,7 +1560,7 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && crtc_state->hw.ctm) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "YCBCR and CTM together are not possible\n"); return -EINVAL; } @@ -1617,7 +1617,7 @@ static void glk_assign_luts(struct intel_crtc_state *crtc_state) static int glk_color_check(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); int ret; ret = check_luts(crtc_state); @@ -1626,7 +1626,7 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && crtc_state->hw.ctm) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "YCBCR and CTM together are not possible\n"); return -EINVAL; } @@ -1798,19 +1798,19 @@ static int icl_gamma_precision(const struct intel_crtc_state *crtc_state) int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv)) + if (HAS_GMCH(i915)) { + if (IS_CHERRYVIEW(i915)) return chv_gamma_precision(crtc_state); else return i9xx_gamma_precision(crtc_state); } else { - if (DISPLAY_VER(dev_priv) >= 11) + if (DISPLAY_VER(i915) >= 11) return icl_gamma_precision(crtc_state); - else if (DISPLAY_VER(dev_priv) == 10) + else if (DISPLAY_VER(i915) == 10) return glk_gamma_precision(crtc_state); - else if (IS_IRONLAKE(dev_priv)) + else if (IS_IRONLAKE(i915)) return ilk_gamma_precision(crtc_state); } @@ -1966,13 +1966,13 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; - blob = drm_property_create_blob(&dev_priv->drm, + blob = drm_property_create_blob(&i915->drm, sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) @@ -1981,8 +1981,8 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc) lut = blob->data; for (i = 0; i < lut_size; i++) { - u32 ldw = intel_de_read_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0)); - u32 udw = intel_de_read_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1)); + u32 ldw = intel_de_read_fw(i915, CGM_PIPE_GAMMA(pipe, i, 0)); + u32 udw = intel_de_read_fw(i915, CGM_PIPE_GAMMA(pipe, i, 1)); chv_cgm_gamma_pack(&lut[i], ldw, udw); } @@ -2002,13 +2002,13 @@ static void chv_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; int i; - blob = drm_property_create_blob(&dev_priv->drm, + blob = drm_property_create_blob(&i915->drm, sizeof(lut[0]) * LEGACY_LUT_LENGTH, NULL); if (IS_ERR(blob)) @@ -2017,7 +2017,7 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc) lut = blob->data; for (i = 0; i < LEGACY_LUT_LENGTH; i++) { - u32 val = intel_de_read_fw(dev_priv, LGC_PALETTE(pipe, i)); + u32 val = intel_de_read_fw(i915, LGC_PALETTE(pipe, i)); i9xx_lut_8_pack(&lut[i], val); } @@ -2027,13 +2027,13 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc) static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; - blob = drm_property_create_blob(&dev_priv->drm, + blob = drm_property_create_blob(&i915->drm, sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) @@ -2042,7 +2042,7 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc) lut = blob->data; for (i = 0; i < lut_size; i++) { - u32 val = intel_de_read_fw(dev_priv, PREC_PALETTE(pipe, i)); + u32 val = intel_de_read_fw(i915, PREC_PALETTE(pipe, i)); ilk_lut_10_pack(&lut[i], val); } @@ -2077,16 +2077,16 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, u32 prec_index) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); int i, hw_lut_size = ivb_lut_10_size(prec_index); - int lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; + int lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; - drm_WARN_ON(&dev_priv->drm, lut_size != hw_lut_size); + drm_WARN_ON(&i915->drm, lut_size != hw_lut_size); - blob = drm_property_create_blob(&dev_priv->drm, + blob = drm_property_create_blob(&i915->drm, sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) @@ -2094,16 +2094,16 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, lut = blob->data; - intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), prec_index | PAL_PREC_AUTO_INCREMENT); for (i = 0; i < lut_size; i++) { - u32 val = intel_de_read_fw(dev_priv, PREC_PAL_DATA(pipe)); + u32 val = intel_de_read_fw(i915, PREC_PAL_DATA(pipe)); ilk_lut_10_pack(&lut[i], val); } - intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); return blob; } @@ -2131,13 +2131,13 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob * icl_read_lut_multi_segment(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; - blob = drm_property_create_blob(&dev_priv->drm, + blob = drm_property_create_blob(&i915->drm, sizeof(lut[0]) * lut_size, NULL); if (IS_ERR(blob)) @@ -2145,17 +2145,17 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) lut = blob->data; - intel_de_write_fw(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), + intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), PAL_PREC_AUTO_INCREMENT); for (i = 0; i < 9; i++) { - u32 ldw = intel_de_read_fw(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe)); - u32 udw = intel_de_read_fw(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe)); + u32 ldw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe)); + u32 udw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe)); icl_lut_multi_seg_pack(&lut[i], ldw, udw); } - intel_de_write_fw(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), 0); /* * FIXME readouts from PAL_PREC_DATA register aren't giving @@ -2268,15 +2268,15 @@ static const struct intel_color_funcs ilk_color_funcs = { void intel_color_crtc_init(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - bool has_ctm = INTEL_INFO(dev_priv)->display.color.degamma_lut_size != 0; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + bool has_ctm = INTEL_INFO(i915)->display.color.degamma_lut_size != 0; drm_mode_crtc_set_gamma_size(&crtc->base, 256); drm_crtc_enable_color_mgmt(&crtc->base, - INTEL_INFO(dev_priv)->display.color.degamma_lut_size, + INTEL_INFO(i915)->display.color.degamma_lut_size, has_ctm, - INTEL_INFO(dev_priv)->display.color.gamma_lut_size); + INTEL_INFO(i915)->display.color.gamma_lut_size); } int intel_color_init(struct drm_i915_private *i915) -- cgit v1.2.3 From fdaa243adf43d1d305d58f70cbc19e54c966c8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:38:59 +0300 Subject: drm/i915: s/icl_load_gcmax/ivb_load_lut_max/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify icl_load_gcmax() with the rest of the function naming scheme by calling it ivb_load_lut_max() instead. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-5-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 415e0a6839a4..e73e6ea6f82f 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -935,8 +935,8 @@ static u32 ilk_lut_12p4_ldw(const struct drm_color_lut *color) } static void -icl_load_gcmax(const struct intel_crtc_state *crtc_state, - const struct drm_color_lut *color) +ivb_load_lut_max(const struct intel_crtc_state *crtc_state, + const struct drm_color_lut *color) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum pipe pipe = crtc->pipe; @@ -1028,7 +1028,7 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) /* The last entry in the LUT is to be programmed in GCMAX */ entry = &lut[256 * 8 * 128]; - icl_load_gcmax(crtc_state, entry); + ivb_load_lut_max(crtc_state, entry); ivb_load_lut_ext_max(crtc_state); } -- cgit v1.2.3 From 4ad1aa571214e8d6468a1806794d987b374b5a08 Mon Sep 17 00:00:00 2001 From: Anirudh Rayabharam Date: Thu, 27 Oct 2022 15:27:28 +0530 Subject: clocksource/drivers/hyperv: add data structure for reference TSC MSR Add a data structure to represent the reference TSC MSR similar to other MSRs. This simplifies the code for updating the MSR. Signed-off-by: Anirudh Rayabharam Reviewed-by: Michael Kelley Link: https://lore.kernel.org/r/20221027095729.1676394-2-anrayabh@linux.microsoft.com Signed-off-by: Wei Liu --- drivers/clocksource/hyperv_timer.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index bb47610bbd1c..18de1f439ffd 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -395,25 +396,25 @@ static u64 notrace read_hv_sched_clock_tsc(void) static void suspend_hv_clock_tsc(struct clocksource *arg) { - u64 tsc_msr; + union hv_reference_tsc_msr tsc_msr; /* Disable the TSC page */ - tsc_msr = hv_get_register(HV_REGISTER_REFERENCE_TSC); - tsc_msr &= ~BIT_ULL(0); - hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr); + tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC); + tsc_msr.enable = 0; + hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64); } static void resume_hv_clock_tsc(struct clocksource *arg) { phys_addr_t phys_addr = virt_to_phys(&tsc_pg); - u64 tsc_msr; + union hv_reference_tsc_msr tsc_msr; /* Re-enable the TSC page */ - tsc_msr = hv_get_register(HV_REGISTER_REFERENCE_TSC); - tsc_msr &= GENMASK_ULL(11, 0); - tsc_msr |= BIT_ULL(0) | (u64)phys_addr; - hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr); + tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC); + tsc_msr.enable = 1; + tsc_msr.pfn = HVPFN_DOWN(phys_addr); + hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64); } #ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK @@ -495,7 +496,7 @@ static __always_inline void hv_setup_sched_clock(void *sched_clock) {} static bool __init hv_init_tsc_clocksource(void) { - u64 tsc_msr; + union hv_reference_tsc_msr tsc_msr; phys_addr_t phys_addr; if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) @@ -530,10 +531,10 @@ static bool __init hv_init_tsc_clocksource(void) * (which already has at least the low 12 bits set to zero since * it is page aligned). Also set the "enable" bit, which is bit 0. */ - tsc_msr = hv_get_register(HV_REGISTER_REFERENCE_TSC); - tsc_msr &= GENMASK_ULL(11, 0); - tsc_msr = tsc_msr | 0x1 | (u64)phys_addr; - hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr); + tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC); + tsc_msr.enable = 1; + tsc_msr.pfn = HVPFN_DOWN(phys_addr); + hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64); clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100); -- cgit v1.2.3 From e70af8d040d2b7904dca93d942ba23fb722e21b1 Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Thu, 27 Oct 2022 13:52:56 -0700 Subject: PCI: hv: Fix the definition of vector in hv_compose_msi_msg() The local variable 'vector' must be u32 rather than u8: see the struct hv_msi_desc3. 'vector_count' should be u16 rather than u8: see struct hv_msi_desc, hv_msi_desc2 and hv_msi_desc3. Fixes: a2bad844a67b ("PCI: hv: Fix interrupt mapping for multi-MSI") Signed-off-by: Dexuan Cui Cc: Jeffrey Hugo Cc: Carl Vanderlip Reviewed-by: Jeffrey Hugo Link: https://lore.kernel.org/r/20221027205256.17678-1-decui@microsoft.com Signed-off-by: Wei Liu --- drivers/pci/controller/pci-hyperv.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index e7c6f6629e7c..ba64284eaf9f 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -1614,7 +1614,7 @@ out: static u32 hv_compose_msi_req_v1( struct pci_create_interrupt *int_pkt, const struct cpumask *affinity, - u32 slot, u8 vector, u8 vector_count) + u32 slot, u8 vector, u16 vector_count) { int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE; int_pkt->wslot.slot = slot; @@ -1642,7 +1642,7 @@ static int hv_compose_msi_req_get_cpu(const struct cpumask *affinity) static u32 hv_compose_msi_req_v2( struct pci_create_interrupt2 *int_pkt, const struct cpumask *affinity, - u32 slot, u8 vector, u8 vector_count) + u32 slot, u8 vector, u16 vector_count) { int cpu; @@ -1661,7 +1661,7 @@ static u32 hv_compose_msi_req_v2( static u32 hv_compose_msi_req_v3( struct pci_create_interrupt3 *int_pkt, const struct cpumask *affinity, - u32 slot, u32 vector, u8 vector_count) + u32 slot, u32 vector, u16 vector_count) { int cpu; @@ -1701,7 +1701,12 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) struct compose_comp_ctxt comp; struct tran_int_desc *int_desc; struct msi_desc *msi_desc; - u8 vector, vector_count; + /* + * vector_count should be u16: see hv_msi_desc, hv_msi_desc2 + * and hv_msi_desc3. vector must be u32: see hv_msi_desc3. + */ + u16 vector_count; + u32 vector; struct { struct pci_packet pci_pkt; union { @@ -1767,6 +1772,11 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) vector_count = 1; } + /* + * hv_compose_msi_req_v1 and v2 are for x86 only, meaning 'vector' + * can't exceed u8. Cast 'vector' down to u8 for v1/v2 explicitly + * for better readability. + */ memset(&ctxt, 0, sizeof(ctxt)); init_completion(&comp.comp_pkt.host_event); ctxt.pci_pkt.completion_func = hv_pci_compose_compl; @@ -1777,7 +1787,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) size = hv_compose_msi_req_v1(&ctxt.int_pkts.v1, dest, hpdev->desc.win_slot.slot, - vector, + (u8)vector, vector_count); break; @@ -1786,7 +1796,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2, dest, hpdev->desc.win_slot.slot, - vector, + (u8)vector, vector_count); break; -- cgit v1.2.3 From 8f079f08833d36d8b756a08f613bccba10e23784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:39:00 +0300 Subject: drm/i915: Split ivb_load_lut_ext_max() into two parts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the EXT2_MAX register programming into its own function. More in line with the whole "cobble together stuff from small pieces" approach used in this code. The EXT(2)_MAX registers are also not really part of the multi-segment section of the LUT, so hoist the calls to a higher level, just like we do in other gamma modes as well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-6-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e73e6ea6f82f..3b78b882e0c0 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -764,27 +764,23 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; /* Program the max register to clamp values > 1.0. */ intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16); intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16); intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16); +} - /* - * Program the gc max 2 register to clamp values > 1.0. - * ToDo: Extend the ABI to be able to program values - * from 3.0 to 7.0 - */ - if (DISPLAY_VER(i915) >= 10) { - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), - 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), - 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), - 1 << 16); - } +static void glk_load_lut_ext2_max(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + enum pipe pipe = crtc->pipe; + + /* Program the max register to clamp values > 1.0. */ + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), 1 << 16); + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), 1 << 16); + intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), 1 << 16); } static void ivb_load_luts(const struct intel_crtc_state *crtc_state) @@ -913,6 +909,7 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state) case GAMMA_MODE_MODE_10BIT: bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); + glk_load_lut_ext2_max(crtc_state); break; default: MISSING_CASE(crtc_state->gamma_mode); @@ -1029,7 +1026,6 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) /* The last entry in the LUT is to be programmed in GCMAX */ entry = &lut[256 * 8 * 128]; ivb_load_lut_max(crtc_state, entry); - ivb_load_lut_ext_max(crtc_state); } static void icl_load_luts(const struct intel_crtc_state *crtc_state) @@ -1048,10 +1044,13 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state) case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: icl_program_gamma_superfine_segment(crtc_state); icl_program_gamma_multi_segment(crtc_state); + ivb_load_lut_ext_max(crtc_state); + glk_load_lut_ext2_max(crtc_state); break; case GAMMA_MODE_MODE_10BIT: bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); + glk_load_lut_ext2_max(crtc_state); break; default: MISSING_CASE(crtc_state->gamma_mode); -- cgit v1.2.3 From 28c9fa7770ea9c818b5a9fdf64e242fd9e4fdc2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:39:01 +0300 Subject: drm/i915: Deconfuse the ilk+ 12.4 LUT entry functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s/icl_lut_multi_seg_pack/ilk_lut_12p4_pack/ since that's what it is and group the corresponding "unpack" functions next to it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-7-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 38 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 3b78b882e0c0..e881c95ee451 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -482,14 +482,28 @@ static void ilk_lut_10_pack(struct drm_color_lut *entry, u32 val) entry->blue = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_BLUE_MASK, val), 10); } -static void icl_lut_multi_seg_pack(struct drm_color_lut *entry, u32 ldw, u32 udw) +/* ilk+ "12.4" interpolated format (high 10 bits) */ +static u32 ilk_lut_12p4_udw(const struct drm_color_lut *color) +{ + return (color->red >> 6) << 20 | (color->green >> 6) << 10 | + (color->blue >> 6); +} + +/* ilk+ "12.4" interpolated format (low 6 bits) */ +static u32 ilk_lut_12p4_ldw(const struct drm_color_lut *color) +{ + return (color->red & 0x3f) << 24 | (color->green & 0x3f) << 14 | + (color->blue & 0x3f) << 4; +} + +static void ilk_lut_12p4_pack(struct drm_color_lut *entry, u32 ldw, u32 udw) { entry->red = REG_FIELD_GET(PAL_PREC_MULTI_SEG_RED_UDW_MASK, udw) << 6 | - REG_FIELD_GET(PAL_PREC_MULTI_SEG_RED_LDW_MASK, ldw); + REG_FIELD_GET(PAL_PREC_MULTI_SEG_RED_LDW_MASK, ldw); entry->green = REG_FIELD_GET(PAL_PREC_MULTI_SEG_GREEN_UDW_MASK, udw) << 6 | - REG_FIELD_GET(PAL_PREC_MULTI_SEG_GREEN_LDW_MASK, ldw); + REG_FIELD_GET(PAL_PREC_MULTI_SEG_GREEN_LDW_MASK, ldw); entry->blue = REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_UDW_MASK, udw) << 6 | - REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_LDW_MASK, ldw); + REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_LDW_MASK, ldw); } static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state) @@ -917,20 +931,6 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state) } } -/* ilk+ "12.4" interpolated format (high 10 bits) */ -static u32 ilk_lut_12p4_udw(const struct drm_color_lut *color) -{ - return (color->red >> 6) << 20 | (color->green >> 6) << 10 | - (color->blue >> 6); -} - -/* ilk+ "12.4" interpolated format (low 6 bits) */ -static u32 ilk_lut_12p4_ldw(const struct drm_color_lut *color) -{ - return (color->red & 0x3f) << 24 | (color->green & 0x3f) << 14 | - (color->blue & 0x3f) << 4; -} - static void ivb_load_lut_max(const struct intel_crtc_state *crtc_state, const struct drm_color_lut *color) @@ -2151,7 +2151,7 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) u32 ldw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe)); u32 udw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe)); - icl_lut_multi_seg_pack(&lut[i], ldw, udw); + ilk_lut_12p4_pack(&lut[i], ldw, udw); } intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), 0); -- cgit v1.2.3 From ad105b715e0092b0c4c8534d07d70692adca8516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:39:02 +0300 Subject: drm/i915: Pass limited_range explicitly to ilk_csc_convert_ctm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since pre-icl vs. icl+ handle the limited range output stuff a bit differently it's probably less confusing if we just pass that information explicitly into ilk_csc_convert_ctm(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-8-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e881c95ee451..946fb767f3e0 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -259,14 +259,14 @@ static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state) } static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state, - u16 coeffs[9]) + u16 coeffs[9], bool limited_color_range) { const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data; const u64 *input; u64 temp[9]; int i; - if (ilk_csc_limited_range(crtc_state)) + if (limited_color_range) input = ctm_mult_by_limited(temp, ctm->matrix); else input = ctm->matrix; @@ -319,7 +319,7 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state) if (crtc_state->hw.ctm) { u16 coeff[9]; - ilk_csc_convert_ctm(crtc_state, coeff); + ilk_csc_convert_ctm(crtc_state, coeff, limited_color_range); ilk_update_pipe_csc(crtc, ilk_csc_off_zero, coeff, limited_color_range ? ilk_csc_postoff_limited_range : @@ -354,7 +354,7 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state) if (crtc_state->hw.ctm) { u16 coeff[9]; - ilk_csc_convert_ctm(crtc_state, coeff); + ilk_csc_convert_ctm(crtc_state, coeff, false); ilk_update_pipe_csc(crtc, ilk_csc_off_zero, coeff, ilk_csc_off_zero); } -- cgit v1.2.3 From 6d5e733f3ac1ad68a6230f44069b14bea2a9bdb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:39:03 +0300 Subject: drm/i915: Reuse ilk_gamma_mode() on ivb+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apart from the split gamma mode ivb+ LUTs work just like ilk+ LUTs. So let's handle the special case, and then just fall back to ilk_gamma_mode() to avoid having to duplicate the same logic. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-9-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 946fb767f3e0..435394cad359 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1521,14 +1521,10 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) static u32 ivb_gamma_mode(const struct intel_crtc_state *crtc_state) { - if (!crtc_state->gamma_enable || - crtc_state_is_legacy_gamma(crtc_state)) - return GAMMA_MODE_MODE_8BIT; - else if (crtc_state->hw.gamma_lut && - crtc_state->hw.degamma_lut) + if (crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) return GAMMA_MODE_MODE_SPLIT; - else - return GAMMA_MODE_MODE_10BIT; + + return ilk_gamma_mode(crtc_state); } static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state) -- cgit v1.2.3 From 4c0119dd0a7728456a2394c1bc0aa612e1f2c3cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:39:04 +0300 Subject: drm/i915: Reject YCbCr output with degamma+gamma on pre-icl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the pipe CSC sits between the degamma and gamma LUTs there is no way to make us it for RGB->YCbCr conversion when both LUTs are also active. Simply reject such combos. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-10-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 435394cad359..926784f266f2 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1556,7 +1556,14 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && crtc_state->hw.ctm) { drm_dbg_kms(&i915->drm, - "YCBCR and CTM together are not possible\n"); + "YCbCr and CTM together are not possible\n"); + return -EINVAL; + } + + if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && + crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) { + drm_dbg_kms(&i915->drm, + "YCbCr and degamma+gamma together are not possible\n"); return -EINVAL; } @@ -1622,7 +1629,14 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && crtc_state->hw.ctm) { drm_dbg_kms(&i915->drm, - "YCBCR and CTM together are not possible\n"); + "YCbCr and CTM together are not possible\n"); + return -EINVAL; + } + + if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && + crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) { + drm_dbg_kms(&i915->drm, + "YCbCr and degamma+gamma together are not possible\n"); return -EINVAL; } -- cgit v1.2.3 From 9034f9c4e284138d5e5646b89285d7a89b840f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:39:05 +0300 Subject: drm/i915: Share {csc,gamma}_enable calculation for ilk/snb vs. ivb+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ilk/snb vs. ivb+ hardware is mostly identical except for the addition of the split gamma mode on ivb. Thus we can share the csc_enable and gamma_enable calculation for both variants. Pull that stuff into a few helpers. Note that this also fills in the missing ctm/degamma stuff into ilk_color_check() pretty much, so for good measure let's also add a few extra checks relating to that, although we still don't expose ctm/degamma to userspace. But now it'll be trivial to do so if we wish. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-11-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 49 +++++++++++++++++++----------- 1 file changed, 32 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 926784f266f2..33871bfacee7 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1442,6 +1442,20 @@ static int chv_color_check(struct intel_crtc_state *crtc_state) return 0; } +static bool ilk_gamma_enable(const struct intel_crtc_state *crtc_state) +{ + return (crtc_state->hw.gamma_lut || + crtc_state->hw.degamma_lut) && + !crtc_state->c8_planes; +} + +static bool ilk_csc_enable(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || + ilk_csc_limited_range(crtc_state) || + crtc_state->hw.ctm; +} + static u32 ilk_gamma_mode(const struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable || @@ -1487,22 +1501,29 @@ static void ilk_assign_luts(struct intel_crtc_state *crtc_state) static int ilk_color_check(struct intel_crtc_state *crtc_state) { + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); int ret; ret = check_luts(crtc_state); if (ret) return ret; - crtc_state->gamma_enable = - crtc_state->hw.gamma_lut && - !crtc_state->c8_planes; + if (crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) { + drm_dbg_kms(&i915->drm, + "Degamma and gamma together are not possible\n"); + return -EINVAL; + } - /* - * We don't expose the ctm on ilk/snb currently, also RGB - * limited range output is handled by the hw automagically. - */ - crtc_state->csc_enable = - crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB; + if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && + crtc_state->hw.ctm) { + drm_dbg_kms(&i915->drm, + "YCbCr and CTM together are not possible\n"); + return -EINVAL; + } + + crtc_state->gamma_enable = ilk_gamma_enable(crtc_state); + + crtc_state->csc_enable = ilk_csc_enable(crtc_state); crtc_state->gamma_mode = ilk_gamma_mode(crtc_state); @@ -1546,7 +1567,6 @@ static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state) static int ivb_color_check(struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - bool limited_color_range = ilk_csc_limited_range(crtc_state); int ret; ret = check_luts(crtc_state); @@ -1567,14 +1587,9 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) return -EINVAL; } - crtc_state->gamma_enable = - (crtc_state->hw.gamma_lut || - crtc_state->hw.degamma_lut) && - !crtc_state->c8_planes; + crtc_state->gamma_enable = ilk_gamma_enable(crtc_state); - crtc_state->csc_enable = - crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || - crtc_state->hw.ctm || limited_color_range; + crtc_state->csc_enable = ilk_csc_enable(crtc_state); crtc_state->gamma_mode = ivb_gamma_mode(crtc_state); -- cgit v1.2.3 From 882ecff709b50b36128e07a6b0035f476c769f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 31 Oct 2022 23:40:36 +0200 Subject: drm/i915: Use intel_crtc_needs_modeset() more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer our own intel_crtc_needs_modeset() wrapper to drm_atomic_crtc_needs_modeset() whenever we are dealing with the intel_ types instead of drm_ types. Makes things a bit neater in general. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221031214037.1636-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_color.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_fbc.c | 2 +- drivers/gpu/drm/i915/display/skl_watermark.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 11 +++++------ 6 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index eada931cb1c8..8a9031012d74 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2755,7 +2755,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); - if (drm_atomic_crtc_needs_modeset(&crtc_state->uapi)) + if (intel_crtc_needs_modeset(crtc_state)) pipe = INVALID_PIPE; } diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 33871bfacee7..458e69578da6 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1239,7 +1239,7 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) struct intel_plane *plane; if (!new_crtc_state->hw.active || - drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) + intel_crtc_needs_modeset(new_crtc_state)) return 0; if (new_crtc_state->gamma_enable == old_crtc_state->gamma_enable && diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 31e91dbaa368..c4d31db935fe 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5931,7 +5931,7 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state, return PTR_ERR(crtc_state); if (!crtc_state->hw.active || - drm_atomic_crtc_needs_modeset(&crtc_state->uapi)) + intel_crtc_needs_modeset(crtc_state)) continue; drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Full modeset due to %s\n", diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 3f24f326b989..b5ee5ea0d010 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1183,7 +1183,7 @@ static bool intel_fbc_can_flip_nuke(struct intel_atomic_state *state, const struct drm_framebuffer *old_fb = old_plane_state->hw.fb; const struct drm_framebuffer *new_fb = new_plane_state->hw.fb; - if (drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) + if (intel_crtc_needs_modeset(new_crtc_state)) return false; if (!intel_fbc_is_ok(old_plane_state) || diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index d58e667016e4..e0766d1be966 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -2744,7 +2744,7 @@ static int skl_wm_add_affected_planes(struct intel_atomic_state *state, * power well the hardware state will go out of sync * with the software state. */ - if (!drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi) && + if (!intel_crtc_needs_modeset(new_crtc_state) && skl_plane_selected_wm_equals(plane, &old_crtc_state->wm.skl.optimal, &new_crtc_state->wm.skl.optimal)) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a204a32bce44..016ac568dc87 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1434,7 +1434,7 @@ static int g4x_compute_intermediate_wm(struct intel_atomic_state *state, enum plane_id plane_id; if (!new_crtc_state->hw.active || - drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) { + intel_crtc_needs_modeset(new_crtc_state)) { *intermediate = *optimal; intermediate->cxsr = false; @@ -1922,7 +1922,6 @@ static int vlv_compute_pipe_wm(struct intel_atomic_state *state, { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->uapi); const struct intel_plane_state *old_plane_state; const struct intel_plane_state *new_plane_state; struct intel_plane *plane; @@ -1949,7 +1948,7 @@ static int vlv_compute_pipe_wm(struct intel_atomic_state *state, * FIFO setting we took over from the BIOS even if there * are no active planes on the crtc. */ - if (needs_modeset) + if (intel_crtc_needs_modeset(crtc_state)) dirty = ~0; if (!dirty) @@ -1969,7 +1968,7 @@ static int vlv_compute_pipe_wm(struct intel_atomic_state *state, if (ret) return ret; - if (needs_modeset || + if (intel_crtc_needs_modeset(crtc_state) || memcmp(old_fifo_state, new_fifo_state, sizeof(*new_fifo_state)) != 0) crtc_state->fifo_changed = true; @@ -2092,7 +2091,7 @@ static int vlv_compute_intermediate_wm(struct intel_atomic_state *state, int level; if (!new_crtc_state->hw.active || - drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) { + intel_crtc_needs_modeset(new_crtc_state)) { *intermediate = *optimal; intermediate->cxsr = false; @@ -3150,7 +3149,7 @@ static int ilk_compute_intermediate_wm(struct intel_atomic_state *state, */ *a = new_crtc_state->wm.ilk.optimal; if (!new_crtc_state->hw.active || - drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi) || + intel_crtc_needs_modeset(new_crtc_state) || state->skip_intermediate_wm) return 0; -- cgit v1.2.3 From 4f1aa35f1fb7d51b125487c835982af792697ecb Mon Sep 17 00:00:00 2001 From: Yu Zhe Date: Tue, 27 Sep 2022 15:02:47 +0800 Subject: cxl/pmem: Use size_add() against integer overflow "struct_size() + n" may cause a integer overflow, use size_add() to handle it. Signed-off-by: Yu Zhe Link: https://lore.kernel.org/r/20220927070247.23148-1-yuzhe@nfschina.com Signed-off-by: Dan Williams --- drivers/cxl/pmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 115a7b79f343..0bac05d804bc 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -148,7 +148,7 @@ static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds, return -EINVAL; /* 4-byte status follows the input data in the payload */ - if (struct_size(cmd, in_buf, cmd->in_length) + 4 > buf_len) + if (size_add(struct_size(cmd, in_buf, cmd->in_length), 4) > buf_len) return -EINVAL; set_lsa = -- cgit v1.2.3 From c7e37cc6240767f794678d11704935d49cc81d59 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 3 Nov 2022 11:31:43 -0700 Subject: Input: goodix - try resetting the controller when no config is set On ACPI systems (irq_pin_access_method == IRQ_PIN_ACCESS_ACPI_*) the driver does not reset the controller at probe time, because sometimes the system firmware loads a config and resetting might loose this config. On the Nanote UMPC-01 device OTOH the config is in flash of the controller, the controller needs a reset to load this; and the system firmware does not reset the controller on a cold boot. To fix the Nanote UMPC-01 touchscreen not working on a cold boot, try resetting the controller and then re-reading the config when encountering a config with 0 width/height/max_touch_num value and the controller has not already been reset by goodix_ts_probe(). This should be safe to do in general because normally we should never encounter a config with 0 width/height/max_touch_num. Doing this in general not only avoids the need for a DMI quirk, but also might help other systems. Signed-off-by: Hans de Goede Reviewed-by: Bastien Nocera Link: https://lore.kernel.org/r/20221025122930.421377-2-hdegoede@redhat.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index a33cc7950cf5..c281e49826c2 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -1158,6 +1158,7 @@ static int goodix_configure_dev(struct goodix_ts_data *ts) input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); +retry_read_config: /* Read configuration and apply touchscreen parameters */ goodix_read_config(ts); @@ -1165,6 +1166,16 @@ static int goodix_configure_dev(struct goodix_ts_data *ts) touchscreen_parse_properties(ts->input_dev, true, &ts->prop); if (!ts->prop.max_x || !ts->prop.max_y || !ts->max_touch_num) { + if (!ts->reset_controller_at_probe && + ts->irq_pin_access_method != IRQ_PIN_ACCESS_NONE) { + dev_info(&ts->client->dev, "Config not set, resetting controller\n"); + /* Retry after a controller reset */ + ts->reset_controller_at_probe = true; + error = goodix_reset(ts); + if (error) + return error; + goto retry_read_config; + } dev_err(&ts->client->dev, "Invalid config (%d, %d, %d), using defaults\n", ts->prop.max_x, ts->prop.max_y, ts->max_touch_num); -- cgit v1.2.3 From f77810f744139572a63e5a85ab6a8c10c2d44fb1 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 3 Nov 2022 10:33:04 -0700 Subject: HID: wacom: Fix logic used for 3rd barrel switch emulation When support was added for devices using an explicit 3rd barrel switch, the logic used by devices emulating this feature was broken. The 'if' statement / block that was introduced only handles the case where the button is pressed (i.e. 'barrelswitch' and 'barrelswitch2' are both set) but not the case where it is released (i.e. one or both being cleared). This results in a BTN_STYLUS3 "down" event being sent when the button is pressed, but no "up" event ever being sent afterwards. This patch restores the previously-used logic for determining button states in the emulated case so that switches are reported correctly again. Link: https://github.com/linuxwacom/xf86-input-wacom/issues/292 Fixes: 6d09085b38e5 ("HID: wacom: Adding Support for new usages") CC: stable@vger.kernel.org #v5.19+ Signed-off-by: Jason Gerecke Tested-by: Joshua Dickens Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 77486962a773..0f3d57b42684 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2520,11 +2520,12 @@ static void wacom_wac_pen_report(struct hid_device *hdev, if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) { int id = wacom_wac->id[0]; - if (wacom_wac->features.quirks & WACOM_QUIRK_PEN_BUTTON3 && - wacom_wac->hid_data.barrelswitch & wacom_wac->hid_data.barrelswitch2) { - wacom_wac->hid_data.barrelswitch = 0; - wacom_wac->hid_data.barrelswitch2 = 0; - wacom_wac->hid_data.barrelswitch3 = 1; + if (wacom_wac->features.quirks & WACOM_QUIRK_PEN_BUTTON3) { + int sw_state = wacom_wac->hid_data.barrelswitch | + (wacom_wac->hid_data.barrelswitch2 << 1); + wacom_wac->hid_data.barrelswitch = sw_state == 1; + wacom_wac->hid_data.barrelswitch2 = sw_state == 2; + wacom_wac->hid_data.barrelswitch3 = sw_state == 3; } input_report_key(input, BTN_STYLUS, wacom_wac->hid_data.barrelswitch); input_report_key(input, BTN_STYLUS2, wacom_wac->hid_data.barrelswitch2); -- cgit v1.2.3 From 4581dd480c9e42a1ad21dd8b9c110abe41878ce5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 31 Oct 2022 22:08:13 -0700 Subject: net: octeontx2-pf: mcs: consider MACSEC setting Fix build errors when MACSEC=m and OCTEONTX2_PF=y by having OCTEONTX2_PF depend on MACSEC if it is enabled. By adding "|| !MACSEC", this means that MACSEC is not required -- it can be disabled for this driver. drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.o: in function `otx2_remove': ../drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c:(.text+0x2fd0): undefined reference to `cn10k_mcs_free' mips64-linux-ld: drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.o: in function `otx2_mbox_up_handler_mcs_intr_notify': ../drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c:(.text+0x4610): undefined reference to `cn10k_handle_mcs_event' Reported-by: kernel test robot Fixes: c54ffc73601c ("octeontx2-pf: mcs: Introduce MACSEC hardware offloading") Signed-off-by: Randy Dunlap Cc: Subbaraya Sundeep Cc: Sunil Goutham Cc: Geetha sowjanya Cc: hariprasad Cc: "David S. Miller" Cc: Eric Dumazet Cc: Jakub Kicinski Cc: Paolo Abeni Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig index e1036b0eb6b1..993ac180a5db 100644 --- a/drivers/net/ethernet/marvell/octeontx2/Kconfig +++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig @@ -36,6 +36,7 @@ config OCTEONTX2_PF select DIMLIB depends on PCI depends on PTP_1588_CLOCK_OPTIONAL + depends on MACSEC || !MACSEC help This driver supports Marvell's OcteonTX2 NIC physical function. -- cgit v1.2.3 From cfdcb075048c1e886c45a9c9e681ed222f74ecb9 Mon Sep 17 00:00:00 2001 From: Guangbin Huang Date: Tue, 1 Nov 2022 15:48:38 +0800 Subject: net: hns3: fix get wrong value of function hclge_get_dscp_prio() As the argument struct hnae3_handle *h of function hclge_get_dscp_prio() can be other client registered in hnae3 layer, we need to transform it into hnae3_handle of local nic client to get right dscp settings for other clients. Fixes: dfea275e06c2 ("net: hns3: optimize converting dscp to priority process of hns3_nic_select_queue()") Signed-off-by: Guangbin Huang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 6962a9d69cf8..987271da6e9b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -12984,14 +12984,16 @@ static void hclge_clean_vport_config(struct hnae3_ae_dev *ae_dev, int num_vfs) static int hclge_get_dscp_prio(struct hnae3_handle *h, u8 dscp, u8 *tc_mode, u8 *priority) { + struct hclge_vport *vport = hclge_get_vport(h); + if (dscp >= HNAE3_MAX_DSCP) return -EINVAL; if (tc_mode) - *tc_mode = h->kinfo.tc_map_mode; + *tc_mode = vport->nic.kinfo.tc_map_mode; if (priority) - *priority = h->kinfo.dscp_prio[dscp] == HNAE3_PRIO_ID_INVALID ? 0 : - h->kinfo.dscp_prio[dscp]; + *priority = vport->nic.kinfo.dscp_prio[dscp] == HNAE3_PRIO_ID_INVALID ? 0 : + vport->nic.kinfo.dscp_prio[dscp]; return 0; } -- cgit v1.2.3 From 8bcd560ae8784da57c610d857118c5d6576b1a8f Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 2 Nov 2022 22:33:12 +0100 Subject: Revert "net: macsec: report real_dev features when HW offloading is enabled" This reverts commit c850240b6c4132574a00f2da439277ab94265b66. That commit tried to improve the performance of macsec offload by taking advantage of some of the NIC's features, but in doing so, broke macsec offload when the lower device supports both macsec and ipsec offload, as the ipsec offload feature flags (mainly NETIF_F_HW_ESP) were copied from the real device. Since the macsec device doesn't provide xdo_* ops, the XFRM core rejects the registration of the new macsec device in xfrm_api_check. Example perf trace when running ip link add link eni1np1 type macsec port 4 offload mac ip 737 [003] 795.477676: probe:xfrm_dev_event__REGISTER name="macsec0" features=0x1c000080014869 xfrm_dev_event+0x3a notifier_call_chain+0x47 register_netdevice+0x846 macsec_newlink+0x25a ip 737 [003] 795.477687: probe:xfrm_dev_event__return ret=0x8002 (NOTIFY_BAD) notifier_call_chain+0x47 register_netdevice+0x846 macsec_newlink+0x25a dev->features includes NETIF_F_HW_ESP (0x04000000000000), so xfrm_api_check returns NOTIFY_BAD because we don't have dev->xfrmdev_ops on the macsec device. We could probably propagate GSO and a few other features from the lower device, similar to macvlan. This will be done in a future patch. Signed-off-by: Sabrina Dubroca Reviewed-by: Antoine Tenart Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/macsec.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index c891b60937a7..b3f76e8071f2 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2654,11 +2654,6 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) if (ret) goto rollback; - /* Force features update, since they are different for SW MACSec and - * HW offloading cases. - */ - netdev_update_features(dev); - rtnl_unlock(); return 0; @@ -3432,16 +3427,9 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, return ret; } -#define SW_MACSEC_FEATURES \ +#define MACSEC_FEATURES \ (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) -/* If h/w offloading is enabled, use real device features save for - * VLAN_FEATURES - they require additional ops - * HW_MACSEC - no reason to report it - */ -#define REAL_DEV_FEATURES(dev) \ - ((dev)->features & ~(NETIF_F_VLAN_FEATURES | NETIF_F_HW_MACSEC)) - static int macsec_dev_init(struct net_device *dev) { struct macsec_dev *macsec = macsec_priv(dev); @@ -3458,12 +3446,8 @@ static int macsec_dev_init(struct net_device *dev) return err; } - if (macsec_is_offloaded(macsec)) { - dev->features = REAL_DEV_FEATURES(real_dev); - } else { - dev->features = real_dev->features & SW_MACSEC_FEATURES; - dev->features |= NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE; - } + dev->features = real_dev->features & MACSEC_FEATURES; + dev->features |= NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE; dev->needed_headroom = real_dev->needed_headroom + MACSEC_NEEDED_HEADROOM; @@ -3495,10 +3479,7 @@ static netdev_features_t macsec_fix_features(struct net_device *dev, struct macsec_dev *macsec = macsec_priv(dev); struct net_device *real_dev = macsec->real_dev; - if (macsec_is_offloaded(macsec)) - return REAL_DEV_FEATURES(real_dev); - - features &= (real_dev->features & SW_MACSEC_FEATURES) | + features &= (real_dev->features & MACSEC_FEATURES) | NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES; features |= NETIF_F_LLTX; -- cgit v1.2.3 From 93a30947821c203d08865c4e17ea181c9668ce52 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 2 Nov 2022 22:33:13 +0100 Subject: macsec: delete new rxsc when offload fails Currently we get an inconsistent state: - netlink returns the error to userspace - the RXSC is installed but not offloaded Then the device could get confused when we try to add an RXSA, because the RXSC isn't supposed to exist. Fixes: 3cf3227a21d1 ("net: macsec: hardware offloading infrastructure") Signed-off-by: Sabrina Dubroca Reviewed-by: Antoine Tenart Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/macsec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index b3f76e8071f2..0d6fe34b91ae 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -1876,7 +1876,6 @@ static int macsec_add_rxsc(struct sk_buff *skb, struct genl_info *info) struct macsec_rx_sc *rx_sc; struct nlattr *tb_rxsc[MACSEC_RXSC_ATTR_MAX + 1]; struct macsec_secy *secy; - bool was_active; int ret; if (!attrs[MACSEC_ATTR_IFINDEX]) @@ -1904,7 +1903,6 @@ static int macsec_add_rxsc(struct sk_buff *skb, struct genl_info *info) return PTR_ERR(rx_sc); } - was_active = rx_sc->active; if (tb_rxsc[MACSEC_RXSC_ATTR_ACTIVE]) rx_sc->active = !!nla_get_u8(tb_rxsc[MACSEC_RXSC_ATTR_ACTIVE]); @@ -1931,7 +1929,8 @@ static int macsec_add_rxsc(struct sk_buff *skb, struct genl_info *info) return 0; cleanup: - rx_sc->active = was_active; + del_rx_sc(secy, sci); + free_rx_sc(rx_sc); rtnl_unlock(); return ret; } -- cgit v1.2.3 From 73a4b31c9d11f98ae3bc5286d5382930adb0e9c7 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 2 Nov 2022 22:33:14 +0100 Subject: macsec: fix secy->n_rx_sc accounting secy->n_rx_sc is supposed to be the number of _active_ rxsc's within a secy. This is then used by macsec_send_sci to help decide if we should add the SCI to the header or not. This logic is currently broken when we create a new RXSC and turn it off at creation, as create_rx_sc always sets ->active to true (and immediately uses that to increment n_rx_sc), and only later macsec_add_rxsc sets rx_sc->active. Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") Signed-off-by: Sabrina Dubroca Reviewed-by: Antoine Tenart Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/macsec.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 0d6fe34b91ae..1b4d856f4bd7 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -1413,7 +1413,8 @@ static struct macsec_rx_sc *del_rx_sc(struct macsec_secy *secy, sci_t sci) return NULL; } -static struct macsec_rx_sc *create_rx_sc(struct net_device *dev, sci_t sci) +static struct macsec_rx_sc *create_rx_sc(struct net_device *dev, sci_t sci, + bool active) { struct macsec_rx_sc *rx_sc; struct macsec_dev *macsec; @@ -1437,7 +1438,7 @@ static struct macsec_rx_sc *create_rx_sc(struct net_device *dev, sci_t sci) } rx_sc->sci = sci; - rx_sc->active = true; + rx_sc->active = active; refcount_set(&rx_sc->refcnt, 1); secy = &macsec_priv(dev)->secy; @@ -1876,6 +1877,7 @@ static int macsec_add_rxsc(struct sk_buff *skb, struct genl_info *info) struct macsec_rx_sc *rx_sc; struct nlattr *tb_rxsc[MACSEC_RXSC_ATTR_MAX + 1]; struct macsec_secy *secy; + bool active = true; int ret; if (!attrs[MACSEC_ATTR_IFINDEX]) @@ -1897,15 +1899,15 @@ static int macsec_add_rxsc(struct sk_buff *skb, struct genl_info *info) secy = &macsec_priv(dev)->secy; sci = nla_get_sci(tb_rxsc[MACSEC_RXSC_ATTR_SCI]); - rx_sc = create_rx_sc(dev, sci); + if (tb_rxsc[MACSEC_RXSC_ATTR_ACTIVE]) + active = nla_get_u8(tb_rxsc[MACSEC_RXSC_ATTR_ACTIVE]); + + rx_sc = create_rx_sc(dev, sci, active); if (IS_ERR(rx_sc)) { rtnl_unlock(); return PTR_ERR(rx_sc); } - if (tb_rxsc[MACSEC_RXSC_ATTR_ACTIVE]) - rx_sc->active = !!nla_get_u8(tb_rxsc[MACSEC_RXSC_ATTR_ACTIVE]); - if (macsec_is_offloaded(netdev_priv(dev))) { const struct macsec_ops *ops; struct macsec_context ctx; -- cgit v1.2.3 From 80df4706357a5a06bbbc70273bf2611df1ceee04 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 2 Nov 2022 22:33:15 +0100 Subject: macsec: fix detection of RXSCs when toggling offloading macsec_is_configured incorrectly uses secy->n_rx_sc to check if some RXSCs exist. secy->n_rx_sc only counts the number of active RXSCs, but there can also be inactive SCs as well, which may be stored in the driver (in case we're disabling offloading), or would have to be pushed to the device (in case we're trying to enable offloading). As long as RXSCs active on creation and never turned off, the issue is not visible. Fixes: dcb780fb2795 ("net: macsec: add nla support for changing the offloading selection") Signed-off-by: Sabrina Dubroca Reviewed-by: Antoine Tenart Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/macsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 1b4d856f4bd7..700a8f96c6c2 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2571,7 +2571,7 @@ static bool macsec_is_configured(struct macsec_dev *macsec) struct macsec_tx_sc *tx_sc = &secy->tx_sc; int i; - if (secy->n_rx_sc > 0) + if (secy->rx_sc) return true; for (i = 0; i < MACSEC_NUM_AN; i++) -- cgit v1.2.3 From aaab73f8fba4fd38f4d2617440d541a1c334e819 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 2 Nov 2022 22:33:16 +0100 Subject: macsec: clear encryption keys from the stack after setting up offload macsec_add_rxsa and macsec_add_txsa copy the key to an on-stack offloading context to pass it to the drivers, but leaves it there when it's done. Clear it with memzero_explicit as soon as it's not needed anymore. Fixes: 3cf3227a21d1 ("net: macsec: hardware offloading infrastructure") Signed-off-by: Sabrina Dubroca Reviewed-by: Antoine Tenart Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/macsec.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 700a8f96c6c2..85376d2f24ca 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -1839,6 +1839,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info) secy->key_len); err = macsec_offload(ops->mdo_add_rxsa, &ctx); + memzero_explicit(ctx.sa.key, secy->key_len); if (err) goto cleanup; } @@ -2081,6 +2082,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info) secy->key_len); err = macsec_offload(ops->mdo_add_txsa, &ctx); + memzero_explicit(ctx.sa.key, secy->key_len); if (err) goto cleanup; } -- cgit v1.2.3 From 1a0c016a4831ea29be09bbc8162d4a2a0690b4b8 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 2 Nov 2022 12:31:44 +0200 Subject: net: ethernet: ti: am65-cpsw: Fix segmentation fault at module unload Move am65_cpsw_nuss_phylink_cleanup() call to after am65_cpsw_nuss_cleanup_ndev() so phylink is still valid to prevent the below Segmentation fault on module remove when first slave link is up. [ 31.652944] Unable to handle kernel paging request at virtual address 00040008000005f4 [ 31.684627] Mem abort info: [ 31.687446] ESR = 0x0000000096000004 [ 31.704614] EC = 0x25: DABT (current EL), IL = 32 bits [ 31.720663] SET = 0, FnV = 0 [ 31.723729] EA = 0, S1PTW = 0 [ 31.740617] FSC = 0x04: level 0 translation fault [ 31.756624] Data abort info: [ 31.759508] ISV = 0, ISS = 0x00000004 [ 31.776705] CM = 0, WnR = 0 [ 31.779695] [00040008000005f4] address between user and kernel address ranges [ 31.808644] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP [ 31.814928] Modules linked in: wlcore_sdio wl18xx wlcore mac80211 libarc4 cfg80211 rfkill crct10dif_ce phy_gmii_sel ti_am65_cpsw_nuss(-) sch_fq_codel ipv6 [ 31.828776] CPU: 0 PID: 1026 Comm: modprobe Not tainted 6.1.0-rc2-00012-gfabfcf7dafdb-dirty #160 [ 31.837547] Hardware name: Texas Instruments AM625 (DT) [ 31.842760] pstate: 40000005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 31.849709] pc : phy_stop+0x18/0xf8 [ 31.853202] lr : phylink_stop+0x38/0xf8 [ 31.857031] sp : ffff80000a0839f0 [ 31.860335] x29: ffff80000a0839f0 x28: ffff000000de1c80 x27: 0000000000000000 [ 31.867462] x26: 0000000000000000 x25: 0000000000000000 x24: ffff80000a083b98 [ 31.874589] x23: 0000000000000800 x22: 0000000000000001 x21: ffff000001bfba90 [ 31.881715] x20: ffff0000015ee000 x19: 0004000800000200 x18: 0000000000000000 [ 31.888842] x17: ffff800076c45000 x16: ffff800008004000 x15: 000058e39660b106 [ 31.895969] x14: 0000000000000144 x13: 0000000000000144 x12: 0000000000000000 [ 31.903095] x11: 000000000000275f x10: 00000000000009e0 x9 : ffff80000a0837d0 [ 31.910222] x8 : ffff000000de26c0 x7 : ffff00007fbd6540 x6 : ffff00007fbd64c0 [ 31.917349] x5 : ffff00007fbd0b10 x4 : ffff00007fbd0b10 x3 : ffff00007fbd3920 [ 31.924476] x2 : d0a07fcff8b8d500 x1 : 0000000000000000 x0 : 0004000800000200 [ 31.931603] Call trace: [ 31.934042] phy_stop+0x18/0xf8 [ 31.937177] phylink_stop+0x38/0xf8 [ 31.940657] am65_cpsw_nuss_ndo_slave_stop+0x28/0x1e0 [ti_am65_cpsw_nuss] [ 31.947452] __dev_close_many+0xa4/0x140 [ 31.951371] dev_close_many+0x84/0x128 [ 31.955115] unregister_netdevice_many+0x130/0x6d0 [ 31.959897] unregister_netdevice_queue+0x94/0xd8 [ 31.964591] unregister_netdev+0x24/0x38 [ 31.968504] am65_cpsw_nuss_cleanup_ndev.isra.0+0x48/0x70 [ti_am65_cpsw_nuss] [ 31.975637] am65_cpsw_nuss_remove+0x58/0xf8 [ti_am65_cpsw_nuss] Cc: # v5.18+ Fixes: e8609e69470f ("net: ethernet: ti: am65-cpsw: Convert to PHYLINK") Signed-off-by: Roger Quadros Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 7f86068f3ff6..c50b137f92d7 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -2823,7 +2823,6 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev) if (ret < 0) return ret; - am65_cpsw_nuss_phylink_cleanup(common); am65_cpsw_unregister_devlink(common); am65_cpsw_unregister_notifiers(common); @@ -2831,6 +2830,7 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev) * dma_deconfigure(dev) before devres_release_all(dev) */ am65_cpsw_nuss_cleanup_ndev(common); + am65_cpsw_nuss_phylink_cleanup(common); of_platform_device_destroy(common->mdio_dev, NULL); -- cgit v1.2.3 From 51afe9026d0c63263abe9840e629f118d7405b36 Mon Sep 17 00:00:00 2001 From: Ratheesh Kannoth Date: Wed, 2 Nov 2022 08:41:13 +0530 Subject: octeontx2-pf: NIX TX overwrites SQ_CTX_HW_S[SQ_INT] In scenarios where multiple errors have occurred for a SQ before SW starts handling error interrupt, SQ_CTX[OP_INT] may get overwritten leading to NIX_LF_SQ_OP_INT returning incorrect value. To workaround this read LMT, MNQ and SQ individual error status registers to determine the cause of error. Fixes: 4ff7d1488a84 ("octeontx2-pf: Error handling support") Signed-off-by: Ratheesh Kannoth Reviewed-by: Sunil Kovvuri Goutham Signed-off-by: David S. Miller --- .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 135 ++++++++++++++++----- .../ethernet/marvell/octeontx2/nic/otx2_struct.h | 57 +++++++++ 2 files changed, 162 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index 892ca88e0cf4..303930499a4c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "otx2_reg.h" #include "otx2_common.h" @@ -1171,6 +1172,59 @@ int otx2_set_real_num_queues(struct net_device *netdev, } EXPORT_SYMBOL(otx2_set_real_num_queues); +static char *nix_sqoperr_e_str[NIX_SQOPERR_MAX] = { + "NIX_SQOPERR_OOR", + "NIX_SQOPERR_CTX_FAULT", + "NIX_SQOPERR_CTX_POISON", + "NIX_SQOPERR_DISABLED", + "NIX_SQOPERR_SIZE_ERR", + "NIX_SQOPERR_OFLOW", + "NIX_SQOPERR_SQB_NULL", + "NIX_SQOPERR_SQB_FAULT", + "NIX_SQOPERR_SQE_SZ_ZERO", +}; + +static char *nix_mnqerr_e_str[NIX_MNQERR_MAX] = { + "NIX_MNQERR_SQ_CTX_FAULT", + "NIX_MNQERR_SQ_CTX_POISON", + "NIX_MNQERR_SQB_FAULT", + "NIX_MNQERR_SQB_POISON", + "NIX_MNQERR_TOTAL_ERR", + "NIX_MNQERR_LSO_ERR", + "NIX_MNQERR_CQ_QUERY_ERR", + "NIX_MNQERR_MAX_SQE_SIZE_ERR", + "NIX_MNQERR_MAXLEN_ERR", + "NIX_MNQERR_SQE_SIZEM1_ZERO", +}; + +static char *nix_snd_status_e_str[NIX_SND_STATUS_MAX] = { + "NIX_SND_STATUS_GOOD", + "NIX_SND_STATUS_SQ_CTX_FAULT", + "NIX_SND_STATUS_SQ_CTX_POISON", + "NIX_SND_STATUS_SQB_FAULT", + "NIX_SND_STATUS_SQB_POISON", + "NIX_SND_STATUS_HDR_ERR", + "NIX_SND_STATUS_EXT_ERR", + "NIX_SND_STATUS_JUMP_FAULT", + "NIX_SND_STATUS_JUMP_POISON", + "NIX_SND_STATUS_CRC_ERR", + "NIX_SND_STATUS_IMM_ERR", + "NIX_SND_STATUS_SG_ERR", + "NIX_SND_STATUS_MEM_ERR", + "NIX_SND_STATUS_INVALID_SUBDC", + "NIX_SND_STATUS_SUBDC_ORDER_ERR", + "NIX_SND_STATUS_DATA_FAULT", + "NIX_SND_STATUS_DATA_POISON", + "NIX_SND_STATUS_NPC_DROP_ACTION", + "NIX_SND_STATUS_LOCK_VIOL", + "NIX_SND_STATUS_NPC_UCAST_CHAN_ERR", + "NIX_SND_STATUS_NPC_MCAST_CHAN_ERR", + "NIX_SND_STATUS_NPC_MCAST_ABORT", + "NIX_SND_STATUS_NPC_VTAG_PTR_ERR", + "NIX_SND_STATUS_NPC_VTAG_SIZE_ERR", + "NIX_SND_STATUS_SEND_STATS_ERR", +}; + static irqreturn_t otx2_q_intr_handler(int irq, void *data) { struct otx2_nic *pf = data; @@ -1204,46 +1258,67 @@ static irqreturn_t otx2_q_intr_handler(int irq, void *data) /* SQ */ for (qidx = 0; qidx < pf->hw.tot_tx_queues; qidx++) { + u64 sq_op_err_dbg, mnq_err_dbg, snd_err_dbg; + u8 sq_op_err_code, mnq_err_code, snd_err_code; + + /* Below debug registers captures first errors corresponding to + * those registers. We don't have to check against SQ qid as + * these are fatal errors. + */ + ptr = otx2_get_regaddr(pf, NIX_LF_SQ_OP_INT); val = otx2_atomic64_add((qidx << 44), ptr); otx2_write64(pf, NIX_LF_SQ_OP_INT, (qidx << 44) | (val & NIX_SQINT_BITS)); - if (!(val & (NIX_SQINT_BITS | BIT_ULL(42)))) - continue; - if (val & BIT_ULL(42)) { netdev_err(pf->netdev, "SQ%lld: error reading NIX_LF_SQ_OP_INT, NIX_LF_ERR_INT 0x%llx\n", qidx, otx2_read64(pf, NIX_LF_ERR_INT)); - } else { - if (val & BIT_ULL(NIX_SQINT_LMT_ERR)) { - netdev_err(pf->netdev, "SQ%lld: LMT store error NIX_LF_SQ_OP_ERR_DBG:0x%llx", - qidx, - otx2_read64(pf, - NIX_LF_SQ_OP_ERR_DBG)); - otx2_write64(pf, NIX_LF_SQ_OP_ERR_DBG, - BIT_ULL(44)); - } - if (val & BIT_ULL(NIX_SQINT_MNQ_ERR)) { - netdev_err(pf->netdev, "SQ%lld: Meta-descriptor enqueue error NIX_LF_MNQ_ERR_DGB:0x%llx\n", - qidx, - otx2_read64(pf, NIX_LF_MNQ_ERR_DBG)); - otx2_write64(pf, NIX_LF_MNQ_ERR_DBG, - BIT_ULL(44)); - } - if (val & BIT_ULL(NIX_SQINT_SEND_ERR)) { - netdev_err(pf->netdev, "SQ%lld: Send error, NIX_LF_SEND_ERR_DBG 0x%llx", - qidx, - otx2_read64(pf, - NIX_LF_SEND_ERR_DBG)); - otx2_write64(pf, NIX_LF_SEND_ERR_DBG, - BIT_ULL(44)); - } - if (val & BIT_ULL(NIX_SQINT_SQB_ALLOC_FAIL)) - netdev_err(pf->netdev, "SQ%lld: SQB allocation failed", - qidx); + goto done; } + sq_op_err_dbg = otx2_read64(pf, NIX_LF_SQ_OP_ERR_DBG); + if (!(sq_op_err_dbg & BIT(44))) + goto chk_mnq_err_dbg; + + sq_op_err_code = FIELD_GET(GENMASK(7, 0), sq_op_err_dbg); + netdev_err(pf->netdev, "SQ%lld: NIX_LF_SQ_OP_ERR_DBG(%llx) err=%s\n", + qidx, sq_op_err_dbg, nix_sqoperr_e_str[sq_op_err_code]); + + otx2_write64(pf, NIX_LF_SQ_OP_ERR_DBG, BIT_ULL(44)); + + if (sq_op_err_code == NIX_SQOPERR_SQB_NULL) + goto chk_mnq_err_dbg; + + /* Err is not NIX_SQOPERR_SQB_NULL, call aq function to read SQ structure. + * TODO: But we are in irq context. How to call mbox functions which does sleep + */ + +chk_mnq_err_dbg: + mnq_err_dbg = otx2_read64(pf, NIX_LF_MNQ_ERR_DBG); + if (!(mnq_err_dbg & BIT(44))) + goto chk_snd_err_dbg; + + mnq_err_code = FIELD_GET(GENMASK(7, 0), mnq_err_dbg); + netdev_err(pf->netdev, "SQ%lld: NIX_LF_MNQ_ERR_DBG(%llx) err=%s\n", + qidx, mnq_err_dbg, nix_mnqerr_e_str[mnq_err_code]); + otx2_write64(pf, NIX_LF_MNQ_ERR_DBG, BIT_ULL(44)); + +chk_snd_err_dbg: + snd_err_dbg = otx2_read64(pf, NIX_LF_SEND_ERR_DBG); + if (snd_err_dbg & BIT(44)) { + snd_err_code = FIELD_GET(GENMASK(7, 0), snd_err_dbg); + netdev_err(pf->netdev, "SQ%lld: NIX_LF_SND_ERR_DBG:0x%llx err=%s\n", + qidx, snd_err_dbg, nix_snd_status_e_str[snd_err_code]); + otx2_write64(pf, NIX_LF_SEND_ERR_DBG, BIT_ULL(44)); + } + +done: + /* Print values and reset */ + if (val & BIT_ULL(NIX_SQINT_SQB_ALLOC_FAIL)) + netdev_err(pf->netdev, "SQ%lld: SQB allocation failed", + qidx); + schedule_work(&pf->reset_task); } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h index aa205a0d158f..fa37b9f312ca 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h @@ -281,4 +281,61 @@ enum nix_sqint_e { BIT_ULL(NIX_SQINT_SEND_ERR) | \ BIT_ULL(NIX_SQINT_SQB_ALLOC_FAIL)) +enum nix_sqoperr_e { + NIX_SQOPERR_OOR = 0, + NIX_SQOPERR_CTX_FAULT = 1, + NIX_SQOPERR_CTX_POISON = 2, + NIX_SQOPERR_DISABLED = 3, + NIX_SQOPERR_SIZE_ERR = 4, + NIX_SQOPERR_OFLOW = 5, + NIX_SQOPERR_SQB_NULL = 6, + NIX_SQOPERR_SQB_FAULT = 7, + NIX_SQOPERR_SQE_SZ_ZERO = 8, + NIX_SQOPERR_MAX, +}; + +enum nix_mnqerr_e { + NIX_MNQERR_SQ_CTX_FAULT = 0, + NIX_MNQERR_SQ_CTX_POISON = 1, + NIX_MNQERR_SQB_FAULT = 2, + NIX_MNQERR_SQB_POISON = 3, + NIX_MNQERR_TOTAL_ERR = 4, + NIX_MNQERR_LSO_ERR = 5, + NIX_MNQERR_CQ_QUERY_ERR = 6, + NIX_MNQERR_MAX_SQE_SIZE_ERR = 7, + NIX_MNQERR_MAXLEN_ERR = 8, + NIX_MNQERR_SQE_SIZEM1_ZERO = 9, + NIX_MNQERR_MAX, +}; + +enum nix_snd_status_e { + NIX_SND_STATUS_GOOD = 0x0, + NIX_SND_STATUS_SQ_CTX_FAULT = 0x1, + NIX_SND_STATUS_SQ_CTX_POISON = 0x2, + NIX_SND_STATUS_SQB_FAULT = 0x3, + NIX_SND_STATUS_SQB_POISON = 0x4, + NIX_SND_STATUS_HDR_ERR = 0x5, + NIX_SND_STATUS_EXT_ERR = 0x6, + NIX_SND_STATUS_JUMP_FAULT = 0x7, + NIX_SND_STATUS_JUMP_POISON = 0x8, + NIX_SND_STATUS_CRC_ERR = 0x9, + NIX_SND_STATUS_IMM_ERR = 0x10, + NIX_SND_STATUS_SG_ERR = 0x11, + NIX_SND_STATUS_MEM_ERR = 0x12, + NIX_SND_STATUS_INVALID_SUBDC = 0x13, + NIX_SND_STATUS_SUBDC_ORDER_ERR = 0x14, + NIX_SND_STATUS_DATA_FAULT = 0x15, + NIX_SND_STATUS_DATA_POISON = 0x16, + NIX_SND_STATUS_NPC_DROP_ACTION = 0x17, + NIX_SND_STATUS_LOCK_VIOL = 0x18, + NIX_SND_STATUS_NPC_UCAST_CHAN_ERR = 0x19, + NIX_SND_STATUS_NPC_MCAST_CHAN_ERR = 0x20, + NIX_SND_STATUS_NPC_MCAST_ABORT = 0x21, + NIX_SND_STATUS_NPC_VTAG_PTR_ERR = 0x22, + NIX_SND_STATUS_NPC_VTAG_SIZE_ERR = 0x23, + NIX_SND_STATUS_SEND_MEM_FAULT = 0x24, + NIX_SND_STATUS_SEND_STATS_ERR = 0x25, + NIX_SND_STATUS_MAX, +}; + #endif /* OTX2_STRUCT_H */ -- cgit v1.2.3 From 1118b2049d77ca0b505775fc1a8d1909cf19a7ec Mon Sep 17 00:00:00 2001 From: Wang Yufen Date: Wed, 2 Nov 2022 17:41:19 +0800 Subject: net: tun: Fix memory leaks of napi_get_frags kmemleak reports after running test_progs: unreferenced object 0xffff8881b1672dc0 (size 232): comm "test_progs", pid 394388, jiffies 4354712116 (age 841.975s) hex dump (first 32 bytes): e0 84 d7 a8 81 88 ff ff 80 2c 67 b1 81 88 ff ff .........,g..... 00 40 c5 9b 81 88 ff ff 00 00 00 00 00 00 00 00 .@.............. backtrace: [<00000000c8f01748>] napi_skb_cache_get+0xd4/0x150 [<0000000041c7fc09>] __napi_build_skb+0x15/0x50 [<00000000431c7079>] __napi_alloc_skb+0x26e/0x540 [<000000003ecfa30e>] napi_get_frags+0x59/0x140 [<0000000099b2199e>] tun_get_user+0x183d/0x3bb0 [tun] [<000000008a5adef0>] tun_chr_write_iter+0xc0/0x1b1 [tun] [<0000000049993ff4>] do_iter_readv_writev+0x19f/0x320 [<000000008f338ea2>] do_iter_write+0x135/0x630 [<000000008a3377a4>] vfs_writev+0x12e/0x440 [<00000000a6b5639a>] do_writev+0x104/0x280 [<00000000ccf065d8>] do_syscall_64+0x3b/0x90 [<00000000d776e329>] entry_SYSCALL_64_after_hwframe+0x63/0xcd The issue occurs in the following scenarios: tun_get_user() napi_gro_frags() napi_frags_finish() case GRO_NORMAL: gro_normal_one() list_add_tail(&skb->list, &napi->rx_list); <-- While napi->rx_count < READ_ONCE(gro_normal_batch), <-- gro_normal_list() is not called, napi->rx_list is not empty <-- not ask to complete the gro work, will cause memory leaks in <-- following tun_napi_del() ... tun_napi_del() netif_napi_del() __netif_napi_del() <-- &napi->rx_list is not empty, which caused memory leaks To fix, add napi_complete() after napi_gro_frags(). Fixes: 90e33d459407 ("tun: enable napi_gro_frags() for TUN/TAP driver") Signed-off-by: Wang Yufen Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/tun.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 946628050f28..eb12f3136a54 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1977,6 +1977,7 @@ drop: local_bh_disable(); napi_gro_frags(&tfile->napi); + napi_complete(&tfile->napi); local_bh_enable(); mutex_unlock(&tfile->napi_mutex); } else if (tfile->napi_enabled) { -- cgit v1.2.3 From bff6bef701db784bb159a659e99c785b4594fc96 Mon Sep 17 00:00:00 2001 From: Vitaly Rodionov Date: Fri, 4 Nov 2022 10:06:37 +0000 Subject: spi: amd: Fix SPI_SPD7 value According to data sheet SPI_SPD7 should be set to 7. Signed-off-by: Vitaly Rodionov Link: https://lore.kernel.org/r/20221104100637.13376-1-vitalyr@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/spi/spi-amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c index e23121456c70..bfc3ab5f39ea 100644 --- a/drivers/spi/spi-amd.c +++ b/drivers/spi/spi-amd.c @@ -65,7 +65,7 @@ enum amd_spi_speed { F_16_66MHz, F_100MHz, F_800KHz, - SPI_SPD7, + SPI_SPD7 = 0x7, F_50MHz = 0x4, F_4MHz = 0x32, F_3_17MHz = 0x3F -- cgit v1.2.3 From 6f7de35b50860c345babf8ed0aa0d75f9315eee4 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 28 Oct 2022 14:06:35 +0100 Subject: drm/i915/userptr: restore probe_range behaviour The conversion looks harmless, however the addr value is updated inside the loop with the previous vm_end, which then incorrectly leads to for_each_vma_range() iterating over stuff outside the range we care about. Fix this by storing the end value separately. Also fix the case where the range doesn't intersect with any vma, or if the vma itself doesn't extend the entire range, which must mean we have hole at the end. Both should result in an error, as per the previous behaviour. v2: Fix the cases where the range is empty, or if there's a hole at the end of the range Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/7247 Testcase: igt@gem_userptr_blits@probe Fixes: f683b9d61319 ("i915: use the VMA iterator") Reported-by: kernel test robot Signed-off-by: Matthew Auld Cc: Tvrtko Ursulin Cc: Matthew Wilcox (Oracle) Cc: Liam R. Howlett Cc: Vlastimil Babka Cc: Yu Zhao Reviewed-by: Liam R. Howlett Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/20221028130635.465839-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index 1b1a22716722..ca7a388ba2bf 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -427,9 +427,10 @@ probe_range(struct mm_struct *mm, unsigned long addr, unsigned long len) { VMA_ITERATOR(vmi, mm, addr); struct vm_area_struct *vma; + unsigned long end = addr + len; mmap_read_lock(mm); - for_each_vma_range(vmi, vma, addr + len) { + for_each_vma_range(vmi, vma, end) { /* Check for holes, note that we also update the addr below */ if (vma->vm_start > addr) break; @@ -441,7 +442,7 @@ probe_range(struct mm_struct *mm, unsigned long addr, unsigned long len) } mmap_read_unlock(mm); - if (vma) + if (vma || addr < end) return -EFAULT; return 0; } -- cgit v1.2.3 From 6e59419fd0a244dd55e53e798797f0697dec8b1c Mon Sep 17 00:00:00 2001 From: Peng Wu Date: Sun, 11 Sep 2022 06:00:53 +0000 Subject: phy: sunplus: Fix an IS_ERR() vs NULL bug in sp_usb_phy_probe The devm_ioremap() function returns NULL on error, it doesn't return error pointers. Fixes: 99d9ccd973852 ("phy: usb: Add USB2.0 phy driver for Sunplus SP7021") Signed-off-by: Peng Wu Link: https://lore.kernel.org/r/20220911060053.123594-1-wupeng58@huawei.com Signed-off-by: Vinod Koul --- drivers/phy/sunplus/phy-sunplus-usb2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/sunplus/phy-sunplus-usb2.c b/drivers/phy/sunplus/phy-sunplus-usb2.c index b932087c55b2..e827b79f6d49 100644 --- a/drivers/phy/sunplus/phy-sunplus-usb2.c +++ b/drivers/phy/sunplus/phy-sunplus-usb2.c @@ -256,8 +256,8 @@ static int sp_usb_phy_probe(struct platform_device *pdev) usbphy->moon4_res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "moon4"); usbphy->moon4_regs = devm_ioremap(&pdev->dev, usbphy->moon4_res_mem->start, resource_size(usbphy->moon4_res_mem)); - if (IS_ERR(usbphy->moon4_regs)) - return PTR_ERR(usbphy->moon4_regs); + if (!usbphy->moon4_regs) + return -ENOMEM; usbphy->phy_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(usbphy->phy_clk)) -- cgit v1.2.3 From cc2e0cf0ad47db7f51283e5c9bd2212a994ad527 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 31 Oct 2022 15:00:07 -0700 Subject: drm/i915/guc: Remove excessive line feeds in state dumps Some of the GuC state dump messages were adding extra line feeds. When printing via a DRM printer to dmesg, for example, that messes up the log formatting as it loses any prefixing from the printer. Given that the extra line feeds are just in the middle of random bits of GuC state, there isn't any real need for them. So just remove them completely. Signed-off-by: John Harrison Reviewed-by: Umesh Nerlige Ramappa Link: https://patchwork.freedesktop.org/patch/msgid/20221031220007.4176835-1-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 4 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 27b09ba1d295..1bcd61bb50f8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -871,14 +871,14 @@ void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p) u32 status = intel_uncore_read(uncore, GUC_STATUS); u32 i; - drm_printf(p, "\nGuC status 0x%08x:\n", status); + drm_printf(p, "GuC status 0x%08x:\n", status); drm_printf(p, "\tBootrom status = 0x%x\n", (status & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT); drm_printf(p, "\tuKernel status = 0x%x\n", (status & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT); drm_printf(p, "\tMIA Core status = 0x%x\n", (status & GS_MIA_MASK) >> GS_MIA_SHIFT); - drm_puts(p, "\nScratch registers:\n"); + drm_puts(p, "Scratch registers:\n"); for (i = 0; i < 16; i++) { drm_printf(p, "\t%2d: \t0x%x\n", i, intel_uncore_read(uncore, SOFT_SCRATCH(i))); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 4ccb29f9ac55..4dbdac8002e3 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4901,7 +4901,7 @@ void intel_guc_submission_print_info(struct intel_guc *guc, drm_printf(p, "GuC Number Outstanding Submission G2H: %u\n", atomic_read(&guc->outstanding_submission_g2h)); - drm_printf(p, "GuC tasklet count: %u\n\n", + drm_printf(p, "GuC tasklet count: %u\n", atomic_read(&sched_engine->tasklet.count)); spin_lock_irqsave(&sched_engine->lock, flags); @@ -4949,7 +4949,7 @@ static inline void guc_log_context(struct drm_printer *p, atomic_read(&ce->pin_count)); drm_printf(p, "\t\tGuC ID Ref Count: %u\n", atomic_read(&ce->guc_id.ref)); - drm_printf(p, "\t\tSchedule State: 0x%x\n\n", + drm_printf(p, "\t\tSchedule State: 0x%x\n", ce->guc_state.sched_state); } @@ -4978,7 +4978,7 @@ void intel_guc_submission_print_context_info(struct intel_guc *guc, READ_ONCE(*ce->parallel.guc.wq_head)); drm_printf(p, "\t\tWQI Tail: %u\n", READ_ONCE(*ce->parallel.guc.wq_tail)); - drm_printf(p, "\t\tWQI Status: %u\n\n", + drm_printf(p, "\t\tWQI Status: %u\n", READ_ONCE(*ce->parallel.guc.wq_status)); } @@ -4986,7 +4986,7 @@ void intel_guc_submission_print_context_info(struct intel_guc *guc, emit_bb_start_parent_no_preempt_mid_batch) { u8 i; - drm_printf(p, "\t\tChildren Go: %u\n\n", + drm_printf(p, "\t\tChildren Go: %u\n", get_children_go_value(ce)); for (i = 0; i < ce->parallel.number_children; ++i) drm_printf(p, "\t\tChildren Join: %u\n", -- cgit v1.2.3 From 403cea4019e206130b5a90f6d34383005d17b54a Mon Sep 17 00:00:00 2001 From: Jay Cornwall Date: Thu, 13 Oct 2022 21:41:13 -0500 Subject: drm/amdkfd: update GFX11 CWSR trap handler With corresponding FW change fixes issue where triggering CWSR on a workgroup with waves in s_barrier wouldn't lead to a back-off and therefore cause a hang. Signed-off-by: Jay Cornwall Tested-by: Graham Sider Acked-by: Harish Kasiviswanathan Acked-by: Felix Kuehling Reviewed-by: Graham Sider Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 764 +++++++++++---------- .../gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm | 6 + 2 files changed, 389 insertions(+), 381 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index c7118843db05..0c4c5499bb5c 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -2495,442 +2495,444 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xbf9f0000, 0x00000000, }; static const uint32_t cwsr_trap_gfx11_hex[] = { - 0xbfa00001, 0xbfa0021e, + 0xbfa00001, 0xbfa00221, 0xb0804006, 0xb8f8f802, 0x9178ff78, 0x00020006, - 0xb8fbf803, 0xbf0d9f6d, - 0xbfa20006, 0x8b6eff78, - 0x00002000, 0xbfa10009, - 0x8b6eff6d, 0x00ff0000, - 0xbfa2001e, 0x8b6eff7b, - 0x00000400, 0xbfa20041, - 0xbf830010, 0xb8fbf803, - 0xbfa0fffa, 0x8b6eff7b, - 0x00000900, 0xbfa20015, - 0x8b6eff7b, 0x000071ff, - 0xbfa10008, 0x8b6fff7b, - 0x00007080, 0xbfa10001, - 0xbeee1287, 0xb8eff801, - 0x846e8c6e, 0x8b6e6f6e, - 0xbfa2000a, 0x8b6eff6d, - 0x00ff0000, 0xbfa20007, - 0xb8eef801, 0x8b6eff6e, - 0x00000800, 0xbfa20003, + 0xb8fbf803, 0xbf0d9e6d, + 0xbfa10001, 0xbfbd0000, + 0xbf0d9f6d, 0xbfa20006, + 0x8b6eff78, 0x00002000, + 0xbfa10009, 0x8b6eff6d, + 0x00ff0000, 0xbfa2001e, 0x8b6eff7b, 0x00000400, - 0xbfa20026, 0xbefa4d82, - 0xbf89fc07, 0x84fa887a, - 0xf4005bbd, 0xf8000010, - 0xbf89fc07, 0x846e976e, - 0x9177ff77, 0x00800000, - 0x8c776e77, 0xf4045bbd, - 0xf8000000, 0xbf89fc07, - 0xf4045ebd, 0xf8000008, - 0xbf89fc07, 0x8bee6e6e, - 0xbfa10001, 0xbe80486e, - 0x8b6eff6d, 0x01ff0000, - 0xbfa20005, 0x8c78ff78, - 0x00002000, 0x80ec886c, - 0x82ed806d, 0xbfa00005, - 0x8b6eff6d, 0x01000000, - 0xbfa20002, 0x806c846c, - 0x826d806d, 0x8b6dff6d, - 0x0000ffff, 0x8bfe7e7e, - 0x8bea6a6a, 0xb978f802, - 0xbe804a6c, 0x8b6dff6d, - 0x0000ffff, 0xbefa0080, - 0xb97a0283, 0xbeee007e, - 0xbeef007f, 0xbefe0180, - 0xbefe4d84, 0xbf89fc07, - 0x8b7aff7f, 0x04000000, - 0x847a857a, 0x8c6d7a6d, - 0xbefa007e, 0x8b7bff7f, - 0x0000ffff, 0xbefe00c1, - 0xbeff00c1, 0xdca6c000, - 0x007a0000, 0x7e000280, - 0xbefe007a, 0xbeff007b, - 0xb8fb02dc, 0x847b997b, - 0xb8fa3b05, 0x807a817a, - 0xbf0d997b, 0xbfa20002, - 0x847a897a, 0xbfa00001, - 0x847a8a7a, 0xb8fb1e06, - 0x847b8a7b, 0x807a7b7a, + 0xbfa20041, 0xbf830010, + 0xb8fbf803, 0xbfa0fffa, + 0x8b6eff7b, 0x00000900, + 0xbfa20015, 0x8b6eff7b, + 0x000071ff, 0xbfa10008, + 0x8b6fff7b, 0x00007080, + 0xbfa10001, 0xbeee1287, + 0xb8eff801, 0x846e8c6e, + 0x8b6e6f6e, 0xbfa2000a, + 0x8b6eff6d, 0x00ff0000, + 0xbfa20007, 0xb8eef801, + 0x8b6eff6e, 0x00000800, + 0xbfa20003, 0x8b6eff7b, + 0x00000400, 0xbfa20026, + 0xbefa4d82, 0xbf89fc07, + 0x84fa887a, 0xf4005bbd, + 0xf8000010, 0xbf89fc07, + 0x846e976e, 0x9177ff77, + 0x00800000, 0x8c776e77, + 0xf4045bbd, 0xf8000000, + 0xbf89fc07, 0xf4045ebd, + 0xf8000008, 0xbf89fc07, + 0x8bee6e6e, 0xbfa10001, + 0xbe80486e, 0x8b6eff6d, + 0x01ff0000, 0xbfa20005, + 0x8c78ff78, 0x00002000, + 0x80ec886c, 0x82ed806d, + 0xbfa00005, 0x8b6eff6d, + 0x01000000, 0xbfa20002, + 0x806c846c, 0x826d806d, + 0x8b6dff6d, 0x0000ffff, + 0x8bfe7e7e, 0x8bea6a6a, + 0xb978f802, 0xbe804a6c, + 0x8b6dff6d, 0x0000ffff, + 0xbefa0080, 0xb97a0283, + 0xbeee007e, 0xbeef007f, + 0xbefe0180, 0xbefe4d84, + 0xbf89fc07, 0x8b7aff7f, + 0x04000000, 0x847a857a, + 0x8c6d7a6d, 0xbefa007e, 0x8b7bff7f, 0x0000ffff, - 0x807aff7a, 0x00000200, - 0x807a7e7a, 0x827b807b, - 0xd7610000, 0x00010870, - 0xd7610000, 0x00010a71, - 0xd7610000, 0x00010c72, - 0xd7610000, 0x00010e73, - 0xd7610000, 0x00011074, - 0xd7610000, 0x00011275, - 0xd7610000, 0x00011476, - 0xd7610000, 0x00011677, - 0xd7610000, 0x00011a79, - 0xd7610000, 0x00011c7e, - 0xd7610000, 0x00011e7f, - 0xbefe00ff, 0x00003fff, - 0xbeff0080, 0xdca6c040, - 0x007a0000, 0xd760007a, - 0x00011d00, 0xd760007b, - 0x00011f00, 0xbefe007a, - 0xbeff007b, 0xbef4007e, - 0x8b75ff7f, 0x0000ffff, - 0x8c75ff75, 0x00040000, - 0xbef60080, 0xbef700ff, - 0x10807fac, 0xbef1007d, - 0xbef00080, 0xb8f302dc, - 0x84739973, 0xbefe00c1, - 0x857d9973, 0x8b7d817d, - 0xbf06817d, 0xbfa20002, - 0xbeff0080, 0xbfa00002, - 0xbeff00c1, 0xbfa00009, + 0xbefe00c1, 0xbeff00c1, + 0xdca6c000, 0x007a0000, + 0x7e000280, 0xbefe007a, + 0xbeff007b, 0xb8fb02dc, + 0x847b997b, 0xb8fa3b05, + 0x807a817a, 0xbf0d997b, + 0xbfa20002, 0x847a897a, + 0xbfa00001, 0x847a8a7a, + 0xb8fb1e06, 0x847b8a7b, + 0x807a7b7a, 0x8b7bff7f, + 0x0000ffff, 0x807aff7a, + 0x00000200, 0x807a7e7a, + 0x827b807b, 0xd7610000, + 0x00010870, 0xd7610000, + 0x00010a71, 0xd7610000, + 0x00010c72, 0xd7610000, + 0x00010e73, 0xd7610000, + 0x00011074, 0xd7610000, + 0x00011275, 0xd7610000, + 0x00011476, 0xd7610000, + 0x00011677, 0xd7610000, + 0x00011a79, 0xd7610000, + 0x00011c7e, 0xd7610000, + 0x00011e7f, 0xbefe00ff, + 0x00003fff, 0xbeff0080, + 0xdca6c040, 0x007a0000, + 0xd760007a, 0x00011d00, + 0xd760007b, 0x00011f00, + 0xbefe007a, 0xbeff007b, + 0xbef4007e, 0x8b75ff7f, + 0x0000ffff, 0x8c75ff75, + 0x00040000, 0xbef60080, + 0xbef700ff, 0x10807fac, + 0xbef1007d, 0xbef00080, + 0xb8f302dc, 0x84739973, + 0xbefe00c1, 0x857d9973, + 0x8b7d817d, 0xbf06817d, + 0xbfa20002, 0xbeff0080, + 0xbfa00002, 0xbeff00c1, + 0xbfa00009, 0xbef600ff, + 0x01000000, 0xe0685080, + 0x701d0100, 0xe0685100, + 0x701d0200, 0xe0685180, + 0x701d0300, 0xbfa00008, 0xbef600ff, 0x01000000, - 0xe0685080, 0x701d0100, - 0xe0685100, 0x701d0200, - 0xe0685180, 0x701d0300, - 0xbfa00008, 0xbef600ff, - 0x01000000, 0xe0685100, - 0x701d0100, 0xe0685200, - 0x701d0200, 0xe0685300, - 0x701d0300, 0xb8f03b05, - 0x80708170, 0xbf0d9973, - 0xbfa20002, 0x84708970, - 0xbfa00001, 0x84708a70, - 0xb8fa1e06, 0x847a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0xbef600ff, - 0x01000000, 0x7e000280, - 0x7e020280, 0x7e040280, - 0xbefd0080, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xd7610002, 0x0000fa6c, - 0x807d817d, 0x917aff6d, - 0x80000000, 0xd7610002, - 0x0000fa7a, 0x807d817d, - 0xd7610002, 0x0000fa6e, - 0x807d817d, 0xd7610002, - 0x0000fa6f, 0x807d817d, - 0xd7610002, 0x0000fa78, - 0x807d817d, 0xb8faf803, - 0xd7610002, 0x0000fa7a, - 0x807d817d, 0xd7610002, - 0x0000fa7b, 0x807d817d, - 0xb8f1f801, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xb8f1f814, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xb8f1f815, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xbefe00ff, 0x0000ffff, - 0xbeff0080, 0xe0685000, - 0x701d0200, 0xbefe00c1, + 0xe0685100, 0x701d0100, + 0xe0685200, 0x701d0200, + 0xe0685300, 0x701d0300, 0xb8f03b05, 0x80708170, 0xbf0d9973, 0xbfa20002, 0x84708970, 0xbfa00001, 0x84708a70, 0xb8fa1e06, 0x847a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, 0xbef600ff, 0x01000000, - 0xbef90080, 0xbefd0080, - 0xbf800000, 0xbe804100, - 0xbe824102, 0xbe844104, - 0xbe864106, 0xbe884108, - 0xbe8a410a, 0xbe8c410c, - 0xbe8e410e, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0x7e000280, 0x7e020280, + 0x7e040280, 0xbefd0080, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xd7610002, + 0x0000fa6c, 0x807d817d, + 0x917aff6d, 0x80000000, + 0xd7610002, 0x0000fa7a, + 0x807d817d, 0xd7610002, + 0x0000fa6e, 0x807d817d, + 0xd7610002, 0x0000fa6f, + 0x807d817d, 0xd7610002, + 0x0000fa78, 0x807d817d, + 0xb8faf803, 0xd7610002, + 0x0000fa7a, 0x807d817d, + 0xd7610002, 0x0000fa7b, + 0x807d817d, 0xb8f1f801, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xb8f1f814, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xb8f1f815, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xbefe00ff, + 0x0000ffff, 0xbeff0080, + 0xe0685000, 0x701d0200, + 0xbefe00c1, 0xb8f03b05, + 0x80708170, 0xbf0d9973, + 0xbfa20002, 0x84708970, + 0xbfa00001, 0x84708a70, + 0xb8fa1e06, 0x847a8a7a, + 0x80707a70, 0xbef600ff, + 0x01000000, 0xbef90080, + 0xbefd0080, 0xbf800000, + 0xbe804100, 0xbe824102, + 0xbe844104, 0xbe864106, + 0xbe884108, 0xbe8a410a, + 0xbe8c410c, 0xbe8e410e, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, 0x80798179, 0xd7610002, - 0x0000f20c, 0x80798179, - 0xd7610002, 0x0000f20d, + 0x0000f20b, 0x80798179, + 0xd7610002, 0x0000f20c, 0x80798179, 0xd7610002, - 0x0000f20e, 0x80798179, - 0xd7610002, 0x0000f20f, - 0x80798179, 0xbf06a079, - 0xbfa10006, 0xe0685000, - 0x701d0200, 0x8070ff70, - 0x00000080, 0xbef90080, - 0x7e040280, 0x807d907d, - 0xbf0aff7d, 0x00000060, - 0xbfa2ffbc, 0xbe804100, - 0xbe824102, 0xbe844104, - 0xbe864106, 0xbe884108, - 0xbe8a410a, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0x0000f20d, 0x80798179, + 0xd7610002, 0x0000f20e, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f20f, 0x80798179, + 0xbf06a079, 0xbfa10006, + 0xe0685000, 0x701d0200, + 0x8070ff70, 0x00000080, + 0xbef90080, 0x7e040280, + 0x807d907d, 0xbf0aff7d, + 0x00000060, 0xbfa2ffbc, + 0xbe804100, 0xbe824102, + 0xbe844104, 0xbe864106, + 0xbe884108, 0xbe8a410a, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, - 0x80798179, 0xe0685000, - 0x701d0200, 0xbefe00c1, - 0x857d9973, 0x8b7d817d, - 0xbf06817d, 0xbfa20002, - 0xbeff0080, 0xbfa00001, - 0xbeff00c1, 0xb8fb4306, - 0x8b7bc17b, 0xbfa10044, - 0xbfbd0000, 0x8b7aff6d, - 0x80000000, 0xbfa10040, - 0x847b867b, 0x847b827b, - 0xbef6007b, 0xb8f03b05, - 0x80708170, 0xbf0d9973, - 0xbfa20002, 0x84708970, - 0xbfa00001, 0x84708a70, - 0xb8fa1e06, 0x847a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0x8070ff70, - 0x00000080, 0xbef600ff, - 0x01000000, 0xd71f0000, - 0x000100c1, 0xd7200000, - 0x000200c1, 0x16000084, - 0x857d9973, 0x8b7d817d, - 0xbf06817d, 0xbefd0080, - 0xbfa20012, 0xbe8300ff, - 0x00000080, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf890000, 0xe0685000, - 0x701d0100, 0x807d037d, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000080, - 0xbf0a7b7d, 0xbfa2fff4, - 0xbfa00011, 0xbe8300ff, - 0x00000100, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf890000, 0xe0685000, - 0x701d0100, 0x807d037d, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000100, - 0xbf0a7b7d, 0xbfa2fff4, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, + 0x80798179, 0xd7610002, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, + 0x80798179, 0xd7610002, + 0x0000f20b, 0x80798179, + 0xe0685000, 0x701d0200, 0xbefe00c1, 0x857d9973, 0x8b7d817d, 0xbf06817d, - 0xbfa20004, 0xbef000ff, - 0x00000200, 0xbeff0080, - 0xbfa00003, 0xbef000ff, - 0x00000400, 0xbeff00c1, - 0xb8fb3b05, 0x807b817b, - 0x847b827b, 0x857d9973, + 0xbfa20002, 0xbeff0080, + 0xbfa00001, 0xbeff00c1, + 0xb8fb4306, 0x8b7bc17b, + 0xbfa10044, 0xbfbd0000, + 0x8b7aff6d, 0x80000000, + 0xbfa10040, 0x847b867b, + 0x847b827b, 0xbef6007b, + 0xb8f03b05, 0x80708170, + 0xbf0d9973, 0xbfa20002, + 0x84708970, 0xbfa00001, + 0x84708a70, 0xb8fa1e06, + 0x847a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000080, + 0xbef600ff, 0x01000000, + 0xd71f0000, 0x000100c1, + 0xd7200000, 0x000200c1, + 0x16000084, 0x857d9973, 0x8b7d817d, 0xbf06817d, - 0xbfa20017, 0xbef600ff, - 0x01000000, 0xbefd0084, - 0xbf0a7b7d, 0xbfa10037, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, - 0xe0685000, 0x701d0000, - 0xe0685080, 0x701d0100, - 0xe0685100, 0x701d0200, - 0xe0685180, 0x701d0300, - 0x807d847d, 0x8070ff70, - 0x00000200, 0xbf0a7b7d, - 0xbfa2ffef, 0xbfa00025, + 0xbefd0080, 0xbfa20012, + 0xbe8300ff, 0x00000080, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf890000, + 0xe0685000, 0x701d0100, + 0x807d037d, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000080, 0xbf0a7b7d, + 0xbfa2fff4, 0xbfa00011, + 0xbe8300ff, 0x00000100, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf890000, + 0xe0685000, 0x701d0100, + 0x807d037d, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000100, 0xbf0a7b7d, + 0xbfa2fff4, 0xbefe00c1, + 0x857d9973, 0x8b7d817d, + 0xbf06817d, 0xbfa20004, + 0xbef000ff, 0x00000200, + 0xbeff0080, 0xbfa00003, + 0xbef000ff, 0x00000400, + 0xbeff00c1, 0xb8fb3b05, + 0x807b817b, 0x847b827b, + 0x857d9973, 0x8b7d817d, + 0xbf06817d, 0xbfa20017, 0xbef600ff, 0x01000000, 0xbefd0084, 0xbf0a7b7d, - 0xbfa10011, 0x7e008700, + 0xbfa10037, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0685000, - 0x701d0000, 0xe0685100, - 0x701d0100, 0xe0685200, - 0x701d0200, 0xe0685300, + 0x701d0000, 0xe0685080, + 0x701d0100, 0xe0685100, + 0x701d0200, 0xe0685180, 0x701d0300, 0x807d847d, - 0x8070ff70, 0x00000400, + 0x8070ff70, 0x00000200, 0xbf0a7b7d, 0xbfa2ffef, - 0xb8fb1e06, 0x8b7bc17b, - 0xbfa1000c, 0x847b837b, - 0x807b7d7b, 0xbefe00c1, - 0xbeff0080, 0x7e008700, + 0xbfa00025, 0xbef600ff, + 0x01000000, 0xbefd0084, + 0xbf0a7b7d, 0xbfa10011, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, 0xe0685000, 0x701d0000, - 0x807d817d, 0x8070ff70, - 0x00000080, 0xbf0a7b7d, - 0xbfa2fff8, 0xbfa00146, - 0xbef4007e, 0x8b75ff7f, - 0x0000ffff, 0x8c75ff75, - 0x00040000, 0xbef60080, - 0xbef700ff, 0x10807fac, - 0xb8f202dc, 0x84729972, - 0x8b6eff7f, 0x04000000, - 0xbfa1003a, 0xbefe00c1, - 0x857d9972, 0x8b7d817d, - 0xbf06817d, 0xbfa20002, - 0xbeff0080, 0xbfa00001, - 0xbeff00c1, 0xb8ef4306, - 0x8b6fc16f, 0xbfa1002f, - 0x846f866f, 0x846f826f, - 0xbef6006f, 0xb8f83b05, - 0x80788178, 0xbf0d9972, - 0xbfa20002, 0x84788978, - 0xbfa00001, 0x84788a78, - 0xb8ee1e06, 0x846e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x8078ff78, - 0x00000080, 0xbef600ff, - 0x01000000, 0x857d9972, - 0x8b7d817d, 0xbf06817d, - 0xbefd0080, 0xbfa2000c, - 0xe0500000, 0x781d0000, - 0xbf8903f7, 0xdac00000, - 0x00000000, 0x807dff7d, - 0x00000080, 0x8078ff78, - 0x00000080, 0xbf0a6f7d, - 0xbfa2fff5, 0xbfa0000b, - 0xe0500000, 0x781d0000, - 0xbf8903f7, 0xdac00000, - 0x00000000, 0x807dff7d, - 0x00000100, 0x8078ff78, - 0x00000100, 0xbf0a6f7d, - 0xbfa2fff5, 0xbef80080, + 0xe0685100, 0x701d0100, + 0xe0685200, 0x701d0200, + 0xe0685300, 0x701d0300, + 0x807d847d, 0x8070ff70, + 0x00000400, 0xbf0a7b7d, + 0xbfa2ffef, 0xb8fb1e06, + 0x8b7bc17b, 0xbfa1000c, + 0x847b837b, 0x807b7d7b, + 0xbefe00c1, 0xbeff0080, + 0x7e008700, 0xe0685000, + 0x701d0000, 0x807d817d, + 0x8070ff70, 0x00000080, + 0xbf0a7b7d, 0xbfa2fff8, + 0xbfa00146, 0xbef4007e, + 0x8b75ff7f, 0x0000ffff, + 0x8c75ff75, 0x00040000, + 0xbef60080, 0xbef700ff, + 0x10807fac, 0xb8f202dc, + 0x84729972, 0x8b6eff7f, + 0x04000000, 0xbfa1003a, 0xbefe00c1, 0x857d9972, 0x8b7d817d, 0xbf06817d, 0xbfa20002, 0xbeff0080, 0xbfa00001, 0xbeff00c1, - 0xb8ef3b05, 0x806f816f, - 0x846f826f, 0x857d9972, - 0x8b7d817d, 0xbf06817d, - 0xbfa20024, 0xbef600ff, - 0x01000000, 0xbeee0078, + 0xb8ef4306, 0x8b6fc16f, + 0xbfa1002f, 0x846f866f, + 0x846f826f, 0xbef6006f, + 0xb8f83b05, 0x80788178, + 0xbf0d9972, 0xbfa20002, + 0x84788978, 0xbfa00001, + 0x84788a78, 0xb8ee1e06, + 0x846e8a6e, 0x80786e78, 0x8078ff78, 0x00000200, - 0xbefd0084, 0xbf0a6f7d, - 0xbfa10050, 0xe0505000, - 0x781d0000, 0xe0505080, - 0x781d0100, 0xe0505100, - 0x781d0200, 0xe0505180, - 0x781d0300, 0xbf8903f7, - 0x7e008500, 0x7e028501, - 0x7e048502, 0x7e068503, - 0x807d847d, 0x8078ff78, - 0x00000200, 0xbf0a6f7d, - 0xbfa2ffee, 0xe0505000, - 0x6e1d0000, 0xe0505080, - 0x6e1d0100, 0xe0505100, - 0x6e1d0200, 0xe0505180, - 0x6e1d0300, 0xbf8903f7, - 0xbfa00034, 0xbef600ff, - 0x01000000, 0xbeee0078, - 0x8078ff78, 0x00000400, - 0xbefd0084, 0xbf0a6f7d, - 0xbfa10012, 0xe0505000, - 0x781d0000, 0xe0505100, - 0x781d0100, 0xe0505200, - 0x781d0200, 0xe0505300, - 0x781d0300, 0xbf8903f7, - 0x7e008500, 0x7e028501, - 0x7e048502, 0x7e068503, - 0x807d847d, 0x8078ff78, - 0x00000400, 0xbf0a6f7d, - 0xbfa2ffee, 0xb8ef1e06, - 0x8b6fc16f, 0xbfa1000e, - 0x846f836f, 0x806f7d6f, - 0xbefe00c1, 0xbeff0080, + 0x8078ff78, 0x00000080, + 0xbef600ff, 0x01000000, + 0x857d9972, 0x8b7d817d, + 0xbf06817d, 0xbefd0080, + 0xbfa2000c, 0xe0500000, + 0x781d0000, 0xbf8903f7, + 0xdac00000, 0x00000000, + 0x807dff7d, 0x00000080, + 0x8078ff78, 0x00000080, + 0xbf0a6f7d, 0xbfa2fff5, + 0xbfa0000b, 0xe0500000, + 0x781d0000, 0xbf8903f7, + 0xdac00000, 0x00000000, + 0x807dff7d, 0x00000100, + 0x8078ff78, 0x00000100, + 0xbf0a6f7d, 0xbfa2fff5, + 0xbef80080, 0xbefe00c1, + 0x857d9972, 0x8b7d817d, + 0xbf06817d, 0xbfa20002, + 0xbeff0080, 0xbfa00001, + 0xbeff00c1, 0xb8ef3b05, + 0x806f816f, 0x846f826f, + 0x857d9972, 0x8b7d817d, + 0xbf06817d, 0xbfa20024, + 0xbef600ff, 0x01000000, + 0xbeee0078, 0x8078ff78, + 0x00000200, 0xbefd0084, + 0xbf0a6f7d, 0xbfa10050, 0xe0505000, 0x781d0000, + 0xe0505080, 0x781d0100, + 0xe0505100, 0x781d0200, + 0xe0505180, 0x781d0300, 0xbf8903f7, 0x7e008500, - 0x807d817d, 0x8078ff78, - 0x00000080, 0xbf0a6f7d, - 0xbfa2fff7, 0xbeff00c1, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807d847d, + 0x8078ff78, 0x00000200, + 0xbf0a6f7d, 0xbfa2ffee, 0xe0505000, 0x6e1d0000, - 0xe0505100, 0x6e1d0100, - 0xe0505200, 0x6e1d0200, - 0xe0505300, 0x6e1d0300, - 0xbf8903f7, 0xb8f83b05, - 0x80788178, 0xbf0d9972, - 0xbfa20002, 0x84788978, - 0xbfa00001, 0x84788a78, - 0xb8ee1e06, 0x846e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x80f8ff78, - 0x00000050, 0xbef600ff, - 0x01000000, 0xbefd00ff, - 0x0000006c, 0x80f89078, - 0xf428403a, 0xf0000000, - 0xbf89fc07, 0x80fd847d, - 0xbf800000, 0xbe804300, - 0xbe824302, 0x80f8a078, - 0xf42c403a, 0xf0000000, - 0xbf89fc07, 0x80fd887d, - 0xbf800000, 0xbe804300, - 0xbe824302, 0xbe844304, - 0xbe864306, 0x80f8c078, - 0xf430403a, 0xf0000000, - 0xbf89fc07, 0x80fd907d, - 0xbf800000, 0xbe804300, - 0xbe824302, 0xbe844304, - 0xbe864306, 0xbe884308, - 0xbe8a430a, 0xbe8c430c, - 0xbe8e430e, 0xbf06807d, - 0xbfa1fff0, 0xb980f801, - 0x00000000, 0xbfbd0000, + 0xe0505080, 0x6e1d0100, + 0xe0505100, 0x6e1d0200, + 0xe0505180, 0x6e1d0300, + 0xbf8903f7, 0xbfa00034, + 0xbef600ff, 0x01000000, + 0xbeee0078, 0x8078ff78, + 0x00000400, 0xbefd0084, + 0xbf0a6f7d, 0xbfa10012, + 0xe0505000, 0x781d0000, + 0xe0505100, 0x781d0100, + 0xe0505200, 0x781d0200, + 0xe0505300, 0x781d0300, + 0xbf8903f7, 0x7e008500, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807d847d, + 0x8078ff78, 0x00000400, + 0xbf0a6f7d, 0xbfa2ffee, + 0xb8ef1e06, 0x8b6fc16f, + 0xbfa1000e, 0x846f836f, + 0x806f7d6f, 0xbefe00c1, + 0xbeff0080, 0xe0505000, + 0x781d0000, 0xbf8903f7, + 0x7e008500, 0x807d817d, + 0x8078ff78, 0x00000080, + 0xbf0a6f7d, 0xbfa2fff7, + 0xbeff00c1, 0xe0505000, + 0x6e1d0000, 0xe0505100, + 0x6e1d0100, 0xe0505200, + 0x6e1d0200, 0xe0505300, + 0x6e1d0300, 0xbf8903f7, 0xb8f83b05, 0x80788178, 0xbf0d9972, 0xbfa20002, 0x84788978, 0xbfa00001, 0x84788a78, 0xb8ee1e06, 0x846e8a6e, 0x80786e78, 0x8078ff78, 0x00000200, + 0x80f8ff78, 0x00000050, 0xbef600ff, 0x01000000, - 0xf4205bfa, 0xf0000000, - 0x80788478, 0xf4205b3a, + 0xbefd00ff, 0x0000006c, + 0x80f89078, 0xf428403a, + 0xf0000000, 0xbf89fc07, + 0x80fd847d, 0xbf800000, + 0xbe804300, 0xbe824302, + 0x80f8a078, 0xf42c403a, + 0xf0000000, 0xbf89fc07, + 0x80fd887d, 0xbf800000, + 0xbe804300, 0xbe824302, + 0xbe844304, 0xbe864306, + 0x80f8c078, 0xf430403a, + 0xf0000000, 0xbf89fc07, + 0x80fd907d, 0xbf800000, + 0xbe804300, 0xbe824302, + 0xbe844304, 0xbe864306, + 0xbe884308, 0xbe8a430a, + 0xbe8c430c, 0xbe8e430e, + 0xbf06807d, 0xbfa1fff0, + 0xb980f801, 0x00000000, + 0xbfbd0000, 0xb8f83b05, + 0x80788178, 0xbf0d9972, + 0xbfa20002, 0x84788978, + 0xbfa00001, 0x84788a78, + 0xb8ee1e06, 0x846e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef600ff, + 0x01000000, 0xf4205bfa, 0xf0000000, 0x80788478, - 0xf4205b7a, 0xf0000000, - 0x80788478, 0xf4205c3a, + 0xf4205b3a, 0xf0000000, + 0x80788478, 0xf4205b7a, 0xf0000000, 0x80788478, - 0xf4205c7a, 0xf0000000, - 0x80788478, 0xf4205eba, + 0xf4205c3a, 0xf0000000, + 0x80788478, 0xf4205c7a, 0xf0000000, 0x80788478, - 0xf4205efa, 0xf0000000, - 0x80788478, 0xf4205e7a, + 0xf4205eba, 0xf0000000, + 0x80788478, 0xf4205efa, 0xf0000000, 0x80788478, - 0xf4205cfa, 0xf0000000, - 0x80788478, 0xf4205bba, + 0xf4205e7a, 0xf0000000, + 0x80788478, 0xf4205cfa, 0xf0000000, 0x80788478, - 0xbf89fc07, 0xb96ef814, 0xf4205bba, 0xf0000000, 0x80788478, 0xbf89fc07, - 0xb96ef815, 0xbefd006f, - 0xbefe0070, 0xbeff0071, - 0x8b6f7bff, 0x000003ff, - 0xb96f4803, 0x8b6f7bff, - 0xfffff800, 0x856f8b6f, - 0xb96fa2c3, 0xb973f801, - 0xb8ee3b05, 0x806e816e, - 0xbf0d9972, 0xbfa20002, - 0x846e896e, 0xbfa00001, - 0x846e8a6e, 0xb8ef1e06, - 0x846f8a6f, 0x806e6f6e, - 0x806eff6e, 0x00000200, - 0x806e746e, 0x826f8075, - 0x8b6fff6f, 0x0000ffff, - 0xf4085c37, 0xf8000050, - 0xf4085d37, 0xf8000060, - 0xf4005e77, 0xf8000074, - 0xbf89fc07, 0x8b6dff6d, - 0x0000ffff, 0x8bfe7e7e, - 0x8bea6a6a, 0xb8eef802, - 0xbf0d866e, 0xbfa20002, - 0xb97af802, 0xbe80486c, - 0xb97af802, 0xbe804a6c, - 0xbfb00000, 0xbf9f0000, + 0xb96ef814, 0xf4205bba, + 0xf0000000, 0x80788478, + 0xbf89fc07, 0xb96ef815, + 0xbefd006f, 0xbefe0070, + 0xbeff0071, 0x8b6f7bff, + 0x000003ff, 0xb96f4803, + 0x8b6f7bff, 0xfffff800, + 0x856f8b6f, 0xb96fa2c3, + 0xb973f801, 0xb8ee3b05, + 0x806e816e, 0xbf0d9972, + 0xbfa20002, 0x846e896e, + 0xbfa00001, 0x846e8a6e, + 0xb8ef1e06, 0x846f8a6f, + 0x806e6f6e, 0x806eff6e, + 0x00000200, 0x806e746e, + 0x826f8075, 0x8b6fff6f, + 0x0000ffff, 0xf4085c37, + 0xf8000050, 0xf4085d37, + 0xf8000060, 0xf4005e77, + 0xf8000074, 0xbf89fc07, + 0x8b6dff6d, 0x0000ffff, + 0x8bfe7e7e, 0x8bea6a6a, + 0xb8eef802, 0xbf0d866e, + 0xbfa20002, 0xb97af802, + 0xbe80486c, 0xb97af802, + 0xbe804a6c, 0xbfb00000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, + 0xbf9f0000, 0x00000000, }; diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 0f81670f6f9c..8b92c33c2a7c 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -186,6 +186,12 @@ L_SKIP_RESTORE: s_getreg_b32 s_save_trapsts, hwreg(HW_REG_TRAPSTS) #if SW_SA_TRAP + // If ttmp1[30] is set then issue s_barrier to unblock dependent waves. + s_bitcmp1_b32 s_save_pc_hi, 30 + s_cbranch_scc0 L_TRAP_NO_BARRIER + s_barrier + +L_TRAP_NO_BARRIER: // If ttmp1[31] is set then trap may occur early. // Spin wait until SAVECTX exception is raised. s_bitcmp1_b32 s_save_pc_hi, 31 -- cgit v1.2.3 From 9a1662f549343d3ec882c5ffcfd232c6104d3c85 Mon Sep 17 00:00:00 2001 From: Graham Sider Date: Thu, 29 Sep 2022 11:57:34 -0400 Subject: drm/amdgpu: extend halt_if_hws_hang to MES Hang on MES timeout if halt_if_hws_hang is set to 1. Signed-off-by: Graham Sider Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 4 ++++ 3 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 0e6ddf05c23c..9999c18e7d8e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -219,10 +219,12 @@ extern int amdgpu_use_xgmi_p2p; extern int sched_policy; extern bool debug_evictions; extern bool no_system_mem_limit; +extern int halt_if_hws_hang; #else static const int __maybe_unused sched_policy = KFD_SCHED_POLICY_HWS; static const bool __maybe_unused debug_evictions; /* = false */ static const bool __maybe_unused no_system_mem_limit; +static const int __maybe_unused halt_if_hws_hang; #endif #ifdef CONFIG_HSA_AMD_P2P extern bool pcie_p2p; diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c index 1abdf8b7ab50..614394118a53 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c @@ -121,6 +121,10 @@ static int mes_v10_1_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, if (r < 1) { DRM_ERROR("MES failed to response msg=%d\n", x_pkt->header.opcode); + + while (halt_if_hws_hang) + schedule(); + return -ETIMEDOUT; } diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 8ca3417fcfe5..1395453a0662 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -129,6 +129,10 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, if (r < 1) { DRM_ERROR("MES failed to response msg=%d\n", x_pkt->header.opcode); + + while (halt_if_hws_hang) + schedule(); + return -ETIMEDOUT; } -- cgit v1.2.3 From 0cfce2401e1553f3bf0ee3b6ef56c9dda0303815 Mon Sep 17 00:00:00 2001 From: Yiqing Yao Date: Fri, 28 Oct 2022 17:03:17 +0800 Subject: drm/amdgpu: Clean up soc21 early init for SRIOV Use virt_init_setting instead of per ip version setting. Signed-off-by: Yiqing Yao Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index e08044008186..1d4013ed0d10 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -584,10 +584,6 @@ static int soc21_common_early_init(void *handle) AMD_PG_SUPPORT_JPEG | AMD_PG_SUPPORT_ATHUB | AMD_PG_SUPPORT_MMHUB; - if (amdgpu_sriov_vf(adev)) { - adev->cg_flags = 0; - adev->pg_flags = 0; - } adev->external_rev_id = adev->rev_id + 0x1; // TODO: need update break; case IP_VERSION(11, 0, 2): @@ -645,11 +641,6 @@ static int soc21_common_early_init(void *handle) adev->pg_flags = AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_VCN_DPG | AMD_PG_SUPPORT_JPEG; - if (amdgpu_sriov_vf(adev)) { - /* hypervisor control CG and PG enablement */ - adev->cg_flags = 0; - adev->pg_flags = 0; - } adev->external_rev_id = adev->rev_id + 0x20; break; default: @@ -657,6 +648,9 @@ static int soc21_common_early_init(void *handle) return -EINVAL; } + if (amdgpu_sriov_vf(adev)) + amdgpu_virt_init_setting(adev); + return 0; } -- cgit v1.2.3 From 8a1fbb4a5ec29d9ae5f792a1d3c049c5c709851c Mon Sep 17 00:00:00 2001 From: Yiqing Yao Date: Fri, 28 Oct 2022 17:30:17 +0800 Subject: drm/amdgpu: Disable MCBP from soc21 for SRIOV [why] Start from soc21, CP does not support MCBP, so disable it. [how] Used amgpu_mcbp flag alone instead of checking if is in SRIOV to enable/disable MCBP. Only set flag to enable on asic_type prior to soc21 in SRIOV. Signed-off-by: Yiqing Yao Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ae10acede495..522820eeaa59 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2397,7 +2397,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) adev->ip_blocks[i].status.hw = true; /* right after GMC hw init, we create CSA */ - if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { + if (amdgpu_mcbp) { r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj, AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_CSA_SIZE); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 4e42dcb1950f..d75e0370a074 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -796,7 +796,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) dev_info->ids_flags = 0; if (adev->flags & AMD_IS_APU) dev_info->ids_flags |= AMDGPU_IDS_FLAGS_FUSION; - if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) + if (amdgpu_mcbp) dev_info->ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION; if (amdgpu_is_tmz(adev)) dev_info->ids_flags |= AMDGPU_IDS_FLAGS_TMZ; @@ -1172,7 +1172,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) goto error_vm; } - if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { + if (amdgpu_mcbp) { uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK; r = amdgpu_map_static_csa(adev, &fpriv->vm, adev->virt.csa_obj, @@ -1236,7 +1236,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE) != NULL) amdgpu_vce_free_handles(adev, file_priv); - if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { + if (amdgpu_mcbp) { /* TODO: how to handle reserve failure */ BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true)); amdgpu_vm_bo_del(adev, fpriv->csa_va); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index c73abe54d974..a226a6c48fb7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -64,6 +64,10 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev) ddev->driver_features &= ~DRIVER_ATOMIC; adev->cg_flags = 0; adev->pg_flags = 0; + + /* enable mcbp for sriov asic_type before soc21 */ + amdgpu_mcbp = (adev->asic_type < CHIP_IP_DISCOVERY) ? 1 : 0; + } void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index af94ac580d3e..ff3c127cf70d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -8489,7 +8489,7 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, control |= ib->length_dw | (vmid << 24); - if ((amdgpu_sriov_vf(ring->adev) || amdgpu_mcbp) && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { + if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { control |= INDIRECT_BUFFER_PRE_ENB(1); if (flags & AMDGPU_IB_PREEMPTED) @@ -8664,7 +8664,7 @@ static void gfx_v10_0_ring_emit_cntxcntl(struct amdgpu_ring *ring, { uint32_t dw2 = 0; - if (amdgpu_mcbp || amdgpu_sriov_vf(ring->adev)) + if (amdgpu_mcbp) gfx_v10_0_ring_emit_ce_meta(ring, (!amdgpu_sriov_vf(ring->adev) && flags & AMDGPU_IB_PREEMPTED) ? true : false); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index f68e13b6282c..84a76c36d9a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -5326,7 +5326,7 @@ static void gfx_v11_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, control |= ib->length_dw | (vmid << 24); - if ((amdgpu_sriov_vf(ring->adev) || amdgpu_mcbp) && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { + if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { control |= INDIRECT_BUFFER_PRE_ENB(1); if (flags & AMDGPU_IB_PREEMPTED) -- cgit v1.2.3 From f8638ad7fcac50d2ba8e76625e7d86cabd5d5bd2 Mon Sep 17 00:00:00 2001 From: Peng Ju Zhou Date: Fri, 28 Oct 2022 18:24:45 +0800 Subject: drm/amdgpu: Remove unnecessary register program in SRIOV Remove unnecessary register program in SRIOV Signed-off-by: Peng Ju Zhou Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 8cf53e039c11..3f8676d23a5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -397,6 +397,9 @@ static void gfxhub_v2_1_gart_disable(struct amdgpu_device *adev) ENABLE_ADVANCED_DRIVER_MODEL, 0); WREG32_SOC15(GC, 0, mmGCMC_VM_MX_L1_TLB_CNTL, tmp); + if (amdgpu_sriov_vf(adev)) + return; + /* Setup L2 cache */ WREG32_FIELD15(GC, 0, GCVM_L2_CNTL, ENABLE_L2_CACHE, 0); WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL3, 0); -- cgit v1.2.3 From 33034c5c2efaf56c7b89aed5a3cf1bcb3f12b853 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Nov 2022 11:17:23 -0400 Subject: drm/amdgpu/gfx9: set gfx.funcs in early init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So the callbacks are set before we use them. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 0320be4a5fc6..c80623c35b52 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1919,8 +1919,6 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) u32 gb_addr_config; int err; - adev->gfx.funcs = &gfx_v9_0_gfx_funcs; - switch (adev->ip_versions[GC_HWIP][0]) { case IP_VERSION(9, 0, 1): adev->gfx.config.max_hw_contexts = 8; @@ -4539,6 +4537,8 @@ static int gfx_v9_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + adev->gfx.funcs = &gfx_v9_0_gfx_funcs; + if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) || adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) adev->gfx.num_gfx_rings = 0; -- cgit v1.2.3 From 105195af02d4e8665e4583cf7ef4e5f69d858d7d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Nov 2022 11:20:49 -0400 Subject: drm/amdgpu/gfx10: set gfx.funcs in early init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So the callbacks are set early in case we need them. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index ff3c127cf70d..7853d3ca58cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -4453,8 +4453,6 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev) { u32 gb_addr_config; - adev->gfx.funcs = &gfx_v10_0_gfx_funcs; - switch (adev->ip_versions[GC_HWIP][0]) { case IP_VERSION(10, 1, 10): case IP_VERSION(10, 1, 1): @@ -7593,6 +7591,8 @@ static int gfx_v10_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + adev->gfx.funcs = &gfx_v10_0_gfx_funcs; + switch (adev->ip_versions[GC_HWIP][0]) { case IP_VERSION(10, 1, 10): case IP_VERSION(10, 1, 1): -- cgit v1.2.3 From e053d71f8c04fd7ef53241d2ab39f02acee6aaa0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Nov 2022 11:21:35 -0400 Subject: drm/amdgpu/gfx11: set gfx.funcs in early init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So the callbacks are set early in case we need them. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 84a76c36d9a7..d799359565b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -843,7 +843,6 @@ static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = { static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev) { - adev->gfx.funcs = &gfx_v11_0_gfx_funcs; switch (adev->ip_versions[GC_HWIP][0]) { case IP_VERSION(11, 0, 0): @@ -4657,6 +4656,8 @@ static int gfx_v11_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + adev->gfx.funcs = &gfx_v11_0_gfx_funcs; + adev->gfx.num_gfx_rings = GFX11_NUM_GFX_RINGS; adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev), AMDGPU_MAX_COMPUTE_RINGS); -- cgit v1.2.3 From c81c5bd5cf2f428867e0bcfcccd4e4d2f8c68f51 Mon Sep 17 00:00:00 2001 From: Paulo Miguel Almeida Date: Sat, 29 Oct 2022 16:32:05 +1300 Subject: drm/radeon: Replace one-element array with flexible-array member One-element arrays are deprecated, and we are replacing them with flexible array members instead. So, replace one-element array with flexible-array member in struct _ATOM_FAKE_EDID_PATCH_RECORD and refactor the rest of the code accordingly. It's worth mentioning that doing a build before/after this patch results in no binary output differences. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/79 Link: https://github.com/KSPP/linux/issues/239 Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101836 [1] Reviewed-by: Kees Cook Signed-off-by: Paulo Miguel Almeida Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios.h | 2 +- drivers/gpu/drm/radeon/radeon_atombios.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index da35a970fcc0..235e59b547a1 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -3615,7 +3615,7 @@ typedef struct _ATOM_FAKE_EDID_PATCH_RECORD { UCHAR ucRecordType; UCHAR ucFakeEDIDLength; - UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements. + UCHAR ucFakeEDIDString[]; // This actually has ucFakeEdidLength elements. } ATOM_FAKE_EDID_PATCH_RECORD; typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 204127bad89c..4ad5a328d920 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1727,8 +1727,11 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct } } record += fake_edid_record->ucFakeEDIDLength ? - fake_edid_record->ucFakeEDIDLength + 2 : - sizeof(ATOM_FAKE_EDID_PATCH_RECORD); + struct_size(fake_edid_record, + ucFakeEDIDString, + fake_edid_record->ucFakeEDIDLength) : + /* empty fake edid record must be 3 bytes long */ + sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; break; case LCD_PANEL_RESOLUTION_RECORD_TYPE: panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; -- cgit v1.2.3 From 320e2590e281d0a7865e861f50155b5b435e9813 Mon Sep 17 00:00:00 2001 From: Paulo Miguel Almeida Date: Sat, 29 Oct 2022 14:30:44 +1300 Subject: drm/amdgpu: Replace one-element array with flexible-array member One-element arrays are deprecated, and we are replacing them with flexible array members instead. So, replace one-element array with flexible-array member in struct _ATOM_FAKE_EDID_PATCH_RECORD and refactor the rest of the code accordingly. Important to mention is that doing a build before/after this patch results in no binary output differences. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/79 Link: https://github.com/KSPP/linux/issues/238 Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101836 [1] Signed-off-by: Paulo Miguel Almeida Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 7 +++++-- drivers/gpu/drm/amd/include/atombios.h | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index 6be9ac2b9c5b..18ae9433e463 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -2081,8 +2081,11 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder) } } record += fake_edid_record->ucFakeEDIDLength ? - fake_edid_record->ucFakeEDIDLength + 2 : - sizeof(ATOM_FAKE_EDID_PATCH_RECORD); + struct_size(fake_edid_record, + ucFakeEDIDString, + fake_edid_record->ucFakeEDIDLength) : + /* empty fake edid record must be 3 bytes long */ + sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; break; case LCD_PANEL_RESOLUTION_RECORD_TYPE: panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index 15943bc21bc5..b5b1d073f8e2 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -4107,7 +4107,7 @@ typedef struct _ATOM_FAKE_EDID_PATCH_RECORD { UCHAR ucRecordType; UCHAR ucFakeEDIDLength; // = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128 - UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements. + UCHAR ucFakeEDIDString[]; // This actually has ucFakeEdidLength elements. } ATOM_FAKE_EDID_PATCH_RECORD; typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD -- cgit v1.2.3 From f0d0f1087333714ee683cc134a95afe331d7ddd9 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 2 Nov 2022 08:25:39 -0700 Subject: drm/amdgpu: Fix type of second parameter in trans_msg() callback With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), indirect call targets are validated against the expected function pointer prototype to make sure the call target is valid to help mitigate ROP attacks. If they are not identical, there is a failure at run time, which manifests as either a kernel panic or thread getting killed. A proposed warning in clang aims to catch these at compile time, which reveals: drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c:412:15: error: incompatible function pointer types initializing 'void (*)(struct amdgpu_device *, u32, u32, u32, u32)' (aka 'void (*)(struct amdgpu_device *, unsigned int, unsigned int, unsigned int, unsigned int)') with an expression of type 'void (struct amdgpu_device *, enum idh_request, u32, u32, u32)' (aka 'void (struct amdgpu_device *, enum idh_request, unsigned int, unsigned int, unsigned int)') [-Werror,-Wincompatible-function-pointer-types-strict] .trans_msg = xgpu_ai_mailbox_trans_msg, ^~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c:435:15: error: incompatible function pointer types initializing 'void (*)(struct amdgpu_device *, u32, u32, u32, u32)' (aka 'void (*)(struct amdgpu_device *, unsigned int, unsigned int, unsigned int, unsigned int)') with an expression of type 'void (struct amdgpu_device *, enum idh_request, u32, u32, u32)' (aka 'void (struct amdgpu_device *, enum idh_request, unsigned int, unsigned int, unsigned int)') [-Werror,-Wincompatible-function-pointer-types-strict] .trans_msg = xgpu_nv_mailbox_trans_msg, ^~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. The type of the second parameter in the prototype should be 'enum idh_request' instead of 'u32'. Update it to clear up the warnings. Link: https://github.com/ClangBuiltLinux/linux/issues/1750 Reported-by: Sami Tolvanen Reviewed-by: Kees Cook Signed-off-by: Nathan Chancellor Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 49c4347d154c..2b9d806e23af 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -75,6 +75,8 @@ struct amdgpu_vf_error_buffer { uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE]; }; +enum idh_request; + /** * struct amdgpu_virt_ops - amdgpu device virt operations */ @@ -84,7 +86,8 @@ struct amdgpu_virt_ops { int (*req_init_data)(struct amdgpu_device *adev); int (*reset_gpu)(struct amdgpu_device *adev); int (*wait_reset)(struct amdgpu_device *adev); - void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3); + void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req, + u32 data1, u32 data2, u32 data3); }; /* -- cgit v1.2.3 From e4d0ef752081e7aa6ffb7ccac11c499c732a2e05 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 2 Nov 2022 08:25:40 -0700 Subject: drm/amdgpu: Fix type of second parameter in odn_edit_dpm_table() callback With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), indirect call targets are validated against the expected function pointer prototype to make sure the call target is valid to help mitigate ROP attacks. If they are not identical, there is a failure at run time, which manifests as either a kernel panic or thread getting killed. A proposed warning in clang aims to catch these at compile time, which reveals: drivers/gpu/drm/amd/amdgpu/../pm/swsmu/amdgpu_smu.c:3008:29: error: incompatible function pointer types initializing 'int (*)(void *, uint32_t, long *, uint32_t)' (aka 'int (*)(void *, unsigned int, long *, unsigned int)') with an expression of type 'int (void *, enum PP_OD_DPM_TABLE_COMMAND, long *, uint32_t)' (aka 'int (void *, enum PP_OD_DPM_TABLE_COMMAND, long *, unsigned int)') [-Werror,-Wincompatible-function-pointer-types-strict] .odn_edit_dpm_table = smu_od_edit_dpm_table, ^~~~~~~~~~~~~~~~~~~~~ 1 error generated. There are only two implementations of ->odn_edit_dpm_table() in 'struct amd_pm_funcs': smu_od_edit_dpm_table() and pp_odn_edit_dpm_table(). One has a second parameter type of 'enum PP_OD_DPM_TABLE_COMMAND' and the other uses 'u32'. Ultimately, smu_od_edit_dpm_table() calls ->od_edit_dpm_table() from 'struct pptable_funcs' and pp_odn_edit_dpm_table() calls ->odn_edit_dpm_table() from 'struct pp_hwmgr_func', which both have a second parameter type of 'enum PP_OD_DPM_TABLE_COMMAND'. Update the type parameter in both the prototype in 'struct amd_pm_funcs' and pp_odn_edit_dpm_table() to 'enum PP_OD_DPM_TABLE_COMMAND', which cleans up the warning. Link: https://github.com/ClangBuiltLinux/linux/issues/1750 Reported-by: Sami Tolvanen Reviewed-by: Kees Cook Signed-off-by: Nathan Chancellor Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 3 ++- drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index a40ead44778a..d18162e9ed1d 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -354,7 +354,8 @@ struct amd_pm_funcs { int (*get_power_profile_mode)(void *handle, char *buf); int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); int (*set_fine_grain_clk_vol)(void *handle, uint32_t type, long *input, uint32_t size); - int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size); + int (*odn_edit_dpm_table)(void *handle, enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size); int (*set_mp1_state)(void *handle, enum pp_mp1_state mp1_state); int (*smu_i2c_bus_access)(void *handle, bool acquire); int (*gfx_state_change_set)(void *handle, uint32_t state); diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index ec055858eb95..1159ae114dd0 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -838,7 +838,8 @@ static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, u return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size); } -static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) +static int pp_odn_edit_dpm_table(void *handle, enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size) { struct pp_hwmgr *hwmgr = handle; -- cgit v1.2.3 From cfa61b8f9e9e5e14e7a79f3e9454feb8e4690f99 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Mon, 25 Oct 2021 17:23:38 +0800 Subject: drm/amdgpu: switch to select_se_sh wrapper for gfx v9_0 To allow invoking ip specific callbacks Acked-by: Felix Kuehling Signed-off-by: Hawking Zhang Reviewed-by: Le Ma Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 28 +++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index 81e3b528bbc9..e92b93557c13 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -787,7 +787,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid, for (se_idx = 0; se_idx < se_cnt; se_idx++) { for (sh_idx = 0; sh_idx < sh_cnt; sh_idx++) { - gfx_v9_0_select_se_sh(adev, se_idx, sh_idx, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, se_idx, sh_idx, 0xffffffff); queue_map = RREG32_SOC15(GC, 0, mmSPI_CSQ_WF_ACTIVE_STATUS); /* @@ -820,7 +820,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid, } } - gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); soc15_grbm_select(adev, 0, 0, 0, 0); unlock_spi_csq_mutexes(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index c80623c35b52..ab30c18decfb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1564,7 +1564,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev) mask = 1; cu_bitmap = 0; counter = 0; - gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff); for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) { if (cu_info->bitmap[i][j] & mask) { @@ -1583,7 +1583,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev) cu_info->ao_cu_bitmap[i][j] = cu_bitmap; } } - gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); } @@ -1605,7 +1605,7 @@ static void gfx_v9_0_init_lbpw(struct amdgpu_device *adev) mutex_lock(&adev->grbm_idx_mutex); /* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/ - gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff); /* set mmRLC_LB_PARAMS = 0x003F_1006 */ @@ -1654,7 +1654,7 @@ static void gfx_v9_4_init_lbpw(struct amdgpu_device *adev) mutex_lock(&adev->grbm_idx_mutex); /* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/ - gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff); /* set mmRLC_LB_PARAMS = 0x003F_1006 */ @@ -2322,13 +2322,13 @@ static void gfx_v9_0_setup_rb(struct amdgpu_device *adev) mutex_lock(&adev->grbm_idx_mutex); for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { - gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff); data = gfx_v9_0_get_rb_active_bitmap(adev); active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) * rb_bitmap_width_per_sh); } } - gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); adev->gfx.config.backend_enable_mask = active_rbs; @@ -2465,14 +2465,14 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev) mutex_lock(&adev->grbm_idx_mutex); for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { - gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff); for (k = 0; k < adev->usec_timeout; k++) { if (RREG32_SOC15(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY) == 0) break; udelay(1); } if (k == adev->usec_timeout) { - gfx_v9_0_select_se_sh(adev, 0xffffffff, + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); DRM_INFO("Timeout wait for RLC serdes %u,%u\n", @@ -2481,7 +2481,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev) } } } - gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); mask = RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK | @@ -6482,7 +6482,7 @@ static void gfx_v9_0_reset_ras_error_count(struct amdgpu_device *adev) for (i = 0; i < ARRAY_SIZE(gfx_v9_0_edc_counter_regs); i++) { for (j = 0; j < gfx_v9_0_edc_counter_regs[i].se_num; j++) { for (k = 0; k < gfx_v9_0_edc_counter_regs[i].instance; k++) { - gfx_v9_0_select_se_sh(adev, j, 0x0, k); + amdgpu_gfx_select_se_sh(adev, j, 0x0, k); RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i])); } } @@ -6544,7 +6544,7 @@ static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, for (i = 0; i < ARRAY_SIZE(gfx_v9_0_edc_counter_regs); i++) { for (j = 0; j < gfx_v9_0_edc_counter_regs[i].se_num; j++) { for (k = 0; k < gfx_v9_0_edc_counter_regs[i].instance; k++) { - gfx_v9_0_select_se_sh(adev, j, 0, k); + amdgpu_gfx_select_se_sh(adev, j, 0, k); reg_value = RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i])); if (reg_value) @@ -6559,7 +6559,7 @@ static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, err_data->ce_count += sec_count; err_data->ue_count += ded_count; - gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); gfx_v9_0_query_utc_edc_status(adev, err_data); @@ -6963,7 +6963,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev, mask = 1; ao_bitmap = 0; counter = 0; - gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff); gfx_v9_0_set_user_cu_inactive_bitmap( adev, disable_masks[i * adev->gfx.config.max_sh_per_se + j]); bitmap = gfx_v9_0_get_cu_active_bitmap(adev); @@ -6996,7 +6996,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev, cu_info->ao_cu_bitmap[i % 4][j + i / 4] = ao_bitmap; } } - gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); cu_info->number = active_cu_number; -- cgit v1.2.3 From c0cc999f3c32e65a7c88fb323893ddf897b24488 Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Wed, 2 Nov 2022 15:53:26 +0800 Subject: drm/amdkfd: Fix the warning of array-index-out-of-bounds For some GPUs with more CUs, the original sibling_map[32] in struct crat_subtype_cache is not enough to save the cache information when create the VCRAT table, so skip filling the struct crat_subtype_cache info instead fill struct kfd_cache_properties directly to fix this problem. Signed-off-by: Ma Jun Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 312 ++++-------------------------- drivers/gpu/drm/amd/amdkfd/kfd_crat.h | 12 ++ drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 245 +++++++++++++++++++++-- drivers/gpu/drm/amd/amdkfd/kfd_topology.h | 5 +- 4 files changed, 282 insertions(+), 292 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 568cbf1d8259..267dd69737fa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -50,16 +50,6 @@ static inline unsigned int get_and_inc_gpu_processor_id( return current_id; } -/* Static table to describe GPU Cache information */ -struct kfd_gpu_cache_info { - uint32_t cache_size; - uint32_t cache_level; - uint32_t flags; - /* Indicates how many Compute Units share this cache - * within a SA. Value = 1 indicates the cache is not shared - */ - uint32_t num_cu_shared; -}; static struct kfd_gpu_cache_info kaveri_cache_info[] = { { @@ -1119,9 +1109,13 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache, props->cachelines_per_tag = cache->lines_per_tag; props->cache_assoc = cache->associativity; props->cache_latency = cache->cache_latency; + memcpy(props->sibling_map, cache->sibling_map, sizeof(props->sibling_map)); + /* set the sibling_map_size as 32 for CRAT from ACPI */ + props->sibling_map_size = CRAT_SIBLINGMAP_SIZE; + if (cache->flags & CRAT_CACHE_FLAGS_DATA_CACHE) props->cache_type |= HSA_CACHE_TYPE_DATA; if (cache->flags & CRAT_CACHE_FLAGS_INST_CACHE) @@ -1338,125 +1332,6 @@ err: return ret; } -/* Helper function. See kfd_fill_gpu_cache_info for parameter description */ -static int fill_in_l1_pcache(struct crat_subtype_cache *pcache, - struct kfd_gpu_cache_info *pcache_info, - struct kfd_cu_info *cu_info, - int mem_available, - int cu_bitmask, - int cache_type, unsigned int cu_processor_id, - int cu_block) -{ - unsigned int cu_sibling_map_mask; - int first_active_cu; - - /* First check if enough memory is available */ - if (sizeof(struct crat_subtype_cache) > mem_available) - return -ENOMEM; - - cu_sibling_map_mask = cu_bitmask; - cu_sibling_map_mask >>= cu_block; - cu_sibling_map_mask &= - ((1 << pcache_info[cache_type].num_cu_shared) - 1); - first_active_cu = ffs(cu_sibling_map_mask); - - /* CU could be inactive. In case of shared cache find the first active - * CU. and incase of non-shared cache check if the CU is inactive. If - * inactive active skip it - */ - if (first_active_cu) { - memset(pcache, 0, sizeof(struct crat_subtype_cache)); - pcache->type = CRAT_SUBTYPE_CACHE_AFFINITY; - pcache->length = sizeof(struct crat_subtype_cache); - pcache->flags = pcache_info[cache_type].flags; - pcache->processor_id_low = cu_processor_id - + (first_active_cu - 1); - pcache->cache_level = pcache_info[cache_type].cache_level; - pcache->cache_size = pcache_info[cache_type].cache_size; - - /* Sibling map is w.r.t processor_id_low, so shift out - * inactive CU - */ - cu_sibling_map_mask = - cu_sibling_map_mask >> (first_active_cu - 1); - - pcache->sibling_map[0] = (uint8_t)(cu_sibling_map_mask & 0xFF); - pcache->sibling_map[1] = - (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF); - pcache->sibling_map[2] = - (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF); - pcache->sibling_map[3] = - (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF); - return 0; - } - return 1; -} - -/* Helper function. See kfd_fill_gpu_cache_info for parameter description */ -static int fill_in_l2_l3_pcache(struct crat_subtype_cache *pcache, - struct kfd_gpu_cache_info *pcache_info, - struct kfd_cu_info *cu_info, - int mem_available, - int cache_type, unsigned int cu_processor_id) -{ - unsigned int cu_sibling_map_mask; - int first_active_cu; - int i, j, k; - - /* First check if enough memory is available */ - if (sizeof(struct crat_subtype_cache) > mem_available) - return -ENOMEM; - - cu_sibling_map_mask = cu_info->cu_bitmap[0][0]; - cu_sibling_map_mask &= - ((1 << pcache_info[cache_type].num_cu_shared) - 1); - first_active_cu = ffs(cu_sibling_map_mask); - - /* CU could be inactive. In case of shared cache find the first active - * CU. and incase of non-shared cache check if the CU is inactive. If - * inactive active skip it - */ - if (first_active_cu) { - memset(pcache, 0, sizeof(struct crat_subtype_cache)); - pcache->type = CRAT_SUBTYPE_CACHE_AFFINITY; - pcache->length = sizeof(struct crat_subtype_cache); - pcache->flags = pcache_info[cache_type].flags; - pcache->processor_id_low = cu_processor_id - + (first_active_cu - 1); - pcache->cache_level = pcache_info[cache_type].cache_level; - pcache->cache_size = pcache_info[cache_type].cache_size; - - /* Sibling map is w.r.t processor_id_low, so shift out - * inactive CU - */ - cu_sibling_map_mask = - cu_sibling_map_mask >> (first_active_cu - 1); - k = 0; - for (i = 0; i < cu_info->num_shader_engines; i++) { - for (j = 0; j < cu_info->num_shader_arrays_per_engine; - j++) { - pcache->sibling_map[k] = - (uint8_t)(cu_sibling_map_mask & 0xFF); - pcache->sibling_map[k+1] = - (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF); - pcache->sibling_map[k+2] = - (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF); - pcache->sibling_map[k+3] = - (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF); - k += 4; - cu_sibling_map_mask = - cu_info->cu_bitmap[i % 4][j + i / 4]; - cu_sibling_map_mask &= ( - (1 << pcache_info[cache_type].num_cu_shared) - - 1); - } - } - return 0; - } - return 1; -} - -#define KFD_MAX_CACHE_TYPES 6 static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev, struct kfd_gpu_cache_info *pcache_info) @@ -1530,231 +1405,133 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev, return i; } -/* kfd_fill_gpu_cache_info - Fill GPU cache info using kfd_gpu_cache_info - * tables - * - * @kdev - [IN] GPU device - * @gpu_processor_id - [IN] GPU processor ID to which these caches - * associate - * @available_size - [IN] Amount of memory available in pcache - * @cu_info - [IN] Compute Unit info obtained from KGD - * @pcache - [OUT] memory into which cache data is to be filled in. - * @size_filled - [OUT] amount of data used up in pcache. - * @num_of_entries - [OUT] number of caches added - */ -static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, - int gpu_processor_id, - int available_size, - struct kfd_cu_info *cu_info, - struct crat_subtype_cache *pcache, - int *size_filled, - int *num_of_entries) +int kfd_get_gpu_cache_info(struct kfd_dev *kdev, struct kfd_gpu_cache_info **pcache_info) { - struct kfd_gpu_cache_info *pcache_info; - struct kfd_gpu_cache_info cache_info[KFD_MAX_CACHE_TYPES]; int num_of_cache_types = 0; - int i, j, k; - int ct = 0; - int mem_available = available_size; - unsigned int cu_processor_id; - int ret; - unsigned int num_cu_shared; switch (kdev->adev->asic_type) { case CHIP_KAVERI: - pcache_info = kaveri_cache_info; + *pcache_info = kaveri_cache_info; num_of_cache_types = ARRAY_SIZE(kaveri_cache_info); break; case CHIP_HAWAII: - pcache_info = hawaii_cache_info; + *pcache_info = hawaii_cache_info; num_of_cache_types = ARRAY_SIZE(hawaii_cache_info); break; case CHIP_CARRIZO: - pcache_info = carrizo_cache_info; + *pcache_info = carrizo_cache_info; num_of_cache_types = ARRAY_SIZE(carrizo_cache_info); break; case CHIP_TONGA: - pcache_info = tonga_cache_info; + *pcache_info = tonga_cache_info; num_of_cache_types = ARRAY_SIZE(tonga_cache_info); break; case CHIP_FIJI: - pcache_info = fiji_cache_info; + *pcache_info = fiji_cache_info; num_of_cache_types = ARRAY_SIZE(fiji_cache_info); break; case CHIP_POLARIS10: - pcache_info = polaris10_cache_info; + *pcache_info = polaris10_cache_info; num_of_cache_types = ARRAY_SIZE(polaris10_cache_info); break; case CHIP_POLARIS11: - pcache_info = polaris11_cache_info; + *pcache_info = polaris11_cache_info; num_of_cache_types = ARRAY_SIZE(polaris11_cache_info); break; case CHIP_POLARIS12: - pcache_info = polaris12_cache_info; + *pcache_info = polaris12_cache_info; num_of_cache_types = ARRAY_SIZE(polaris12_cache_info); break; case CHIP_VEGAM: - pcache_info = vegam_cache_info; + *pcache_info = vegam_cache_info; num_of_cache_types = ARRAY_SIZE(vegam_cache_info); break; default: switch (KFD_GC_VERSION(kdev)) { case IP_VERSION(9, 0, 1): - pcache_info = vega10_cache_info; + *pcache_info = vega10_cache_info; num_of_cache_types = ARRAY_SIZE(vega10_cache_info); break; case IP_VERSION(9, 2, 1): - pcache_info = vega12_cache_info; + *pcache_info = vega12_cache_info; num_of_cache_types = ARRAY_SIZE(vega12_cache_info); break; case IP_VERSION(9, 4, 0): case IP_VERSION(9, 4, 1): - pcache_info = vega20_cache_info; + *pcache_info = vega20_cache_info; num_of_cache_types = ARRAY_SIZE(vega20_cache_info); break; case IP_VERSION(9, 4, 2): - pcache_info = aldebaran_cache_info; + *pcache_info = aldebaran_cache_info; num_of_cache_types = ARRAY_SIZE(aldebaran_cache_info); break; case IP_VERSION(9, 1, 0): case IP_VERSION(9, 2, 2): - pcache_info = raven_cache_info; + *pcache_info = raven_cache_info; num_of_cache_types = ARRAY_SIZE(raven_cache_info); break; case IP_VERSION(9, 3, 0): - pcache_info = renoir_cache_info; + *pcache_info = renoir_cache_info; num_of_cache_types = ARRAY_SIZE(renoir_cache_info); break; case IP_VERSION(10, 1, 10): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): case IP_VERSION(10, 1, 4): - pcache_info = navi10_cache_info; + *pcache_info = navi10_cache_info; num_of_cache_types = ARRAY_SIZE(navi10_cache_info); break; case IP_VERSION(10, 1, 1): - pcache_info = navi14_cache_info; + *pcache_info = navi14_cache_info; num_of_cache_types = ARRAY_SIZE(navi14_cache_info); break; case IP_VERSION(10, 3, 0): - pcache_info = sienna_cichlid_cache_info; + *pcache_info = sienna_cichlid_cache_info; num_of_cache_types = ARRAY_SIZE(sienna_cichlid_cache_info); break; case IP_VERSION(10, 3, 2): - pcache_info = navy_flounder_cache_info; + *pcache_info = navy_flounder_cache_info; num_of_cache_types = ARRAY_SIZE(navy_flounder_cache_info); break; case IP_VERSION(10, 3, 4): - pcache_info = dimgrey_cavefish_cache_info; + *pcache_info = dimgrey_cavefish_cache_info; num_of_cache_types = ARRAY_SIZE(dimgrey_cavefish_cache_info); break; case IP_VERSION(10, 3, 1): - pcache_info = vangogh_cache_info; + *pcache_info = vangogh_cache_info; num_of_cache_types = ARRAY_SIZE(vangogh_cache_info); break; case IP_VERSION(10, 3, 5): - pcache_info = beige_goby_cache_info; + *pcache_info = beige_goby_cache_info; num_of_cache_types = ARRAY_SIZE(beige_goby_cache_info); break; case IP_VERSION(10, 3, 3): - pcache_info = yellow_carp_cache_info; + *pcache_info = yellow_carp_cache_info; num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info); break; case IP_VERSION(10, 3, 6): - pcache_info = gc_10_3_6_cache_info; + *pcache_info = gc_10_3_6_cache_info; num_of_cache_types = ARRAY_SIZE(gc_10_3_6_cache_info); break; case IP_VERSION(10, 3, 7): - pcache_info = gfx1037_cache_info; + *pcache_info = gfx1037_cache_info; num_of_cache_types = ARRAY_SIZE(gfx1037_cache_info); break; case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 2): case IP_VERSION(11, 0, 3): - pcache_info = cache_info; num_of_cache_types = - kfd_fill_gpu_cache_info_from_gfx_config(kdev, pcache_info); + kfd_fill_gpu_cache_info_from_gfx_config(kdev, *pcache_info); break; default: - pcache_info = dummy_cache_info; + *pcache_info = dummy_cache_info; num_of_cache_types = ARRAY_SIZE(dummy_cache_info); pr_warn("dummy cache info is used temporarily and real cache info need update later.\n"); break; } } - - *size_filled = 0; - *num_of_entries = 0; - - /* For each type of cache listed in the kfd_gpu_cache_info table, - * go through all available Compute Units. - * The [i,j,k] loop will - * if kfd_gpu_cache_info.num_cu_shared = 1 - * will parse through all available CU - * If (kfd_gpu_cache_info.num_cu_shared != 1) - * then it will consider only one CU from - * the shared unit - */ - - for (ct = 0; ct < num_of_cache_types; ct++) { - cu_processor_id = gpu_processor_id; - if (pcache_info[ct].cache_level == 1) { - for (i = 0; i < cu_info->num_shader_engines; i++) { - for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) { - for (k = 0; k < cu_info->num_cu_per_sh; - k += pcache_info[ct].num_cu_shared) { - ret = fill_in_l1_pcache(pcache, - pcache_info, - cu_info, - mem_available, - cu_info->cu_bitmap[i % 4][j + i / 4], - ct, - cu_processor_id, - k); - - if (ret < 0) - break; - - if (!ret) { - pcache++; - (*num_of_entries)++; - mem_available -= sizeof(*pcache); - (*size_filled) += sizeof(*pcache); - } - - /* Move to next CU block */ - num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <= - cu_info->num_cu_per_sh) ? - pcache_info[ct].num_cu_shared : - (cu_info->num_cu_per_sh - k); - cu_processor_id += num_cu_shared; - } - } - } - } else { - ret = fill_in_l2_l3_pcache(pcache, - pcache_info, - cu_info, - mem_available, - ct, - cu_processor_id); - - if (ret < 0) - break; - - if (!ret) { - pcache++; - (*num_of_entries)++; - mem_available -= sizeof(*pcache); - (*size_filled) += sizeof(*pcache); - } - } - } - - pr_debug("Added [%d] GPU cache entries\n", *num_of_entries); - - return 0; + return num_of_cache_types; } static bool kfd_ignore_crat(void) @@ -2313,8 +2090,6 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image, struct kfd_cu_info cu_info; int avail_size = *size; uint32_t total_num_of_cu; - int num_of_cache_entries = 0; - int cache_mem_filled = 0; uint32_t nid = 0; int ret = 0; @@ -2415,31 +2190,12 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image, crat_table->length += sizeof(struct crat_subtype_memory); crat_table->total_entries++; - /* TODO: Fill in cache information. This information is NOT readily - * available in KGD - */ - sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + - sub_type_hdr->length); - ret = kfd_fill_gpu_cache_info(kdev, cu->processor_id_low, - avail_size, - &cu_info, - (struct crat_subtype_cache *)sub_type_hdr, - &cache_mem_filled, - &num_of_cache_entries); - - if (ret < 0) - return ret; - - crat_table->length += cache_mem_filled; - crat_table->total_entries += num_of_cache_entries; - avail_size -= cache_mem_filled; - /* Fill in Subtype: IO_LINKS * Only direct links are added here which is Link from GPU to * its NUMA node. Indirect links are added by userspace. */ sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + - cache_mem_filled); + sub_type_hdr->length); ret = kfd_fill_gpu_direct_io_link_to_cpu(&avail_size, kdev, (struct crat_subtype_iolink *)sub_type_hdr, proximity_domain); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h index 22893ff7b9a1..8d1e8ba58dee 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h @@ -295,6 +295,18 @@ struct crat_subtype_generic { struct kfd_dev; +/* Static table to describe GPU Cache information */ +struct kfd_gpu_cache_info { + uint32_t cache_size; + uint32_t cache_level; + uint32_t flags; + /* Indicates how many Compute Units share this cache + * within a SA. Value = 1 indicates the cache is not shared + */ + uint32_t num_cu_shared; +}; +int kfd_get_gpu_cache_info(struct kfd_dev *kdev, struct kfd_gpu_cache_info **pcache_info); + int kfd_create_crat_image_acpi(void **crat_image, size_t *size); void kfd_destroy_crat_image(void *crat_image); int kfd_parse_crat_table(void *crat_image, struct list_head *device_list, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index ec8c9c10d348..1d9b90d979c4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -364,7 +364,6 @@ static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr, /* Making sure that the buffer is an empty string */ buffer[0] = 0; - cache = container_of(attr, struct kfd_cache_properties, attr); if (cache->gpu && kfd_devcgroup_check_permission(cache->gpu)) return -EPERM; @@ -379,12 +378,13 @@ static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr, sysfs_show_32bit_prop(buffer, offs, "association", cache->cache_assoc); sysfs_show_32bit_prop(buffer, offs, "latency", cache->cache_latency); sysfs_show_32bit_prop(buffer, offs, "type", cache->cache_type); + offs += snprintf(buffer+offs, PAGE_SIZE-offs, "sibling_map "); - for (i = 0; i < CRAT_SIBLINGMAP_SIZE; i++) + for (i = 0; i < cache->sibling_map_size; i++) for (j = 0; j < sizeof(cache->sibling_map[0])*8; j++) /* Check each bit */ offs += snprintf(buffer+offs, PAGE_SIZE-offs, "%d,", - (cache->sibling_map[i] >> j) & 1); + (cache->sibling_map[i] >> j) & 1); /* Replace the last "," with end of line */ buffer[offs-1] = '\n'; @@ -1197,7 +1197,6 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) struct kfd_iolink_properties *iolink; struct kfd_iolink_properties *p2plink; - down_write(&topology_lock); list_for_each_entry(dev, &topology_device_list, list) { /* Discrete GPUs need their own topology device list * entries. Don't assign them to CPU/APU nodes. @@ -1221,7 +1220,6 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) break; } } - up_write(&topology_lock); return out_dev; } @@ -1592,6 +1590,221 @@ out: return ret; } + +/* Helper function. See kfd_fill_gpu_cache_info for parameter description */ +static int fill_in_l1_pcache(struct kfd_cache_properties **props_ext, + struct kfd_gpu_cache_info *pcache_info, + struct kfd_cu_info *cu_info, + int cu_bitmask, + int cache_type, unsigned int cu_processor_id, + int cu_block) +{ + unsigned int cu_sibling_map_mask; + int first_active_cu; + struct kfd_cache_properties *pcache = NULL; + + cu_sibling_map_mask = cu_bitmask; + cu_sibling_map_mask >>= cu_block; + cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1); + first_active_cu = ffs(cu_sibling_map_mask); + + /* CU could be inactive. In case of shared cache find the first active + * CU. and incase of non-shared cache check if the CU is inactive. If + * inactive active skip it + */ + if (first_active_cu) { + pcache = kfd_alloc_struct(pcache); + if (!pcache) + return -ENOMEM; + + memset(pcache, 0, sizeof(struct kfd_cache_properties)); + pcache->processor_id_low = cu_processor_id + (first_active_cu - 1); + pcache->cache_level = pcache_info[cache_type].cache_level; + pcache->cache_size = pcache_info[cache_type].cache_size; + + if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE) + pcache->cache_type |= HSA_CACHE_TYPE_DATA; + if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_INST_CACHE) + pcache->cache_type |= HSA_CACHE_TYPE_INSTRUCTION; + if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_CPU_CACHE) + pcache->cache_type |= HSA_CACHE_TYPE_CPU; + if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_SIMD_CACHE) + pcache->cache_type |= HSA_CACHE_TYPE_HSACU; + + /* Sibling map is w.r.t processor_id_low, so shift out + * inactive CU + */ + cu_sibling_map_mask = + cu_sibling_map_mask >> (first_active_cu - 1); + + pcache->sibling_map[0] = (uint8_t)(cu_sibling_map_mask & 0xFF); + pcache->sibling_map[1] = + (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF); + pcache->sibling_map[2] = + (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF); + pcache->sibling_map[3] = + (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF); + + pcache->sibling_map_size = 4; + *props_ext = pcache; + + return 0; + } + return 1; +} + +/* Helper function. See kfd_fill_gpu_cache_info for parameter description */ +static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext, + struct kfd_gpu_cache_info *pcache_info, + struct kfd_cu_info *cu_info, + int cache_type, unsigned int cu_processor_id) +{ + unsigned int cu_sibling_map_mask; + int first_active_cu; + int i, j, k; + struct kfd_cache_properties *pcache = NULL; + + cu_sibling_map_mask = cu_info->cu_bitmap[0][0]; + cu_sibling_map_mask &= + ((1 << pcache_info[cache_type].num_cu_shared) - 1); + first_active_cu = ffs(cu_sibling_map_mask); + + /* CU could be inactive. In case of shared cache find the first active + * CU. and incase of non-shared cache check if the CU is inactive. If + * inactive active skip it + */ + if (first_active_cu) { + pcache = kfd_alloc_struct(pcache); + if (!pcache) + return -ENOMEM; + + memset(pcache, 0, sizeof(struct kfd_cache_properties)); + pcache->processor_id_low = cu_processor_id + + (first_active_cu - 1); + pcache->cache_level = pcache_info[cache_type].cache_level; + pcache->cache_size = pcache_info[cache_type].cache_size; + + if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE) + pcache->cache_type |= HSA_CACHE_TYPE_DATA; + if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_INST_CACHE) + pcache->cache_type |= HSA_CACHE_TYPE_INSTRUCTION; + if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_CPU_CACHE) + pcache->cache_type |= HSA_CACHE_TYPE_CPU; + if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_SIMD_CACHE) + pcache->cache_type |= HSA_CACHE_TYPE_HSACU; + + /* Sibling map is w.r.t processor_id_low, so shift out + * inactive CU + */ + cu_sibling_map_mask = cu_sibling_map_mask >> (first_active_cu - 1); + k = 0; + + for (i = 0; i < cu_info->num_shader_engines; i++) { + for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) { + pcache->sibling_map[k] = (uint8_t)(cu_sibling_map_mask & 0xFF); + pcache->sibling_map[k+1] = (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF); + pcache->sibling_map[k+2] = (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF); + pcache->sibling_map[k+3] = (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF); + k += 4; + + cu_sibling_map_mask = cu_info->cu_bitmap[i % 4][j + i / 4]; + cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1); + } + } + pcache->sibling_map_size = k; + *props_ext = pcache; + return 0; + } + return 1; +} + +#define KFD_MAX_CACHE_TYPES 6 + +/* kfd_fill_cache_non_crat_info - Fill GPU cache info using kfd_gpu_cache_info + * tables + */ +void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct kfd_dev *kdev) +{ + struct kfd_gpu_cache_info *pcache_info = NULL; + int i, j, k; + int ct = 0; + unsigned int cu_processor_id; + int ret; + unsigned int num_cu_shared; + struct kfd_cu_info cu_info; + struct kfd_cu_info *pcu_info; + int gpu_processor_id; + struct kfd_cache_properties *props_ext; + int num_of_entries = 0; + int num_of_cache_types = 0; + struct kfd_gpu_cache_info cache_info[KFD_MAX_CACHE_TYPES]; + + amdgpu_amdkfd_get_cu_info(kdev->adev, &cu_info); + pcu_info = &cu_info; + + gpu_processor_id = dev->node_props.simd_id_base; + + pcache_info = cache_info; + num_of_cache_types = kfd_get_gpu_cache_info(kdev, &pcache_info); + if (!num_of_cache_types) { + pr_warn("no cache info found\n"); + return; + } + + /* For each type of cache listed in the kfd_gpu_cache_info table, + * go through all available Compute Units. + * The [i,j,k] loop will + * if kfd_gpu_cache_info.num_cu_shared = 1 + * will parse through all available CU + * If (kfd_gpu_cache_info.num_cu_shared != 1) + * then it will consider only one CU from + * the shared unit + */ + for (ct = 0; ct < num_of_cache_types; ct++) { + cu_processor_id = gpu_processor_id; + if (pcache_info[ct].cache_level == 1) { + for (i = 0; i < pcu_info->num_shader_engines; i++) { + for (j = 0; j < pcu_info->num_shader_arrays_per_engine; j++) { + for (k = 0; k < pcu_info->num_cu_per_sh; k += pcache_info[ct].num_cu_shared) { + + ret = fill_in_l1_pcache(&props_ext, pcache_info, pcu_info, + pcu_info->cu_bitmap[i % 4][j + i / 4], ct, + cu_processor_id, k); + + if (ret < 0) + break; + + if (!ret) { + num_of_entries++; + list_add_tail(&props_ext->list, &dev->cache_props); + } + + /* Move to next CU block */ + num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <= + pcu_info->num_cu_per_sh) ? + pcache_info[ct].num_cu_shared : + (pcu_info->num_cu_per_sh - k); + cu_processor_id += num_cu_shared; + } + } + } + } else { + ret = fill_in_l2_l3_pcache(&props_ext, pcache_info, + pcu_info, ct, cu_processor_id); + + if (ret < 0) + break; + + if (!ret) { + num_of_entries++; + list_add_tail(&props_ext->list, &dev->cache_props); + } + } + } + dev->node_props.caches_count += num_of_entries; + pr_debug("Added [%d] GPU cache entries\n", num_of_entries); +} + int kfd_topology_add_device(struct kfd_dev *gpu) { uint32_t gpu_id; @@ -1616,9 +1829,9 @@ int kfd_topology_add_device(struct kfd_dev *gpu) * CRAT to create a new topology device. Once created assign the gpu to * that topology device */ + down_write(&topology_lock); dev = kfd_assign_gpu(gpu); if (!dev) { - down_write(&topology_lock); proximity_domain = ++topology_crat_proximity_domain; res = kfd_create_crat_image_virtual(&crat_image, &image_size, @@ -1630,6 +1843,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) topology_crat_proximity_domain--; return res; } + res = kfd_parse_crat_table(crat_image, &temp_topology_device_list, proximity_domain); @@ -1643,23 +1857,28 @@ int kfd_topology_add_device(struct kfd_dev *gpu) kfd_topology_update_device_list(&temp_topology_device_list, &topology_device_list); + dev = kfd_assign_gpu(gpu); + if (WARN_ON(!dev)) { + res = -ENODEV; + goto err; + } + + /* Fill the cache affinity information here for the GPUs + * using VCRAT + */ + kfd_fill_cache_non_crat_info(dev, gpu); + /* Update the SYSFS tree, since we added another topology * device */ res = kfd_topology_update_sysfs(); - up_write(&topology_lock); - if (!res) sys_props.generation_count++; else pr_err("Failed to update GPU (ID: 0x%x) to sysfs topology. res=%d\n", gpu_id, res); - dev = kfd_assign_gpu(gpu); - if (WARN_ON(!dev)) { - res = -ENODEV; - goto err; - } } + up_write(&topology_lock); dev->gpu_id = gpu_id; gpu->id = gpu_id; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h index 90c069fbd581..fca30d00a9bb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h @@ -80,6 +80,8 @@ struct kfd_mem_properties { struct attribute attr; }; +#define CACHE_SIBLINGMAP_SIZE 64 + struct kfd_cache_properties { struct list_head list; uint32_t processor_id_low; @@ -90,10 +92,11 @@ struct kfd_cache_properties { uint32_t cache_assoc; uint32_t cache_latency; uint32_t cache_type; - uint8_t sibling_map[CRAT_SIBLINGMAP_SIZE]; + uint8_t sibling_map[CACHE_SIBLINGMAP_SIZE]; struct kfd_dev *gpu; struct kobject *kobj; struct attribute attr; + uint32_t sibling_map_size; }; struct kfd_iolink_properties { -- cgit v1.2.3 From 5cefe31b2a34005c83ff45834e21a0578defcbe4 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 3 Nov 2022 11:36:27 +0800 Subject: drm/amd/amdgpu: temporary workaround to skip ras error for gc_v11_0_3 temporary workaround to skip ras error for gc_v11_0_3 until IFWI release later Signed-off-by: Kenneth Feng Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index d799359565b8..96b9054c790c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -4689,10 +4689,10 @@ static int gfx_v11_0_ras_late_init(void *handle) ret = amdgpu_ras_feature_enable(adev, gfx_common_if, true); if (ret) - dev_err(adev->dev, "Failed to enable gfx11 ras feature\n"); + dev_warn(adev->dev, "Failed to enable gfx11 ras feature\n"); kfree(gfx_common_if); - return ret; + return 0; } static int gfx_v11_0_late_init(void *handle) -- cgit v1.2.3 From ec4927d463cbf385be212af1ade9f5a6f1474d4f Mon Sep 17 00:00:00 2001 From: Victor Zhao Date: Wed, 26 Oct 2022 11:48:50 +0800 Subject: drm/amdgpu: fix for suspend/resume sequence under sriov - clear kiq ring after suspend/resume under sriov to aviod kiq ring test failure - update irq after resume to fix kiq interrput loss Signed-off-by: Victor Zhao Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 ++ drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 ++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 ++ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 ++ 5 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 522820eeaa59..5b9f992e4607 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4197,6 +4197,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) } /* Make sure IB tests flushed */ + if (amdgpu_sriov_vf(adev)) + amdgpu_irq_gpu_reset_resume_helper(adev); flush_delayed_work(&adev->delayed_init_work); if (adev->in_s0ix) { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 7853d3ca58cf..49d34c7bbf20 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6909,6 +6909,8 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); } else { memset((void *)mqd, 0, sizeof(*mqd)); + if (amdgpu_sriov_vf(adev) && adev->in_suspend) + amdgpu_ring_clear_ring(ring); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); amdgpu_ring_init_mqd(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 96b9054c790c..9447999a3a48 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -4004,6 +4004,8 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); } else { memset((void *)mqd, 0, sizeof(*mqd)); + if (amdgpu_sriov_vf(adev) && adev->in_suspend) + amdgpu_ring_clear_ring(ring); mutex_lock(&adev->srbm_mutex); soc21_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); amdgpu_ring_init_mqd(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 7f0b18b0d4c4..d47135606e3e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4643,6 +4643,8 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; + if (amdgpu_sriov_vf(adev) && adev->in_suspend) + amdgpu_ring_clear_ring(ring); mutex_lock(&adev->srbm_mutex); vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0); gfx_v8_0_mqd_init(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index ab30c18decfb..676832da75eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3581,6 +3581,8 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; + if (amdgpu_sriov_vf(adev) && adev->in_suspend) + amdgpu_ring_clear_ring(ring); mutex_lock(&adev->srbm_mutex); soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); gfx_v9_0_mqd_init(ring); -- cgit v1.2.3 From 79b72db63392d35a4dbcd4743b95cb668691f790 Mon Sep 17 00:00:00 2001 From: Ao Zhong Date: Mon, 31 Oct 2022 20:37:40 +0100 Subject: drm/amd/display: add DCN support for ARM64 After moving all FPU code to the DML folder, we can enable DCN support for the ARM64 platform. Remove the -mgeneral-regs-only CFLAG from the code in the DML folder that needs to use hardware FPU, and add a control mechanism for ARM Neon. Reviewed-by: Rodrigo Siqueira Signed-off-by: Ao Zhong Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 3 ++- drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/dml/Makefile | 20 ++++++++++++++++---- 3 files changed, 24 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 6925e0280dbe..1cdb379a90d7 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -6,7 +6,8 @@ config DRM_AMD_DC bool "AMD DC - Enable new display engine" default y select SND_HDA_COMPONENT if SND_HDA_CORE - select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128) + # !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752 + select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128 || (ARM64 && KERNEL_MODE_NEON && !CC_IS_CLANG)) help Choose this option if you want to use the new display engine support for AMDGPU. This adds required support for Vega and diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c index ab0c6d191038..1743ca0a3641 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c @@ -31,6 +31,8 @@ #elif defined(CONFIG_PPC64) #include #include +#elif defined(CONFIG_ARM64) +#include #endif /** @@ -99,6 +101,8 @@ void dc_fpu_begin(const char *function_name, const int line) preempt_disable(); enable_kernel_fp(); } +#elif defined(CONFIG_ARM64) + kernel_neon_begin(); #endif } @@ -136,6 +140,8 @@ void dc_fpu_end(const char *function_name, const int line) disable_kernel_fp(); preempt_enable(); } +#elif defined(CONFIG_ARM64) + kernel_neon_end(); #endif } diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index ca7d24000621..0ecea87cf48f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -33,6 +33,10 @@ ifdef CONFIG_PPC64 dml_ccflags := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +dml_rcflags := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifneq ($(call gcc-min-version, 70100),y) IS_OLD_GCC = 1 @@ -55,8 +59,6 @@ frame_warn_flag := -Wframe-larger-than=2048 endif CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) - -ifdef CONFIG_DRM_AMD_DC_DCN CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn10/dcn10_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags) @@ -88,7 +90,6 @@ CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_ccflags) -Wno-tautological-compare CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_rcflags) @@ -105,7 +106,18 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_util_32.o := $(dml_rcf CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_rcflags) -endif +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn10/dcn10_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/display_mode_vba_314.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/display_rq_dlg_calc_314.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/dcn314_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/dcn30_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn32/dcn32_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn321/dcn321_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/dcn31_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn303/dcn303_fpu.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_rcflags) CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_rcflags) -- cgit v1.2.3 From fcf00f8d29f2fc6bf00531a1447be28b99073cc3 Mon Sep 17 00:00:00 2001 From: Xiaogang Chen Date: Fri, 28 Oct 2022 19:13:31 -0500 Subject: drm/amdkfd: Remove skiping userptr buffer mapping when mmu notifier marks it as invalid mmu notifier does not always hold mm->sem during call back. That causes a race condition between kfd userprt buffer mapping and mmu notifier which leds to gpu shadder or SDMA access userptr buffer before it has been mapped to gpu VM. Always map userptr buffer to avoid that though it may make some userprt buffers mapped two times. Suggested-by: Felix Kuehling Signed-off-by: Xiaogang Chen Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index da9d475d7ef2..ba72a910d0d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1907,16 +1907,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( */ mutex_lock(&mem->process_info->lock); - /* Lock mmap-sem. If we find an invalid userptr BO, we can be - * sure that the MMU notifier is no longer running - * concurrently and the queues are actually stopped - */ - if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) { - mmap_write_lock(current->mm); - is_invalid_userptr = atomic_read(&mem->invalid); - mmap_write_unlock(current->mm); - } - mutex_lock(&mem->lock); domain = mem->domain; -- cgit v1.2.3 From de51de9672a17e242ebe3727b5e6ec0f2b4c1ab4 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Wed, 2 Nov 2022 12:21:08 -0700 Subject: drm/i915/guc: Properly initialise kernel contexts If a context has already been registered prior to first submission then context init code was not being called. The noticeable effect of that was the scheduling priority was left at zero (meaning super high priority) instead of being set to normal. This would occur with kernel contexts at start of day as they are manually pinned up front rather than on first submission. So add a call to initialise those when they are pinned. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20221102192109.2492625-2-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 4dbdac8002e3..8fbc36356460 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4111,6 +4111,9 @@ static inline void guc_kernel_context_pin(struct intel_guc *guc, if (context_guc_id_invalid(ce)) pin_guc_id(guc, ce); + if (!test_bit(CONTEXT_GUC_INIT, &ce->flags)) + guc_context_init(ce); + try_context_registration(ce, true); } -- cgit v1.2.3 From 178b8a3668bd63b40303d9dcb17ad58cf4b44007 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Wed, 2 Nov 2022 12:21:09 -0700 Subject: drm/i915/guc: Don't deadlock busyness stats vs reset The engine busyness stats has a worker function to do things like 64bit extend the 32bit hardware counters. The GuC's reset prepare function flushes out this worker function to ensure no corruption happens during the reset. Unforunately, the worker function has an infinite wait for active resets to finish before doing its work. Thus a deadlock would occur if the worker function had actually started just as the reset starts. The function being used to lock the reset-in-progress mutex is called intel_gt_reset_trylock(). However, as noted it does not follow standard 'trylock' conventions and exit if already locked. So rename the current _trylock function to intel_gt_reset_lock_interruptible(), which is the behaviour it actually provides. In addition, add a new implementation of _trylock and call that from the busyness stats worker instead. v2: Rename existing trylock to interruptible rather than trying to preserve the existing (confusing) naming scheme (review comments from Tvrtko). Signed-off-by: John Harrison Reviewed-by: Umesh Nerlige Ramappa Link: https://patchwork.freedesktop.org/patch/msgid/20221102192109.2492625-3-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 18 ++++++++++++++++-- drivers/gpu/drm/i915/gt/intel_reset.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 +++- 4 files changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index e63329bc8065..c29efdef8313 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -330,7 +330,7 @@ retry: if (ret) goto err_rpm; - ret = intel_gt_reset_trylock(ggtt->vm.gt, &srcu); + ret = intel_gt_reset_lock_interruptible(ggtt->vm.gt, &srcu); if (ret) goto err_pages; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 3159df6cdd49..24736ebee17c 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1407,15 +1407,19 @@ out: intel_runtime_pm_put(gt->uncore->rpm, wakeref); } -int intel_gt_reset_trylock(struct intel_gt *gt, int *srcu) +static int _intel_gt_reset_lock(struct intel_gt *gt, int *srcu, bool retry) { might_lock(>->reset.backoff_srcu); - might_sleep(); + if (retry) + might_sleep(); rcu_read_lock(); while (test_bit(I915_RESET_BACKOFF, >->reset.flags)) { rcu_read_unlock(); + if (!retry) + return -EBUSY; + if (wait_event_interruptible(gt->reset.queue, !test_bit(I915_RESET_BACKOFF, >->reset.flags))) @@ -1429,6 +1433,16 @@ int intel_gt_reset_trylock(struct intel_gt *gt, int *srcu) return 0; } +int intel_gt_reset_trylock(struct intel_gt *gt, int *srcu) +{ + return _intel_gt_reset_lock(gt, srcu, false); +} + +int intel_gt_reset_lock_interruptible(struct intel_gt *gt, int *srcu) +{ + return _intel_gt_reset_lock(gt, srcu, true); +} + void intel_gt_reset_unlock(struct intel_gt *gt, int tag) __releases(>->reset.backoff_srcu) { diff --git a/drivers/gpu/drm/i915/gt/intel_reset.h b/drivers/gpu/drm/i915/gt/intel_reset.h index adc734e67387..25c975b6e8fc 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.h +++ b/drivers/gpu/drm/i915/gt/intel_reset.h @@ -39,6 +39,7 @@ int __intel_engine_reset_bh(struct intel_engine_cs *engine, void __i915_request_reset(struct i915_request *rq, bool guilty); int __must_check intel_gt_reset_trylock(struct intel_gt *gt, int *srcu); +int __must_check intel_gt_reset_lock_interruptible(struct intel_gt *gt, int *srcu); void intel_gt_reset_unlock(struct intel_gt *gt, int tag); void intel_gt_set_wedged(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 8fbc36356460..412c2624e119 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1401,7 +1401,9 @@ static void guc_timestamp_ping(struct work_struct *wrk) /* * Synchronize with gt reset to make sure the worker does not - * corrupt the engine/guc stats. + * corrupt the engine/guc stats. NB: can't actually block waiting + * for a reset to complete as the reset requires flushing out + * this worker thread if started. So waiting would deadlock. */ ret = intel_gt_reset_trylock(gt, &srcu); if (ret) -- cgit v1.2.3 From a90accb358ae33ea982a35595573f7a045993f8b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Nov 2022 17:30:24 -0700 Subject: cxl/region: Fix region HPA ordering validation Some regions may not have any address space allocated. Skip them when validating HPA order otherwise a crash like the following may result: devm_cxl_add_region: cxl_acpi cxl_acpi.0: decoder3.4: created region9 BUG: kernel NULL pointer dereference, address: 0000000000000000 [..] RIP: 0010:store_targetN+0x655/0x1740 [cxl_core] [..] Call Trace: kernfs_fop_write_iter+0x144/0x200 vfs_write+0x24a/0x4d0 ksys_write+0x69/0xf0 do_syscall_64+0x3a/0x90 store_targetN+0x655/0x1740: alloc_region_ref at drivers/cxl/core/region.c:676 (inlined by) cxl_port_attach_region at drivers/cxl/core/region.c:850 (inlined by) cxl_region_attach at drivers/cxl/core/region.c:1290 (inlined by) attach_target at drivers/cxl/core/region.c:1410 (inlined by) store_targetN at drivers/cxl/core/region.c:1453 Cc: Fixes: 384e624bb211 ("cxl/region: Attach endpoint decoders") Reviewed-by: Vishal Verma Reviewed-by: Dave Jiang Link: https://lore.kernel.org/r/166752182461.947915.497032805239915067.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams --- drivers/cxl/core/region.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index bb6f4fc84a3f..d26ca7a6beae 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -658,6 +658,9 @@ static struct cxl_region_ref *alloc_region_ref(struct cxl_port *port, xa_for_each(&port->regions, index, iter) { struct cxl_region_params *ip = &iter->region->params; + if (!ip->res) + continue; + if (ip->res->start > p->res->start) { dev_dbg(&cxlr->dev, "%s: HPA order violation %s:%pr vs %pr\n", -- cgit v1.2.3 From 0d9e734018d70cecf79e2e4c6082167160a0f13f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Nov 2022 17:30:30 -0700 Subject: cxl/region: Fix cxl_region leak, cleanup targets at region delete When a region is deleted any targets that have been previously assigned to that region hold references to it. Trigger those references to drop by detaching all targets at unregister_region() time. Otherwise that region object will leak as userspace has lost the ability to detach targets once region sysfs is torn down. Cc: Fixes: b9686e8c8e39 ("cxl/region: Enable the assignment of endpoint decoders to regions") Reviewed-by: Dave Jiang Reviewed-by: Vishal Verma Link: https://lore.kernel.org/r/166752183055.947915.17681995648556534844.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams --- drivers/cxl/core/region.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index d26ca7a6beae..c52465e09f26 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -1557,8 +1557,19 @@ static struct cxl_region *to_cxl_region(struct device *dev) static void unregister_region(void *dev) { struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + int i; device_del(dev); + + /* + * Now that region sysfs is shutdown, the parameter block is now + * read-only, so no need to hold the region rwsem to access the + * region parameters. + */ + for (i = 0; i < p->interleave_ways; i++) + detach_target(cxlr, i); + cxl_region_iomem_release(cxlr); put_device(dev); } -- cgit v1.2.3 From 4d07ae22e79ebc2d7528bbc69daa53b86981cb3a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Nov 2022 17:30:36 -0700 Subject: cxl/pmem: Fix cxl_pmem_region and cxl_memdev leak When a cxl_nvdimm object goes through a ->remove() event (device physically removed, nvdimm-bridge disabled, or nvdimm device disabled), then any associated regions must also be disabled. As highlighted by the cxl-create-region.sh test [1], a single device may host multiple regions, but the driver was only tracking one region at a time. This leads to a situation where only the last enabled region per nvdimm device is cleaned up properly. Other regions are leaked, and this also causes cxl_memdev reference leaks. Fix the tracking by allowing cxl_nvdimm objects to track multiple region associations. Cc: Link: https://github.com/pmem/ndctl/blob/main/test/cxl-create-region.sh [1] Reported-by: Vishal Verma Fixes: 04ad63f086d1 ("cxl/region: Introduce cxl_pmem_region objects") Reviewed-by: Dave Jiang Reviewed-by: Vishal Verma Link: https://lore.kernel.org/r/166752183647.947915.2045230911503793901.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams --- drivers/cxl/core/pmem.c | 2 + drivers/cxl/cxl.h | 2 +- drivers/cxl/pmem.c | 101 +++++++++++++++++++++++++++++++----------------- 3 files changed, 68 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c index 1d12a8206444..36aa5070d902 100644 --- a/drivers/cxl/core/pmem.c +++ b/drivers/cxl/core/pmem.c @@ -188,6 +188,7 @@ static void cxl_nvdimm_release(struct device *dev) { struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev); + xa_destroy(&cxl_nvd->pmem_regions); kfree(cxl_nvd); } @@ -230,6 +231,7 @@ static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_memdev *cxlmd) dev = &cxl_nvd->dev; cxl_nvd->cxlmd = cxlmd; + xa_init(&cxl_nvd->pmem_regions); device_initialize(dev); lockdep_set_class(&dev->mutex, &cxl_nvdimm_key); device_set_pm_not_required(dev); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index f680450f0b16..1164ad49f3d3 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -423,7 +423,7 @@ struct cxl_nvdimm { struct device dev; struct cxl_memdev *cxlmd; struct cxl_nvdimm_bridge *bridge; - struct cxl_pmem_region *region; + struct xarray pmem_regions; }; struct cxl_pmem_region_mapping { diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 0bac05d804bc..4c627d67281a 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -30,17 +30,20 @@ static void unregister_nvdimm(void *nvdimm) struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_nvdimm_bridge *cxl_nvb = cxl_nvd->bridge; struct cxl_pmem_region *cxlr_pmem; + unsigned long index; device_lock(&cxl_nvb->dev); - cxlr_pmem = cxl_nvd->region; dev_set_drvdata(&cxl_nvd->dev, NULL); - cxl_nvd->region = NULL; - device_unlock(&cxl_nvb->dev); + xa_for_each(&cxl_nvd->pmem_regions, index, cxlr_pmem) { + get_device(&cxlr_pmem->dev); + device_unlock(&cxl_nvb->dev); - if (cxlr_pmem) { device_release_driver(&cxlr_pmem->dev); put_device(&cxlr_pmem->dev); + + device_lock(&cxl_nvb->dev); } + device_unlock(&cxl_nvb->dev); nvdimm_delete(nvdimm); cxl_nvd->bridge = NULL; @@ -366,25 +369,49 @@ static int match_cxl_nvdimm(struct device *dev, void *data) static void unregister_nvdimm_region(void *nd_region) { - struct cxl_nvdimm_bridge *cxl_nvb; - struct cxl_pmem_region *cxlr_pmem; + nvdimm_region_delete(nd_region); +} + +static int cxl_nvdimm_add_region(struct cxl_nvdimm *cxl_nvd, + struct cxl_pmem_region *cxlr_pmem) +{ + int rc; + + rc = xa_insert(&cxl_nvd->pmem_regions, (unsigned long)cxlr_pmem, + cxlr_pmem, GFP_KERNEL); + if (rc) + return rc; + + get_device(&cxlr_pmem->dev); + return 0; +} + +static void cxl_nvdimm_del_region(struct cxl_nvdimm *cxl_nvd, + struct cxl_pmem_region *cxlr_pmem) +{ + /* + * It is possible this is called without a corresponding + * cxl_nvdimm_add_region for @cxlr_pmem + */ + cxlr_pmem = xa_erase(&cxl_nvd->pmem_regions, (unsigned long)cxlr_pmem); + if (cxlr_pmem) + put_device(&cxlr_pmem->dev); +} + +static void release_mappings(void *data) +{ int i; + struct cxl_pmem_region *cxlr_pmem = data; + struct cxl_nvdimm_bridge *cxl_nvb = cxlr_pmem->bridge; - cxlr_pmem = nd_region_provider_data(nd_region); - cxl_nvb = cxlr_pmem->bridge; device_lock(&cxl_nvb->dev); for (i = 0; i < cxlr_pmem->nr_mappings; i++) { struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i]; struct cxl_nvdimm *cxl_nvd = m->cxl_nvd; - if (cxl_nvd->region) { - put_device(&cxlr_pmem->dev); - cxl_nvd->region = NULL; - } + cxl_nvdimm_del_region(cxl_nvd, cxlr_pmem); } device_unlock(&cxl_nvb->dev); - - nvdimm_region_delete(nd_region); } static void cxlr_pmem_remove_resource(void *res) @@ -422,7 +449,7 @@ static int cxl_pmem_region_probe(struct device *dev) if (!cxl_nvb->nvdimm_bus) { dev_dbg(dev, "nvdimm bus not found\n"); rc = -ENXIO; - goto err; + goto out_nvb; } memset(&mappings, 0, sizeof(mappings)); @@ -431,7 +458,7 @@ static int cxl_pmem_region_probe(struct device *dev) res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL); if (!res) { rc = -ENOMEM; - goto err; + goto out_nvb; } res->name = "Persistent Memory"; @@ -442,11 +469,11 @@ static int cxl_pmem_region_probe(struct device *dev) rc = insert_resource(&iomem_resource, res); if (rc) - goto err; + goto out_nvb; rc = devm_add_action_or_reset(dev, cxlr_pmem_remove_resource, res); if (rc) - goto err; + goto out_nvb; ndr_desc.res = res; ndr_desc.provider_data = cxlr_pmem; @@ -462,7 +489,7 @@ static int cxl_pmem_region_probe(struct device *dev) nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL); if (!nd_set) { rc = -ENOMEM; - goto err; + goto out_nvb; } ndr_desc.memregion = cxlr->id; @@ -472,9 +499,13 @@ static int cxl_pmem_region_probe(struct device *dev) info = kmalloc_array(cxlr_pmem->nr_mappings, sizeof(*info), GFP_KERNEL); if (!info) { rc = -ENOMEM; - goto err; + goto out_nvb; } + rc = devm_add_action_or_reset(dev, release_mappings, cxlr_pmem); + if (rc) + goto out_nvd; + for (i = 0; i < cxlr_pmem->nr_mappings; i++) { struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i]; struct cxl_memdev *cxlmd = m->cxlmd; @@ -486,7 +517,7 @@ static int cxl_pmem_region_probe(struct device *dev) dev_dbg(dev, "[%d]: %s: no cxl_nvdimm found\n", i, dev_name(&cxlmd->dev)); rc = -ENODEV; - goto err; + goto out_nvd; } /* safe to drop ref now with bridge lock held */ @@ -498,10 +529,17 @@ static int cxl_pmem_region_probe(struct device *dev) dev_dbg(dev, "[%d]: %s: no nvdimm found\n", i, dev_name(&cxlmd->dev)); rc = -ENODEV; - goto err; + goto out_nvd; } - cxl_nvd->region = cxlr_pmem; - get_device(&cxlr_pmem->dev); + + /* + * Pin the region per nvdimm device as those may be released + * out-of-order with respect to the region, and a single nvdimm + * maybe associated with multiple regions + */ + rc = cxl_nvdimm_add_region(cxl_nvd, cxlr_pmem); + if (rc) + goto out_nvd; m->cxl_nvd = cxl_nvd; mappings[i] = (struct nd_mapping_desc) { .nvdimm = nvdimm, @@ -527,27 +565,18 @@ static int cxl_pmem_region_probe(struct device *dev) nvdimm_pmem_region_create(cxl_nvb->nvdimm_bus, &ndr_desc); if (!cxlr_pmem->nd_region) { rc = -ENOMEM; - goto err; + goto out_nvd; } rc = devm_add_action_or_reset(dev, unregister_nvdimm_region, cxlr_pmem->nd_region); -out: +out_nvd: kfree(info); +out_nvb: device_unlock(&cxl_nvb->dev); put_device(&cxl_nvb->dev); return rc; - -err: - dev_dbg(dev, "failed to create nvdimm region\n"); - for (i--; i >= 0; i--) { - nvdimm = mappings[i].nvdimm; - cxl_nvd = nvdimm_provider_data(nvdimm); - put_device(&cxl_nvd->region->dev); - cxl_nvd->region = NULL; - } - goto out; } static struct cxl_driver cxl_pmem_region_driver = { -- cgit v1.2.3 From e4f6dfa9ef756a3934a4caf618b1e86e9e8e21d0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Nov 2022 17:30:54 -0700 Subject: cxl/region: Fix 'distance' calculation with passthrough ports When programming port decode targets, the algorithm wants to ensure that two devices are compatible to be programmed as peers beneath a given port. A compatible peer is a target that shares the same dport, and where that target's interleave position also routes it to the same dport. Compatibility is determined by the device's interleave position being >= to distance. For example, if a given dport can only map every Nth position then positions less than N away from the last target programmed are incompatible. The @distance for the host-bridge's cxl_port in a simple dual-ported host-bridge configuration with 2 direct-attached devices is 1, i.e. An x2 region divided by 2 dports to reach 2 region targets. An x4 region under an x2 host-bridge would need 2 intervening switches where the @distance at the host bridge level is 2 (x4 region divided by 2 switches to reach 4 devices). However, the distance between peers underneath a single ported host-bridge is always zero because there is no limit to the number of devices that can be mapped. In other words, there are no decoders to program in a passthrough, all descendants are mapped and distance only starts matters for the intervening descendant ports of the passthrough port. Add tracking for the number of dports mapped to a port, and use that to detect the passthrough case for calculating @distance. Cc: Reported-by: Bobo WL Reported-by: Jonathan Cameron Link: http://lore.kernel.org/r/20221010172057.00001559@huawei.com Fixes: 27b3f8d13830 ("cxl/region: Program target lists") Reviewed-by: Vishal Verma Link: https://lore.kernel.org/r/166752185440.947915.6617495912508299445.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams --- drivers/cxl/core/port.c | 11 +++++++++-- drivers/cxl/core/region.c | 9 ++++++++- drivers/cxl/cxl.h | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index bffde862de0b..e7556864ea80 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -811,6 +811,7 @@ static struct cxl_dport *find_dport(struct cxl_port *port, int id) static int add_dport(struct cxl_port *port, struct cxl_dport *new) { struct cxl_dport *dup; + int rc; device_lock_assert(&port->dev); dup = find_dport(port, new->port_id); @@ -821,8 +822,14 @@ static int add_dport(struct cxl_port *port, struct cxl_dport *new) dev_name(dup->dport)); return -EBUSY; } - return xa_insert(&port->dports, (unsigned long)new->dport, new, - GFP_KERNEL); + + rc = xa_insert(&port->dports, (unsigned long)new->dport, new, + GFP_KERNEL); + if (rc) + return rc; + + port->nr_dports++; + return 0; } /* diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index c52465e09f26..c0253de74945 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -990,7 +990,14 @@ static int cxl_port_setup_targets(struct cxl_port *port, if (cxl_rr->nr_targets_set) { int i, distance; - distance = p->nr_targets / cxl_rr->nr_targets; + /* + * Passthrough ports impose no distance requirements between + * peers + */ + if (port->nr_dports == 1) + distance = 0; + else + distance = p->nr_targets / cxl_rr->nr_targets; for (i = 0; i < cxl_rr->nr_targets_set; i++) if (ep->dport == cxlsd->target[i]) { rc = check_last_peer(cxled, ep, cxl_rr, diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 1164ad49f3d3..ac75554b5d76 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -457,6 +457,7 @@ struct cxl_pmem_region { * @regions: cxl_region_ref instances, regions mapped by this port * @parent_dport: dport that points to this port in the parent * @decoder_ida: allocator for decoder ids + * @nr_dports: number of entries in @dports * @hdm_end: track last allocated HDM decoder instance for allocation ordering * @commit_end: cursor to track highest committed decoder for commit ordering * @component_reg_phys: component register capability base address (optional) @@ -475,6 +476,7 @@ struct cxl_port { struct xarray regions; struct cxl_dport *parent_dport; struct ida decoder_ida; + int nr_dports; int hdm_end; int commit_end; resource_size_t component_reg_phys; -- cgit v1.2.3 From 8f401ec1c8975eabfe4c089de91cbe058deabf71 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Nov 2022 17:31:00 -0700 Subject: cxl/region: Recycle region ids At region creation time the next region-id is atomically cached so that there is predictability of region device names. If that region is destroyed and then a new one is created the region id increments. That ends up looking like a memory leak, or is otherwise surprising that identifiers roll forward even after destroying all previously created regions. Try to reuse rather than free old region ids at region release time. While this fixes a cosmetic issue, the needlessly advancing memory region-id gives the appearance of a memory leak, hence the "Fixes" tag, but no "Cc: stable" tag. Cc: Ben Widawsky Cc: Jonathan Cameron Fixes: 779dd20cfb56 ("cxl/region: Add region creation support") Reviewed-by: Dave Jiang Reviewed-by: Vishal Verma Link: https://lore.kernel.org/r/166752186062.947915.13200195701224993317.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams --- drivers/cxl/core/region.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index c0253de74945..f9ae5ad284ff 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -1534,9 +1534,24 @@ static const struct attribute_group *region_groups[] = { static void cxl_region_release(struct device *dev) { + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev->parent); struct cxl_region *cxlr = to_cxl_region(dev); + int id = atomic_read(&cxlrd->region_id); + + /* + * Try to reuse the recently idled id rather than the cached + * next id to prevent the region id space from increasing + * unnecessarily. + */ + if (cxlr->id < id) + if (atomic_try_cmpxchg(&cxlrd->region_id, &id, cxlr->id)) { + memregion_free(id); + goto out; + } memregion_free(cxlr->id); +out: + put_device(dev->parent); kfree(cxlr); } @@ -1598,6 +1613,11 @@ static struct cxl_region *cxl_region_alloc(struct cxl_root_decoder *cxlrd, int i device_initialize(dev); lockdep_set_class(&dev->mutex, &cxl_region_key); dev->parent = &cxlrd->cxlsd.cxld.dev; + /* + * Keep root decoder pinned through cxl_region_release to fixup + * region id allocations + */ + get_device(dev->parent); device_set_pm_not_required(dev); dev->bus = &cxl_bus_type; dev->type = &cxl_region_type; -- cgit v1.2.3 From c4f683731db330460d909bd0ca8d5af876fcdc97 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 31 Oct 2022 11:40:18 +0000 Subject: hwmon: (scmi) Register explicitly with Thermal Framework Available sensors are enumerated and reported by the SCMI platform server using a 16bit identification number; not all such sensors are of a type supported by hwmon subsystem and, among the supported ones, only a subset could be temperature sensors that have to be registered with the Thermal Framework. Potential clashes between hwmon channels indexes and the underlying real sensors IDs do not play well with the hwmon<-->thermal bridge automatic registration routines and could need a sensible number of fake dummy sensors to be made up in order to keep indexes and IDs in sync. Avoid to use the hwmon<-->thermal bridge dropping the HWMON_C_REGISTER_TZ attribute and instead explicit register temperature sensors directly with the Thermal Framework. Cc: Daniel Lezcano Cc: Guenter Roeck Cc: linux-hwmon@vger.kernel.org Signed-off-by: Cristian Marussi Acked-by: Sudeep Holla Link: https://lore.kernel.org/r/20221031114018.59048-1-cristian.marussi@arm.com Signed-off-by: Guenter Roeck --- drivers/hwmon/scmi-hwmon.c | 116 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 103 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c index b1329a58ce40..e192f0c67146 100644 --- a/drivers/hwmon/scmi-hwmon.c +++ b/drivers/hwmon/scmi-hwmon.c @@ -20,6 +20,11 @@ struct scmi_sensors { const struct scmi_sensor_info **info[hwmon_max]; }; +struct scmi_thermal_sensor { + const struct scmi_protocol_handle *ph; + const struct scmi_sensor_info *info; +}; + static inline u64 __pow10(u8 x) { u64 r = 1; @@ -64,16 +69,14 @@ static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value) return 0; } -static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, - u32 attr, int channel, long *val) +static int scmi_hwmon_read_scaled_value(const struct scmi_protocol_handle *ph, + const struct scmi_sensor_info *sensor, + long *val) { int ret; u64 value; - const struct scmi_sensor_info *sensor; - struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev); - sensor = *(scmi_sensors->info[type] + channel); - ret = sensor_ops->reading_get(scmi_sensors->ph, sensor->id, &value); + ret = sensor_ops->reading_get(ph, sensor->id, &value); if (ret) return ret; @@ -84,6 +87,17 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, return ret; } +static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + const struct scmi_sensor_info *sensor; + struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev); + + sensor = *(scmi_sensors->info[type] + channel); + + return scmi_hwmon_read_scaled_value(scmi_sensors->ph, sensor, val); +} + static int scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, const char **str) @@ -122,6 +136,25 @@ static struct hwmon_chip_info scmi_chip_info = { .info = NULL, }; +static int scmi_hwmon_thermal_get_temp(struct thermal_zone_device *tz, + int *temp) +{ + int ret; + long value; + struct scmi_thermal_sensor *th_sensor = tz->devdata; + + ret = scmi_hwmon_read_scaled_value(th_sensor->ph, th_sensor->info, + &value); + if (!ret) + *temp = value; + + return ret; +} + +static const struct thermal_zone_device_ops scmi_hwmon_thermal_ops = { + .get_temp = scmi_hwmon_thermal_get_temp, +}; + static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan, struct device *dev, int num, enum hwmon_sensor_types type, u32 config) @@ -149,7 +182,6 @@ static enum hwmon_sensor_types scmi_types[] = { }; static u32 hwmon_attributes[hwmon_max] = { - [hwmon_chip] = HWMON_C_REGISTER_TZ, [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL, [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL, [hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL, @@ -157,6 +189,43 @@ static u32 hwmon_attributes[hwmon_max] = { [hwmon_energy] = HWMON_E_INPUT | HWMON_E_LABEL, }; +static int scmi_thermal_sensor_register(struct device *dev, + const struct scmi_protocol_handle *ph, + const struct scmi_sensor_info *sensor) +{ + struct scmi_thermal_sensor *th_sensor; + struct thermal_zone_device *tzd; + + th_sensor = devm_kzalloc(dev, sizeof(*th_sensor), GFP_KERNEL); + if (!th_sensor) + return -ENOMEM; + + th_sensor->ph = ph; + th_sensor->info = sensor; + + /* + * Try to register a temperature sensor with the Thermal Framework: + * skip sensors not defined as part of any thermal zone (-ENODEV) but + * report any other errors related to misconfigured zones/sensors. + */ + tzd = devm_thermal_of_zone_register(dev, th_sensor->info->id, th_sensor, + &scmi_hwmon_thermal_ops); + if (IS_ERR(tzd)) { + devm_kfree(dev, th_sensor); + + if (PTR_ERR(tzd) != -ENODEV) + return PTR_ERR(tzd); + + dev_dbg(dev, "Sensor '%s' not attached to any thermal zone.\n", + sensor->name); + } else { + dev_dbg(dev, "Sensor '%s' attached to thermal zone ID:%d\n", + sensor->name, tzd->id); + } + + return 0; +} + static int scmi_hwmon_probe(struct scmi_device *sdev) { int i, idx; @@ -164,7 +233,7 @@ static int scmi_hwmon_probe(struct scmi_device *sdev) enum hwmon_sensor_types type; struct scmi_sensors *scmi_sensors; const struct scmi_sensor_info *sensor; - int nr_count[hwmon_max] = {0}, nr_types = 0; + int nr_count[hwmon_max] = {0}, nr_types = 0, nr_count_temp = 0; const struct hwmon_chip_info *chip_info; struct device *hwdev, *dev = &sdev->dev; struct hwmon_channel_info *scmi_hwmon_chan; @@ -208,10 +277,8 @@ static int scmi_hwmon_probe(struct scmi_device *sdev) } } - if (nr_count[hwmon_temp]) { - nr_count[hwmon_chip]++; - nr_types++; - } + if (nr_count[hwmon_temp]) + nr_count_temp = nr_count[hwmon_temp]; scmi_hwmon_chan = devm_kcalloc(dev, nr_types, sizeof(*scmi_hwmon_chan), GFP_KERNEL); @@ -262,8 +329,31 @@ static int scmi_hwmon_probe(struct scmi_device *sdev) hwdev = devm_hwmon_device_register_with_info(dev, "scmi_sensors", scmi_sensors, chip_info, NULL); + if (IS_ERR(hwdev)) + return PTR_ERR(hwdev); - return PTR_ERR_OR_ZERO(hwdev); + for (i = 0; i < nr_count_temp; i++) { + int ret; + + sensor = *(scmi_sensors->info[hwmon_temp] + i); + if (!sensor) + continue; + + /* + * Warn on any misconfiguration related to thermal zones but + * bail out of probing only on memory errors. + */ + ret = scmi_thermal_sensor_register(dev, ph, sensor); + if (ret) { + if (ret == -ENOMEM) + return ret; + dev_warn(dev, + "Thermal zone misconfigured for %s. err=%d\n", + sensor->name, ret); + } + } + + return 0; } static const struct scmi_device_id scmi_id_table[] = { -- cgit v1.2.3 From 1e699e177e339e462cdc8571e3d0fcf29665608e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 4 Nov 2022 16:37:30 -0700 Subject: Revert "hwmon: (pmbus) Add regulator supply into macro" This reverts commit 54cc3dbfc10dc3db7cb1cf49aee4477a8398fbde. Zev Weiss reports that the reverted patch may cause a regulator undercount. Here is his report: ... having regulator-dummy set as a supply on my PMBus regulators (instead of having them as their own top-level regulators without an upstream supply) leads to enable-count underflow errors when disabling them: # echo 0 > /sys/bus/platform/devices/efuse01/state [ 906.094477] regulator-dummy: Underflow of regulator enable count [ 906.100563] Failed to disable vout: -EINVAL [ 136.992676] reg-userspace-consumer efuse01: Failed to configure state: -22 Zev reports that reverting the patch fixes the problem. So let's do that for now. Fixes: 54cc3dbfc10d ("hwmon: (pmbus) Add regulator supply into macro") Cc: Marcello Sylvester Bauer Reported-by: Zev Weiss Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/pmbus.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index 7daaf0caf4d3..10fb17879f8e 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -467,7 +467,6 @@ extern const struct regulator_ops pmbus_regulator_ops; #define PMBUS_REGULATOR_STEP(_name, _id, _voltages, _step) \ [_id] = { \ .name = (_name # _id), \ - .supply_name = "vin", \ .id = (_id), \ .of_match = of_match_ptr(_name # _id), \ .regulators_node = of_match_ptr("regulators"), \ -- cgit v1.2.3 From b4c66425771ddb910316c7b4cd7fa0614098ec45 Mon Sep 17 00:00:00 2001 From: Vikas Gupta Date: Thu, 3 Nov 2022 19:33:24 -0400 Subject: bnxt_en: refactor bnxt_cancel_reservations() Introduce bnxt_clear_reservations() to clear the reserved attributes only. This will be used in the next patch to fix PCI AER handling. Signed-off-by: Vikas Gupta Signed-off-by: Michael Chan Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 04cf7684f1b0..3743d9755eb4 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -9983,17 +9983,12 @@ static int bnxt_try_recover_fw(struct bnxt *bp) return -ENODEV; } -int bnxt_cancel_reservations(struct bnxt *bp, bool fw_reset) +static void bnxt_clear_reservations(struct bnxt *bp, bool fw_reset) { struct bnxt_hw_resc *hw_resc = &bp->hw_resc; - int rc; if (!BNXT_NEW_RM(bp)) - return 0; /* no resource reservations required */ - - rc = bnxt_hwrm_func_resc_qcaps(bp, true); - if (rc) - netdev_err(bp->dev, "resc_qcaps failed\n"); + return; /* no resource reservations required */ hw_resc->resv_cp_rings = 0; hw_resc->resv_stat_ctxs = 0; @@ -10006,6 +10001,20 @@ int bnxt_cancel_reservations(struct bnxt *bp, bool fw_reset) bp->tx_nr_rings = 0; bp->rx_nr_rings = 0; } +} + +int bnxt_cancel_reservations(struct bnxt *bp, bool fw_reset) +{ + int rc; + + if (!BNXT_NEW_RM(bp)) + return 0; /* no resource reservations required */ + + rc = bnxt_hwrm_func_resc_qcaps(bp, true); + if (rc) + netdev_err(bp->dev, "resc_qcaps failed\n"); + + bnxt_clear_reservations(bp, fw_reset); return rc; } -- cgit v1.2.3 From 0cf736a18a1e804037839bd8df9e36f0efdb8745 Mon Sep 17 00:00:00 2001 From: Vikas Gupta Date: Thu, 3 Nov 2022 19:33:25 -0400 Subject: bnxt_en: fix the handling of PCIE-AER Fix the sequence required for PCIE-AER. While slot reset occurs, firmware might not be ready and the driver needs to check for its recovery. We also need to remap the health registers for some chips and clear the resource reservations. The resources will be allocated again during bnxt_io_resume(). Fixes: fb1e6e562b37 ("bnxt_en: Fix AER recovery.") Signed-off-by: Vikas Gupta Signed-off-by: Michael Chan Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 29 +++++++++++++++++++++++++- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 + drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c | 3 ++- 3 files changed, 31 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 3743d9755eb4..f44f9367b7fd 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -13922,7 +13922,9 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev) pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT; struct net_device *netdev = pci_get_drvdata(pdev); struct bnxt *bp = netdev_priv(netdev); - int err = 0, off; + int retry = 0; + int err = 0; + int off; netdev_info(bp->dev, "PCI Slot Reset\n"); @@ -13950,11 +13952,36 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev) pci_restore_state(pdev); pci_save_state(pdev); + bnxt_inv_fw_health_reg(bp); + bnxt_try_map_fw_health_reg(bp); + + /* In some PCIe AER scenarios, firmware may take up to + * 10 seconds to become ready in the worst case. + */ + do { + err = bnxt_try_recover_fw(bp); + if (!err) + break; + retry++; + } while (retry < BNXT_FW_SLOT_RESET_RETRY); + + if (err) { + dev_err(&pdev->dev, "Firmware not ready\n"); + goto reset_exit; + } + err = bnxt_hwrm_func_reset(bp); if (!err) result = PCI_ERS_RESULT_RECOVERED; + + bnxt_ulp_irq_stop(bp); + bnxt_clear_int_mode(bp); + err = bnxt_init_int_mode(bp); + bnxt_ulp_irq_restart(bp, err); } +reset_exit: + bnxt_clear_reservations(bp, true); rtnl_unlock(); return result; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index b1b17f911300..d5fa43cfe524 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1621,6 +1621,7 @@ struct bnxt_fw_health { #define BNXT_FW_RETRY 5 #define BNXT_FW_IF_RETRY 10 +#define BNXT_FW_SLOT_RESET_RETRY 4 enum board_idx { BCM57301, diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c index b01d42928a53..132442f16fe6 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c @@ -476,7 +476,8 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx) memset(ctx->resp, 0, PAGE_SIZE); req_type = le16_to_cpu(ctx->req->req_type); - if (BNXT_NO_FW_ACCESS(bp) && req_type != HWRM_FUNC_RESET) { + if (BNXT_NO_FW_ACCESS(bp) && + (req_type != HWRM_FUNC_RESET && req_type != HWRM_VER_GET)) { netdev_dbg(bp->dev, "hwrm req_type 0x%x skipped, FW channel down\n", req_type); goto exit; -- cgit v1.2.3 From 6d81ea3765dfa6c8a20822613c81edad1c4a16a0 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 3 Nov 2022 19:33:26 -0400 Subject: bnxt_en: Fix possible crash in bnxt_hwrm_set_coal() During the error recovery sequence, the rtnl_lock is not held for the entire duration and some datastructures may be freed during the sequence. Check for the BNXT_STATE_OPEN flag instead of netif_running() to ensure that the device is fully operational before proceeding to reconfigure the coalescing settings. This will fix a possible crash like this: BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 PGD 0 P4D 0 Oops: 0000 [#1] SMP NOPTI CPU: 10 PID: 181276 Comm: ethtool Kdump: loaded Tainted: G IOE --------- - - 4.18.0-348.el8.x86_64 #1 Hardware name: Dell Inc. PowerEdge R740/0F9N89, BIOS 2.3.10 08/15/2019 RIP: 0010:bnxt_hwrm_set_coal+0x1fb/0x2a0 [bnxt_en] Code: c2 66 83 4e 22 08 66 89 46 1c e8 10 cb 00 00 41 83 c6 01 44 39 b3 68 01 00 00 0f 8e a3 00 00 00 48 8b 93 c8 00 00 00 49 63 c6 <48> 8b 2c c2 48 8b 85 b8 02 00 00 48 85 c0 74 2e 48 8b 74 24 08 f6 RSP: 0018:ffffb11c8dcaba50 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff8d168a8b0ac0 RCX: 00000000000000c5 RDX: 0000000000000000 RSI: ffff8d162f72c000 RDI: ffff8d168a8b0b28 RBP: 0000000000000000 R08: b6e1f68a12e9a7eb R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000037 R12: ffff8d168a8b109c R13: ffff8d168a8b10aa R14: 0000000000000000 R15: ffffffffc01ac4e0 FS: 00007f3852e4c740(0000) GS:ffff8d24c0080000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000041b3ee003 CR4: 00000000007706e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: ethnl_set_coalesce+0x3ce/0x4c0 genl_family_rcv_msg_doit.isra.15+0x10f/0x150 genl_family_rcv_msg+0xb3/0x160 ? coalesce_fill_reply+0x480/0x480 genl_rcv_msg+0x47/0x90 ? genl_family_rcv_msg+0x160/0x160 netlink_rcv_skb+0x4c/0x120 genl_rcv+0x24/0x40 netlink_unicast+0x196/0x230 netlink_sendmsg+0x204/0x3d0 sock_sendmsg+0x4c/0x50 __sys_sendto+0xee/0x160 ? syscall_trace_enter+0x1d3/0x2c0 ? __audit_syscall_exit+0x249/0x2a0 __x64_sys_sendto+0x24/0x30 do_syscall_64+0x5b/0x1a0 entry_SYSCALL_64_after_hwframe+0x65/0xca RIP: 0033:0x7f38524163bb Fixes: 2151fe0830fd ("bnxt_en: Handle RESET_NOTIFY async event from firmware.") Reviewed-by: Somnath Kotur Signed-off-by: Michael Chan Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index f57e524c7e30..8cad15c458b3 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -162,7 +162,7 @@ static int bnxt_set_coalesce(struct net_device *dev, } reset_coalesce: - if (netif_running(dev)) { + if (test_bit(BNXT_STATE_OPEN, &bp->state)) { if (update_stats) { rc = bnxt_close_nic(bp, true, false); if (!rc) -- cgit v1.2.3 From 02597d39145bb0aa81d04bf39b6a913ce9a9d465 Mon Sep 17 00:00:00 2001 From: Alex Barba Date: Thu, 3 Nov 2022 19:33:27 -0400 Subject: bnxt_en: fix potentially incorrect return value for ndo_rx_flow_steer In the bnxt_en driver ndo_rx_flow_steer returns '0' whenever an entry that we are attempting to steer is already found. This is not the correct behavior. The return code should be the value/index that corresponds to the entry. Returning zero all the time causes the RFS records to be incorrect unless entry '0' is the correct one. As flows migrate to different cores this can create entries that are not correct. Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.") Reported-by: Akshay Navgire Signed-off-by: Alex Barba Signed-off-by: Andy Gospodarek Signed-off-by: Michael Chan Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f44f9367b7fd..c78b6e9dea2c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -12903,8 +12903,8 @@ static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, rcu_read_lock(); hlist_for_each_entry_rcu(fltr, head, hash) { if (bnxt_fltr_match(fltr, new_fltr)) { + rc = fltr->sw_id; rcu_read_unlock(); - rc = 0; goto err_free; } } -- cgit v1.2.3 From b7cbc6740bd6ad5d43345a2504f7e4beff0d709f Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Thu, 3 Nov 2022 14:28:30 -0400 Subject: net: fman: Unregister ethernet device on removal When the mac device gets removed, it leaves behind the ethernet device. This will result in a segfault next time the ethernet device accesses mac_dev. Remove the ethernet device when we get removed to prevent this. This is not completely reversible, since some resources aren't cleaned up properly, but that can be addressed later. Fixes: 3933961682a3 ("fsl/fman: Add FMan MAC driver") Signed-off-by: Sean Anderson Link: https://lore.kernel.org/r/20221103182831.2248833-1-sean.anderson@seco.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fman/mac.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index 65df308bad97..13e67f2864be 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -487,12 +487,21 @@ _return_of_node_put: return err; } +static int mac_remove(struct platform_device *pdev) +{ + struct mac_device *mac_dev = platform_get_drvdata(pdev); + + platform_device_unregister(mac_dev->priv->eth_dev); + return 0; +} + static struct platform_driver mac_driver = { .driver = { .name = KBUILD_MODNAME, .of_match_table = mac_match, }, .probe = mac_probe, + .remove = mac_remove, }; builtin_platform_driver(mac_driver); -- cgit v1.2.3 From 819b885cd886c193782891c4f51bbcab3de119a4 Mon Sep 17 00:00:00 2001 From: John Thomson Date: Sat, 5 Nov 2022 06:52:41 +1000 Subject: phy: ralink: mt7621-pci: add sentinel to quirks table With mt7621 soc_dev_attr fixed to register the soc as a device, kernel will experience an oops in soc_device_match_attr This quirk test was introduced in the staging driver in commit 9445ccb3714c ("staging: mt7621-pci-phy: add quirks for 'E2' revision using 'soc_device_attribute'"). The staging driver was removed, and later re-added in commit d87da32372a0 ("phy: ralink: Add PHY driver for MT7621 PCIe PHY") for kernel 5.11 Link: https://lore.kernel.org/lkml/26ebbed1-0fe9-4af9-8466-65f841d0b382@app.fastmail.com Fixes: d87da32372a0 ("phy: ralink: Add PHY driver for MT7621 PCIe PHY") Signed-off-by: John Thomson Acked-by: Sergio Paracuellos Link: https://lore.kernel.org/r/20221104205242.3440388-2-git@johnthomson.fastmail.com.au Signed-off-by: Vinod Koul --- drivers/phy/ralink/phy-mt7621-pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/phy/ralink/phy-mt7621-pci.c b/drivers/phy/ralink/phy-mt7621-pci.c index 5e6530f545b5..85888ab2d307 100644 --- a/drivers/phy/ralink/phy-mt7621-pci.c +++ b/drivers/phy/ralink/phy-mt7621-pci.c @@ -280,7 +280,8 @@ static struct phy *mt7621_pcie_phy_of_xlate(struct device *dev, } static const struct soc_device_attribute mt7621_pci_quirks_match[] = { - { .soc_id = "mt7621", .revision = "E2" } + { .soc_id = "mt7621", .revision = "E2" }, + { /* sentinel */ } }; static const struct regmap_config mt7621_pci_phy_regmap_config = { -- cgit v1.2.3 From ea6143a86c67110a2c62deaf70d0b7b92e4f865f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:32 +1000 Subject: drm/nouveau/disp: move and extend the role of outp acquire/release methods There are various pieces of information we pass to NVKM about the next modeset, which are generally used while handling supervisor interrupts. We had to start passing in some information about audio requirements a while back to allocate an appropriate SOR in ACQUIRE, so we may as well move all this type of information here for other protocols too. Certain methods will be blocked on non-acquired outputs now, preventing NULL pointer derefs from KMS driver bugs. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv50/crc.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 98 +++++++--------------- drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 10 --- drivers/gpu/drm/nouveau/include/nvif/if0012.h | 32 +++++++ drivers/gpu/drm/nouveau/include/nvif/outp.h | 10 +++ drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 - drivers/gpu/drm/nouveau/nvif/outp.c | 81 +++++++++++++++++- .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 18 ---- drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 61 ++++++++++++++ 9 files changed, 213 insertions(+), 100 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.c b/drivers/gpu/drm/nouveau/dispnv50/crc.c index b834e8a9ae77..9c942fbd836d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crc.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crc.c @@ -463,7 +463,7 @@ void nv50_crc_atomic_set(struct nv50_head *head, if (!outp) return; - func->set_src(head, outp->or, nv50_crc_source_type(outp, asyh->crc.src), + func->set_src(head, outp->outp.or.id, nv50_crc_source_type(outp, asyh->crc.src), &crc->ctx[crc->ctx_idx]); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index aa94f8e284dd..093321a93046 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -317,52 +317,6 @@ nv50_outp_dump_caps(struct nouveau_drm *drm, outp->base.base.name, outp->caps.dp_interlace); } -static void -nv50_outp_release(struct nouveau_encoder *nv_encoder) -{ - struct nv50_disp *disp = nv50_disp(nv_encoder->base.base.dev); - struct { - struct nv50_disp_mthd_v1 base; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_RELEASE, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = nv_encoder->dcb->hashm, - }; - - nvif_mthd(&disp->disp->object, 0, &args, sizeof(args)); - nv_encoder->or = -1; - nv_encoder->link = 0; -} - -static int -nv50_outp_acquire(struct nouveau_encoder *nv_encoder, bool hda) -{ - struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); - struct nv50_disp *disp = nv50_disp(drm->dev); - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_acquire_v0 info; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_ACQUIRE, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = nv_encoder->dcb->hashm, - .info.hda = hda, - }; - int ret; - - ret = nvif_mthd(&disp->disp->object, 0, &args, sizeof(args)); - if (ret) { - NV_ERROR(drm, "error acquiring output path: %d\n", ret); - return ret; - } - - nv_encoder->or = args.info.or; - nv_encoder->link = args.info.link; - return 0; -} - static int nv50_outp_atomic_check_view(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, @@ -489,9 +443,9 @@ nv50_dac_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *st struct nv50_core *core = nv50_disp(encoder->dev)->core; const u32 ctrl = NVDEF(NV507D, DAC_SET_CONTROL, OWNER, NONE); - core->func->dac->ctrl(core, nv_encoder->or, ctrl, NULL); + core->func->dac->ctrl(core, nv_encoder->outp.or.id, ctrl, NULL); nv_encoder->crtc = NULL; - nv50_outp_release(nv_encoder); + nvif_outp_release(&nv_encoder->outp); } static void @@ -516,9 +470,9 @@ nv50_dac_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta ctrl |= NVDEF(NV507D, DAC_SET_CONTROL, PROTOCOL, RGB_CRT); - nv50_outp_acquire(nv_encoder, false); + nvif_outp_acquire_rgb_crt(&nv_encoder->outp); - core->func->dac->ctrl(core, nv_encoder->or, ctrl, asyh); + core->func->dac->ctrl(core, nv_encoder->outp.or.id, ctrl, asyh); asyh->or.depth = 0; nv_encoder->crtc = &nv_crtc->base; @@ -634,7 +588,7 @@ nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id, nv_connector = nouveau_connector(nv_encoder->audio.connector); nv_crtc = nouveau_crtc(nv_encoder->crtc); - if (!nv_crtc || nv_encoder->or != port || nv_crtc->index != dev_id) + if (!nv_crtc || nv_encoder->outp.or.id != port || nv_crtc->index != dev_id) continue; *enabled = nv_encoder->audio.enabled; @@ -724,6 +678,7 @@ nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nv50_disp *disp = nv50_disp(encoder->dev); + struct nvif_outp *outp = &nv_encoder->outp; struct { struct nv50_disp_mthd_v1 base; struct nv50_disp_sor_hda_eld_v0 eld; @@ -743,8 +698,7 @@ nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) } mutex_unlock(&drm->audio.lock); - nv50_audio_component_eld_notify(drm->audio.component, nv_encoder->or, - nv_crtc->index); + nv50_audio_component_eld_notify(drm->audio.component, outp->or.id, nv_crtc->index); } static void @@ -755,6 +709,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc, struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nv50_disp *disp = nv50_disp(encoder->dev); + struct nvif_outp *outp = &nv_encoder->outp; struct __packed { struct { struct nv50_disp_mthd_v1 mthd; @@ -783,8 +738,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc, mutex_unlock(&drm->audio.lock); - nv50_audio_component_eld_notify(drm->audio.component, nv_encoder->or, - nv_crtc->index); + nv50_audio_component_eld_notify(drm->audio.component, outp->or.id, nv_crtc->index); } /****************************************************************************** @@ -1107,10 +1061,12 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st if (WARN_ON(!mstc)) return; - if (!mstm->links++) - nv50_outp_acquire(mstm->outp, false /*XXX: MST audio.*/); + if (!mstm->links++) { + /*XXX: MST audio. */ + nvif_outp_acquire_dp(&mstm->outp->outp, false); + } - if (mstm->outp->link & 1) + if (mstm->outp->outp.or.link & 1) proto = NV917D_SOR_SET_CONTROL_PROTOCOL_DP_A; else proto = NV917D_SOR_SET_CONTROL_PROTOCOL_DP_B; @@ -1405,7 +1361,7 @@ nv50_mstm_prepare(struct drm_atomic_state *state, if (mstm->disabled) { if (!mstm->links) - nv50_outp_release(mstm->outp); + nvif_outp_release(&mstm->outp->outp); mstm->disabled = false; } } @@ -1623,7 +1579,7 @@ nv50_sor_update(struct nouveau_encoder *nv_encoder, u8 head, asyh->or.depth = depth; } - core->func->sor->ctrl(core, nv_encoder->or, nv_encoder->ctrl, asyh); + core->func->sor->ctrl(core, nv_encoder->outp.or.id, nv_encoder->ctrl, asyh); } /* TODO: Should we extend this to PWM-only backlights? @@ -1667,7 +1623,7 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *st nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0); nv50_audio_disable(encoder, nv_crtc); nv50_hdmi_disable(&nv_encoder->base.base, nv_crtc); - nv50_outp_release(nv_encoder); + nvif_outp_release(&nv_encoder->outp); nv_encoder->crtc = NULL; } @@ -1707,11 +1663,11 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta disp->disp->object.oclass >= GF110_DISP) && drm_detect_monitor_audio(nv_connector->edid)) hda = true; - nv50_outp_acquire(nv_encoder, hda); switch (nv_encoder->dcb->type) { case DCB_OUTPUT_TMDS: - if (nv_encoder->link & 1) { + nvif_outp_acquire_tmds(&nv_encoder->outp, hda); + if (nv_encoder->outp.or.link & 1) { proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_A; /* Only enable dual-link if: * - Need to (i.e. rate > 165MHz) @@ -1758,12 +1714,14 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta lvds.lvds.script |= 0x0200; } + nvif_outp_acquire_lvds(&nv_encoder->outp); nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds)); break; case DCB_OUTPUT_DP: + nvif_outp_acquire_dp(&nv_encoder->outp, hda); depth = nv50_dp_bpc_to_depth(asyh->or.bpc); - if (nv_encoder->link & 1) + if (nv_encoder->outp.or.link & 1) proto = NV887D_SOR_SET_CONTROL_PROTOCOL_DP_A; else proto = NV887D_SOR_SET_CONTROL_PROTOCOL_DP_B; @@ -1921,9 +1879,9 @@ nv50_pior_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *s struct nv50_core *core = nv50_disp(encoder->dev)->core; const u32 ctrl = NVDEF(NV507D, PIOR_SET_CONTROL, OWNER, NONE); - core->func->pior->ctrl(core, nv_encoder->or, ctrl, NULL); + core->func->pior->ctrl(core, nv_encoder->outp.or.id, ctrl, NULL); nv_encoder->crtc = NULL; - nv50_outp_release(nv_encoder); + nvif_outp_release(&nv_encoder->outp); } static void @@ -1944,8 +1902,6 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st break; } - nv50_outp_acquire(nv_encoder, false); - switch (asyh->or.bpc) { case 10: asyh->or.depth = NV837D_PIOR_SET_CONTROL_PIXEL_DEPTH_BPP_30_444; break; case 8: asyh->or.depth = NV837D_PIOR_SET_CONTROL_PIXEL_DEPTH_BPP_24_444; break; @@ -1955,15 +1911,19 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st switch (nv_encoder->dcb->type) { case DCB_OUTPUT_TMDS: + ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC); + nvif_outp_acquire_tmds(&nv_encoder->outp, false); + break; case DCB_OUTPUT_DP: ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC); + nvif_outp_acquire_dp(&nv_encoder->outp, false); break; default: BUG(); break; } - core->func->pior->ctrl(core, nv_encoder->or, ctrl, asyh); + core->func->pior->ctrl(core, nv_encoder->outp.or.id, ctrl, asyh); nv_encoder->crtc = &nv_crtc->base; } diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index 56affb606adf..37e669b9c4dc 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -28,8 +28,6 @@ struct nv50_disp_scanoutpos_v0 { struct nv50_disp_mthd_v1 { __u8 version; -#define NV50_DISP_MTHD_V1_ACQUIRE 0x01 -#define NV50_DISP_MTHD_V1_RELEASE 0x02 #define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 #define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22 #define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23 @@ -41,14 +39,6 @@ struct nv50_disp_mthd_v1 { __u8 pad06[2]; }; -struct nv50_disp_acquire_v0 { - __u8 version; - __u8 or; - __u8 link; - __u8 hda; - __u8 pad04[4]; -}; - struct nv50_disp_sor_hda_eld_v0 { __u8 version; __u8 pad01[7]; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index 243bd35d942f..8bc00a8c525a 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -11,6 +11,8 @@ union nvif_outp_args { }; #define NVIF_OUTP_V0_LOAD_DETECT 0x00 +#define NVIF_OUTP_V0_ACQUIRE 0x01 +#define NVIF_OUTP_V0_RELEASE 0x02 union nvif_outp_load_detect_args { struct nvif_outp_load_detect_v0 { @@ -20,4 +22,34 @@ union nvif_outp_load_detect_args { __u32 data; /*TODO: move vbios loadval parsing into nvkm */ } v0; }; + +union nvif_outp_acquire_args { + struct nvif_outp_acquire_v0 { + __u8 version; +#define NVIF_OUTP_ACQUIRE_V0_RGB_CRT 0x00 +#define NVIF_OUTP_ACQUIRE_V0_TV 0x01 +#define NVIF_OUTP_ACQUIRE_V0_TMDS 0x02 +#define NVIF_OUTP_ACQUIRE_V0_LVDS 0x03 +#define NVIF_OUTP_ACQUIRE_V0_DP 0x04 + __u8 proto; + __u8 or; + __u8 link; + __u8 pad04[4]; + union { + struct { + __u8 hda; + __u8 pad01[7]; + } tmds; + struct { + __u8 hda; + __u8 pad01[7]; + } dp; + }; + } v0; +}; + +union nvif_outp_release_args { + struct nvif_outp_release_vn { + } vn; +}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index 0d6aa07a9184..2a45b57b1f75 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -6,9 +6,19 @@ struct nvif_disp; struct nvif_outp { struct nvif_object object; + + struct { + int id; + int link; + } or; }; int nvif_outp_ctor(struct nvif_disp *, const char *name, int id, struct nvif_outp *); void nvif_outp_dtor(struct nvif_outp *); int nvif_outp_load_detect(struct nvif_outp *, u32 loadval); +int nvif_outp_acquire_rgb_crt(struct nvif_outp *); +int nvif_outp_acquire_tmds(struct nvif_outp *, bool hda); +int nvif_outp_acquire_lvds(struct nvif_outp *); +int nvif_outp_acquire_dp(struct nvif_outp *, bool hda); +void nvif_outp_release(struct nvif_outp *); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index b72e5783a00f..b6c51fc60d13 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -48,7 +48,6 @@ struct nouveau_encoder { struct dcb_output *dcb; struct nvif_outp outp; int or; - int link; struct i2c_adapter *i2c; struct nvkm_i2c_aux *aux; diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 7bfe91a8d6f9..bd20f75045dc 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -26,6 +26,81 @@ #include #include +void +nvif_outp_release(struct nvif_outp *outp) +{ + int ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_RELEASE, NULL, 0); + NVIF_ERRON(ret, &outp->object, "[RELEASE]"); + outp->or.id = -1; +} + +static inline int +nvif_outp_acquire(struct nvif_outp *outp, u8 proto, struct nvif_outp_acquire_v0 *args) +{ + int ret; + + args->version = 0; + args->proto = proto; + + ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_ACQUIRE, args, sizeof(*args)); + if (ret) + return ret; + + outp->or.id = args->or; + outp->or.link = args->link; + return 0; +} + +int +nvif_outp_acquire_dp(struct nvif_outp *outp, bool hda) +{ + struct nvif_outp_acquire_v0 args; + int ret; + + args.dp.hda = hda; + + ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DP, &args); + NVIF_ERRON(ret, &outp->object, + "[ACQUIRE proto:DP hda:%d] or:%d link:%d", args.dp.hda, args.or, args.link); + return ret; +} + +int +nvif_outp_acquire_lvds(struct nvif_outp *outp) +{ + struct nvif_outp_acquire_v0 args; + int ret; + + ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_LVDS, &args); + NVIF_ERRON(ret, &outp->object, "[ACQUIRE proto:LVDS] or:%d link:%d", args.or, args.link); + return ret; +} + +int +nvif_outp_acquire_tmds(struct nvif_outp *outp, bool hda) +{ + struct nvif_outp_acquire_v0 args; + int ret; + + args.tmds.hda = hda; + + ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_TMDS, &args); + NVIF_ERRON(ret, &outp->object, + "[ACQUIRE proto:TMDS hda:%d] or:%d link:%d", args.tmds.hda, args.or, args.link); + return ret; +} + +int +nvif_outp_acquire_rgb_crt(struct nvif_outp *outp) +{ + struct nvif_outp_acquire_v0 args; + int ret; + + ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_RGB_CRT, &args); + NVIF_ERRON(ret, &outp->object, "[ACQUIRE proto:RGB_CRT] or:%d", args.or); + return ret; +} + int nvif_outp_load_detect(struct nvif_outp *outp, u32 loadval) { @@ -58,5 +133,9 @@ nvif_outp_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_out ret = nvif_object_ctor(&disp->object, name ?: "nvifOutp", id, NVIF_CLASS_OUTP, &args, sizeof(args), &outp->object); NVIF_ERRON(ret, &disp->object, "[NEW outp id:%d]", id); - return ret; + if (ret) + return ret; + + outp->or.id = -1; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index 0af45ccd140c..341f244cddb7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -91,24 +91,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } switch (mthd * !!outp) { - case NV50_DISP_MTHD_V1_ACQUIRE: { - union { - struct nv50_disp_acquire_v0 v0; - } *args = data; - int ret = -ENOSYS; - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, args->v0.hda); - if (ret == 0) { - args->v0.or = outp->ior->id; - args->v0.link = outp->ior->asy.link; - } - } - return ret; - } - break; - case NV50_DISP_MTHD_V1_RELEASE: - nvkm_outp_release(outp, NVKM_OUTP_USER); - return 0; case NV50_DISP_MTHD_V1_SOR_HDA_ELD: { union { struct nv50_disp_sor_hda_eld_v0 v0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index abedb3e86361..edbed699ade2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -25,6 +25,49 @@ #include +static int +nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc) +{ + union nvif_outp_release_args *args = argv; + + if (argc != sizeof(args->vn)) + return -ENOSYS; + + nvkm_outp_release(outp, NVKM_OUTP_USER); + return 0; +} + +static int +nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) +{ + union nvif_outp_acquire_args *args = argv; + int ret; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + switch (args->v0.proto) { + case NVIF_OUTP_ACQUIRE_V0_RGB_CRT: + case NVIF_OUTP_ACQUIRE_V0_LVDS: + ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, false); + break; + case NVIF_OUTP_ACQUIRE_V0_TMDS: + case NVIF_OUTP_ACQUIRE_V0_DP: + ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, args->v0.dp.hda); + break; + default: + ret = -EINVAL; + break; + } + + if (ret) + return ret; + + args->v0.or = outp->ior->id; + args->v0.link = outp->ior->asy.link; + return 0; +} + static int nvkm_uoutp_mthd_load_detect(struct nvkm_outp *outp, void *argv, u32 argc) { @@ -48,11 +91,24 @@ nvkm_uoutp_mthd_load_detect(struct nvkm_outp *outp, void *argv, u32 argc) return ret; } +static int +nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc) +{ + switch (mthd) { + case NVIF_OUTP_V0_RELEASE : return nvkm_uoutp_mthd_release (outp, argv, argc); + default: + break; + } + + return -EINVAL; +} + static int nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc) { switch (mthd) { case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, argv, argc); + case NVIF_OUTP_V0_ACQUIRE : return nvkm_uoutp_mthd_acquire (outp, argv, argc); default: break; } @@ -73,6 +129,11 @@ nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) if (ret <= 0) goto done; + if (outp->ior) + ret = nvkm_uoutp_mthd_acquired(outp, mthd, argv, argc); + else + ret = -EIO; + done: mutex_unlock(&disp->super.mutex); return ret; -- cgit v1.2.3 From 9793083f1dd9da8dda0ef68e90934dd7d112203b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:32 +1000 Subject: drm/nouveau/disp: move LVDS protocol information into acquire Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 32 +++++++--------------- drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 8 ------ drivers/gpu/drm/nouveau/include/nvif/if0012.h | 5 ++++ drivers/gpu/drm/nouveau/include/nvif/outp.h | 2 +- drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h | 8 +----- drivers/gpu/drm/nouveau/nvif/outp.c | 9 ++++-- drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c | 10 ++++--- drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 5 ++++ .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 16 ----------- drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 16 ++++++++++- 10 files changed, 50 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 093321a93046..0a8404686f16 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1635,15 +1635,6 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta struct nv50_head_atom *asyh = nv50_head_atom(drm_atomic_get_new_crtc_state(state, &nv_crtc->base)); struct drm_display_mode *mode = &asyh->state.adjusted_mode; - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_lvds_script_v0 lvds; - } lvds = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = nv_encoder->dcb->hashm, - }; struct nv50_disp *disp = nv50_disp(encoder->dev); struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); @@ -1652,7 +1643,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta struct nouveau_backlight *backlight; #endif struct nvbios *bios = &drm->vbios; - bool hda = false; + bool lvds_dual = false, lvds_8bpc = false, hda = false; u8 proto = NV507D_SOR_SET_CONTROL_PROTOCOL_CUSTOM; u8 depth = NV837D_SOR_SET_CONTROL_PIXEL_DEPTH_DEFAULT; @@ -1689,33 +1680,30 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta proto = NV507D_SOR_SET_CONTROL_PROTOCOL_LVDS_CUSTOM; if (bios->fp_no_ddc) { - if (bios->fp.dual_link) - lvds.lvds.script |= 0x0100; - if (bios->fp.if_is_24bit) - lvds.lvds.script |= 0x0200; + lvds_dual = bios->fp.dual_link; + lvds_8bpc = bios->fp.if_is_24bit; } else { if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { if (((u8 *)nv_connector->edid)[121] == 2) - lvds.lvds.script |= 0x0100; + lvds_dual = true; } else if (mode->clock >= bios->fp.duallink_transition_clk) { - lvds.lvds.script |= 0x0100; + lvds_dual = true; } - if (lvds.lvds.script & 0x0100) { + if (lvds_dual) { if (bios->fp.strapless_is_24bit & 2) - lvds.lvds.script |= 0x0200; + lvds_8bpc = true; } else { if (bios->fp.strapless_is_24bit & 1) - lvds.lvds.script |= 0x0200; + lvds_8bpc = true; } if (asyh->or.bpc == 8) - lvds.lvds.script |= 0x0200; + lvds_8bpc = true; } - nvif_outp_acquire_lvds(&nv_encoder->outp); - nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds)); + nvif_outp_acquire_lvds(&nv_encoder->outp, lvds_dual, lvds_8bpc); break; case DCB_OUTPUT_DP: nvif_outp_acquire_dp(&nv_encoder->outp, hda); diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index 37e669b9c4dc..f371fc7a1d10 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -30,7 +30,6 @@ struct nv50_disp_mthd_v1 { __u8 version; #define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 #define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22 -#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23 #define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25 #define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26 __u8 method; @@ -58,13 +57,6 @@ struct nv50_disp_sor_hdmi_pwr_v0 { __u8 pad07[1]; }; -struct nv50_disp_sor_lvds_script_v0 { - __u8 version; - __u8 pad01[1]; - __u16 script; - __u8 pad04[4]; -}; - struct nv50_disp_sor_dp_mst_link_v0 { __u8 version; __u8 state; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index 8bc00a8c525a..4fcb9e4f5d76 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -40,6 +40,11 @@ union nvif_outp_acquire_args { __u8 hda; __u8 pad01[7]; } tmds; + struct { + __u8 dual; + __u8 bpc8; + __u8 pad02[6]; + } lvds; struct { __u8 hda; __u8 pad01[7]; diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index 2a45b57b1f75..e247d441afc1 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -18,7 +18,7 @@ void nvif_outp_dtor(struct nvif_outp *); int nvif_outp_load_detect(struct nvif_outp *, u32 loadval); int nvif_outp_acquire_rgb_crt(struct nvif_outp *); int nvif_outp_acquire_tmds(struct nvif_outp *, bool hda); -int nvif_outp_acquire_lvds(struct nvif_outp *); +int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8); int nvif_outp_acquire_dp(struct nvif_outp *, bool hda); void nvif_outp_release(struct nvif_outp *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index 8b5d8a434be8..eaf10f5d505e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -31,13 +31,7 @@ struct nvkm_disp { struct { unsigned long mask; int nr; - } wndw, head, dac; - - struct { - unsigned long mask; - int nr; - u32 lvdsconf; - } sor; + } wndw, head, dac, sor; struct { unsigned long mask; diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index bd20f75045dc..58cd629657fb 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -66,13 +66,18 @@ nvif_outp_acquire_dp(struct nvif_outp *outp, bool hda) } int -nvif_outp_acquire_lvds(struct nvif_outp *outp) +nvif_outp_acquire_lvds(struct nvif_outp *outp, bool dual, bool bpc8) { struct nvif_outp_acquire_v0 args; int ret; + args.lvds.dual = dual; + args.lvds.bpc8 = bpc8; + ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_LVDS, &args); - NVIF_ERRON(ret, &outp->object, "[ACQUIRE proto:LVDS] or:%d link:%d", args.or, args.link); + NVIF_ERRON(ret, &outp->object, + "[ACQUIRE proto:LVDS dual:%d 8bpc:%d] or:%d link:%d", + args.lvds.dual, args.lvds.bpc8, args.or, args.link); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index a46e13cc9ff1..55ac6d70e950 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -1238,6 +1238,8 @@ nv50_disp_super_2_2(struct nvkm_disp *disp, struct nvkm_head *head) if (!ior) return; + outp = ior->asy.outp; + /* For some reason, NVIDIA decided not to: * * A) Give dual-link LVDS a separate EVO protocol, like for TMDS. @@ -1247,13 +1249,13 @@ nv50_disp_super_2_2(struct nvkm_disp *disp, struct nvkm_head *head) * Override the values we usually read from HW with the same * data we pass though an ioctl instead. */ - if (ior->type == SOR && ior->asy.proto == LVDS) { - head->asy.or.depth = (disp->sor.lvdsconf & 0x0200) ? 24 : 18; - ior->asy.link = (disp->sor.lvdsconf & 0x0100) ? 3 : 1; + if (outp && ior->type == SOR && ior->asy.proto == LVDS) { + head->asy.or.depth = outp->lvds.bpc8 ? 24 : 18; + ior->asy.link = outp->lvds.dual ? 3 : 1; } /* Handle any link training, etc. */ - if ((outp = ior->asy.outp) && outp->func->acquire) + if (outp && outp->func->acquire) outp->func->acquire(outp); /* Execute OnInt2 IED script. */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index 3f3924c41957..16aadcedcbda 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -27,6 +27,11 @@ struct nvkm_outp { struct nvkm_ior *ior; union { + struct { + bool dual; + bool bpc8; + } lvds; + struct { struct nvbios_dpout info; u8 version; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index 341f244cddb7..f028ab17f8cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -169,22 +169,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) return 0; } break; - case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: { - union { - struct nv50_disp_sor_lvds_script_v0 v0; - } *args = data; - int ret = -ENOSYS; - nvif_ioctl(object, "disp sor lvds script size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "disp sor lvds script " - "vers %d name %04x\n", - args->v0.version, args->v0.script); - disp->sor.lvdsconf = args->v0.script; - return 0; - } else - return ret; - } - break; case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: { union { struct nv50_disp_sor_dp_mst_link_v0 v0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index edbed699ade2..7e0cef0f80a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -37,6 +37,18 @@ nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc) return 0; } +static int +nvkm_uoutp_mthd_acquire_lvds(struct nvkm_outp *outp, bool dual, bool bpc8) +{ + if (outp->info.type != DCB_OUTPUT_LVDS) + return -EINVAL; + + outp->lvds.dual = dual; + outp->lvds.bpc8 = bpc8; + + return nvkm_outp_acquire(outp, NVKM_OUTP_USER, false); +} + static int nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) { @@ -48,13 +60,15 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) switch (args->v0.proto) { case NVIF_OUTP_ACQUIRE_V0_RGB_CRT: - case NVIF_OUTP_ACQUIRE_V0_LVDS: ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, false); break; case NVIF_OUTP_ACQUIRE_V0_TMDS: case NVIF_OUTP_ACQUIRE_V0_DP: ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, args->v0.dp.hda); break; + case NVIF_OUTP_ACQUIRE_V0_LVDS: + ret = nvkm_uoutp_mthd_acquire_lvds(outp, args->v0.lvds.dual, args->v0.lvds.bpc8); + break; default: ret = -EINVAL; break; -- cgit v1.2.3 From 59dc2a7e7c6a0d4a2a2c4dafea874af484fc0592 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 31 Oct 2022 11:17:45 +0100 Subject: ACPI: video: Improve Chromebook checks 2 improvements for the Chromebook handling in acpi_video_get_backlight_type(): 1. Also check for the "GOOG000C" ACPI HID used on some models 2. Move the Chromebook check to above the ACPI-video check normally Chromebooks don't have ACPI video backlight support, but when flashed with upstream coreboot builds they may have ACPI video backlight support, but native should still be used/preferred then. Suggested-by: Mr. Chromebox Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 9cd8797d12bb..06aaec2e378b 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -670,7 +670,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = { static bool google_cros_ec_present(void) { - return acpi_dev_found("GOOG0004"); + return acpi_dev_found("GOOG0004") || acpi_dev_found("GOOG000C"); } /* @@ -718,6 +718,10 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) if (apple_gmux_present()) return acpi_backlight_apple_gmux; + /* Chromebooks should always prefer native backlight control. */ + if (google_cros_ec_present() && native_available) + return acpi_backlight_native; + /* On systems with ACPI video use either native or ACPI video. */ if (video_caps & ACPI_VIDEO_BACKLIGHT) { /* @@ -735,13 +739,6 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) return acpi_backlight_video; } - /* - * Chromebooks that don't have backlight handle in ACPI table - * are supposed to use native backlight if it's available. - */ - if (google_cros_ec_present() && native_available) - return acpi_backlight_native; - /* No ACPI video (old hw), use vendor specific fw methods. */ return acpi_backlight_vendor; } -- cgit v1.2.3 From 531705a765493655472c993627106e19f7e5a6d2 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Thu, 3 Nov 2022 17:05:37 +0800 Subject: net: lapbether: fix issue of dev reference count leakage in lapbeth_device_event() When following tests are performed, it will cause dev reference counting leakage. a)ip link add bond2 type bond mode balance-rr b)ip link set bond2 up c)ifenslave -f bond2 rose1 d)ip link del bond2 When new bond device is created, the default type of the bond device is ether. And the bond device is up, lapbeth_device_event() receives the message and creates a new lapbeth device. In this case, the reference count value of dev is hold once. But after "ifenslave -f bond2 rose1" command is executed, the type of the bond device is changed to rose. When the bond device is unregistered, lapbeth_device_event() will not put the dev reference count. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Zhengchao Shao Signed-off-by: David S. Miller --- drivers/net/wan/lapbether.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 960f1393595c..cb360dca3250 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -446,7 +446,7 @@ static int lapbeth_device_event(struct notifier_block *this, if (dev_net(dev) != &init_net) return NOTIFY_DONE; - if (!dev_is_ethdev(dev)) + if (!dev_is_ethdev(dev) && !lapbeth_get_x25_dev(dev)) return NOTIFY_DONE; switch (event) { -- cgit v1.2.3 From 85cbaf032d3cd9f595152625eda5d4ecb1d6d78d Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Thu, 3 Nov 2022 17:09:05 +0800 Subject: hamradio: fix issue of dev reference count leakage in bpq_device_event() When following tests are performed, it will cause dev reference counting leakage. a)ip link add bond2 type bond mode balance-rr b)ip link set bond2 up c)ifenslave -f bond2 rose1 d)ip link del bond2 When new bond device is created, the default type of the bond device is ether. And the bond device is up, bpq_device_event() receives the message and creates a new bpq device. In this case, the reference count value of dev is hold once. But after "ifenslave -f bond2 rose1" command is executed, the type of the bond device is changed to rose. When the bond device is unregistered, bpq_device_event() will not put the dev reference count. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Zhengchao Shao Signed-off-by: David S. Miller --- drivers/net/hamradio/bpqether.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 30af0081e2be..83a16d10eedb 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -533,7 +533,7 @@ static int bpq_device_event(struct notifier_block *this, if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; - if (!dev_is_ethdev(dev)) + if (!dev_is_ethdev(dev) && !bpq_get_ax25_dev(dev)) return NOTIFY_DONE; switch (event) { -- cgit v1.2.3 From f25caaca424703d5a0607310f0452f978f1f78d9 Mon Sep 17 00:00:00 2001 From: HW He Date: Thu, 3 Nov 2022 18:40:00 +0800 Subject: net: wwan: iosm: fix memory leak in ipc_wwan_dellink IOSM driver registers network device without setting the needs_free_netdev flag, and does NOT call free_netdev() when unregisters network device, which causes a memory leak. This patch sets needs_free_netdev to true when registers network device, which makes netdev subsystem call free_netdev() automatically after unregister_netdevice(). Fixes: 2a54f2c77934 ("net: iosm: net driver") Signed-off-by: HW He Reviewed-by: Loic Poulain Signed-off-by: Zhaoping Shu Signed-off-by: David S. Miller --- drivers/net/wwan/iosm/iosm_ipc_wwan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c index 2f1f8b5d5b59..0108d8d01ff2 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c +++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c @@ -168,6 +168,7 @@ static void ipc_wwan_setup(struct net_device *iosm_dev) iosm_dev->max_mtu = ETH_MAX_MTU; iosm_dev->flags = IFF_POINTOPOINT | IFF_NOARP; + iosm_dev->needs_free_netdev = true; iosm_dev->netdev_ops = &ipc_inm_ops; } -- cgit v1.2.3 From 668205b9c9f94d5ed6ab00cce9a46a654c2b5d16 Mon Sep 17 00:00:00 2001 From: HW He Date: Thu, 3 Nov 2022 18:54:19 +0800 Subject: net: wwan: mhi: fix memory leak in mhi_mbim_dellink MHI driver registers network device without setting the needs_free_netdev flag, and does NOT call free_netdev() when unregisters network device, which causes a memory leak. This patch sets needs_free_netdev to true when registers network device, which makes netdev subsystem call free_netdev() automatically after unregister_netdevice(). Fixes: aa730a9905b7 ("net: wwan: Add MHI MBIM network driver") Signed-off-by: HW He Signed-off-by: Zhaoping Shu Signed-off-by: David S. Miller --- drivers/net/wwan/mhi_wwan_mbim.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c index 6872782e8dd8..ef70bb7c88ad 100644 --- a/drivers/net/wwan/mhi_wwan_mbim.c +++ b/drivers/net/wwan/mhi_wwan_mbim.c @@ -582,6 +582,7 @@ static void mhi_mbim_setup(struct net_device *ndev) ndev->min_mtu = ETH_MIN_MTU; ndev->max_mtu = MHI_MAX_BUF_SZ - ndev->needed_headroom; ndev->tx_queue_len = 1000; + ndev->needs_free_netdev = true; } static const struct wwan_ops mhi_mbim_wwan_ops = { -- cgit v1.2.3 From f9027f88f7d1dc2b0ed1afbf28f22992d72d7efe Mon Sep 17 00:00:00 2001 From: Zhaoping Shu Date: Thu, 3 Nov 2022 19:08:49 +0800 Subject: net: wwan: iosm: Remove unnecessary if_mutex lock These WWAN network interface operations (create/delete/open/close) are already protected by RTNL lock, i.e., wwan_ops.newlink(), wwan_ops.dellink(), net_device_ops.ndo_open() and net_device.ndo_stop() are called with RTNL lock held. Therefore, this patch removes the unnecessary if_mutex. Signed-off-by: Zhaoping Shu Signed-off-by: David S. Miller --- drivers/net/wwan/iosm/iosm_ipc_wwan.c | 42 +++++------------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c index 0108d8d01ff2..4c9022a93e01 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c +++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c @@ -40,13 +40,11 @@ struct iosm_netdev_priv { * @ipc_imem: Pointer to imem data-struct * @sub_netlist: List of active netdevs * @dev: Pointer device structure - * @if_mutex: Mutex used for add and remove interface id */ struct iosm_wwan { struct iosm_imem *ipc_imem; struct iosm_netdev_priv __rcu *sub_netlist[IP_MUX_SESSION_END + 1]; struct device *dev; - struct mutex if_mutex; /* Mutex used for add and remove interface id */ }; /* Bring-up the wwan net link */ @@ -55,14 +53,11 @@ static int ipc_wwan_link_open(struct net_device *netdev) struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); struct iosm_wwan *ipc_wwan = priv->ipc_wwan; int if_id = priv->if_id; - int ret; if (if_id < IP_MUX_SESSION_START || if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL; - mutex_lock(&ipc_wwan->if_mutex); - /* get channel id */ priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id); @@ -70,8 +65,7 @@ static int ipc_wwan_link_open(struct net_device *netdev) dev_err(ipc_wwan->dev, "cannot connect wwan0 & id %d to the IPC mem layer", if_id); - ret = -ENODEV; - goto out; + return -ENODEV; } /* enable tx path, DL data may follow */ @@ -80,10 +74,7 @@ static int ipc_wwan_link_open(struct net_device *netdev) dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d", priv->ch_id, priv->if_id); - ret = 0; -out: - mutex_unlock(&ipc_wwan->if_mutex); - return ret; + return 0; } /* Bring-down the wwan net link */ @@ -93,11 +84,9 @@ static int ipc_wwan_link_stop(struct net_device *netdev) netif_stop_queue(netdev); - mutex_lock(&priv->ipc_wwan->if_mutex); ipc_imem_sys_wwan_close(priv->ipc_wwan->ipc_imem, priv->if_id, priv->ch_id); priv->ch_id = -1; - mutex_unlock(&priv->ipc_wwan->if_mutex); return 0; } @@ -190,26 +179,17 @@ static int ipc_wwan_newlink(void *ctxt, struct net_device *dev, priv->netdev = dev; priv->ipc_wwan = ipc_wwan; - mutex_lock(&ipc_wwan->if_mutex); - if (rcu_access_pointer(ipc_wwan->sub_netlist[if_id])) { - err = -EBUSY; - goto out_unlock; - } + if (rcu_access_pointer(ipc_wwan->sub_netlist[if_id])) + return -EBUSY; err = register_netdevice(dev); if (err) - goto out_unlock; + return err; rcu_assign_pointer(ipc_wwan->sub_netlist[if_id], priv); - mutex_unlock(&ipc_wwan->if_mutex); - netif_device_attach(dev); return 0; - -out_unlock: - mutex_unlock(&ipc_wwan->if_mutex); - return err; } static void ipc_wwan_dellink(void *ctxt, struct net_device *dev, @@ -223,17 +203,12 @@ static void ipc_wwan_dellink(void *ctxt, struct net_device *dev, if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))) return; - mutex_lock(&ipc_wwan->if_mutex); - if (WARN_ON(rcu_access_pointer(ipc_wwan->sub_netlist[if_id]) != priv)) - goto unlock; + return; RCU_INIT_POINTER(ipc_wwan->sub_netlist[if_id], NULL); /* unregistering includes synchronize_net() */ unregister_netdevice_queue(dev, head); - -unlock: - mutex_unlock(&ipc_wwan->if_mutex); } static const struct wwan_ops iosm_wwan_ops = { @@ -324,12 +299,9 @@ struct iosm_wwan *ipc_wwan_init(struct iosm_imem *ipc_imem, struct device *dev) ipc_wwan->dev = dev; ipc_wwan->ipc_imem = ipc_imem; - mutex_init(&ipc_wwan->if_mutex); - /* WWAN core will create a netdev for the default IP MUX channel */ if (wwan_register_ops(ipc_wwan->dev, &iosm_wwan_ops, ipc_wwan, IP_MUX_SESSION_DEFAULT)) { - mutex_destroy(&ipc_wwan->if_mutex); kfree(ipc_wwan); return NULL; } @@ -342,7 +314,5 @@ void ipc_wwan_deinit(struct iosm_wwan *ipc_wwan) /* This call will remove all child netdev(s) */ wwan_unregister_ops(ipc_wwan->dev); - mutex_destroy(&ipc_wwan->if_mutex); - kfree(ipc_wwan); } -- cgit v1.2.3 From cf53db768a8790fdaae2fa3a81322b080285f7e5 Mon Sep 17 00:00:00 2001 From: Yuan Can Date: Thu, 3 Nov 2022 01:47:05 +0000 Subject: drm/vc4: Fix missing platform_unregister_drivers() call in vc4_drm_register() A problem about modprobe vc4 failed is triggered with the following log given: [ 420.327987] Error: Driver 'vc4_hvs' is already registered, aborting... [ 420.333904] failed to register platform driver vc4_hvs_driver [vc4]: -16 modprobe: ERROR: could not insert 'vc4': Device or resource busy The reason is that vc4_drm_register() returns platform_driver_register() directly without checking its return value, if platform_driver_register() fails, it returns without unregistering all the vc4 drivers, resulting the vc4 can never be installed later. A simple call graph is shown as below: vc4_drm_register() platform_register_drivers() # all vc4 drivers are registered platform_driver_register() driver_register() bus_add_driver() priv = kzalloc(...) # OOM happened # return without unregister drivers Fixing this problem by checking the return value of platform_driver_register() and do platform_unregister_drivers() if error happened. Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.") Signed-off-by: Yuan Can Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20221103014705.109322-1-yuancan@huawei.com --- drivers/gpu/drm/vc4/vc4_drv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 2027063fdc30..8c329c071c62 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -476,7 +476,12 @@ static int __init vc4_drm_register(void) if (ret) return ret; - return platform_driver_register(&vc4_platform_driver); + ret = platform_driver_register(&vc4_platform_driver); + if (ret) + platform_unregister_drivers(component_drivers, + ARRAY_SIZE(component_drivers)); + + return ret; } static void __exit vc4_drm_unregister(void) -- cgit v1.2.3 From 454d61a56d5e4c8cd9905f81d475d23f86f370af Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 4 Nov 2022 18:06:29 +0100 Subject: ACPI: video: Make acpi_video_backlight_use_native() always return true Testing has shown that there are quite a few laptop models which rely on native backlight control and which do not support ACPI video bus backlight control, causing __acpi_video_get_backlight_type() to return vendor. Known Windows laptop models affected by this are: Acer Aspire 1640 HP Compaq nc6120 IBM ThinkPad X40 System76 Starling Star1 and the following MacBook models are affected too: Apple MacBook 2.1 Apple MacBook 4.1 Apple MacBook Pro 7.1 the list of affected Windows laptop models is likely just the top of the iceberg. So for now lets undo the change to not register native backlight class devices when __acpi_video_get_backlight_type() != native. Since as part of the backlight-detect refactor the detection code now relies on the GPU drivers calling acpi_video_backlight_use_native() to learn that native backlight support is available we cannot just remove the acpi_video_backlight_use_native() calls from the GPU drivers. Instead modify acpi_video_backlight_use_native() to always return true for now. This is meant as a temporary work-around, which will be removed again when the heuristics from __acpi_video_get_backlight_type() have been improved so that they will return native on affected models. Reported-by: Matthew Garrett Reported-by: John Warriner Reported-by: Scott Ostrander Reported-by: Matthias Rampke Reported-by: Milan Hodoscek Signed-off-by: Hans de Goede --- drivers/acpi/video_detect.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 06aaec2e378b..c02e960cdbe3 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -751,6 +751,18 @@ EXPORT_SYMBOL(acpi_video_get_backlight_type); bool acpi_video_backlight_use_native(void) { - return __acpi_video_get_backlight_type(true) == acpi_backlight_native; + /* + * Call __acpi_video_get_backlight_type() to let it know that + * a native backlight is available. + */ + __acpi_video_get_backlight_type(true); + + /* + * For now just always return true. There is a whole bunch of laptop + * models where (video_caps & ACPI_VIDEO_BACKLIGHT) is false causing + * __acpi_video_get_backlight_type() to return vendor, while these + * models only have a native backlight control. + */ + return true; } EXPORT_SYMBOL(acpi_video_backlight_use_native); -- cgit v1.2.3 From f46acc1efd4b5846de9fa05f966e504f328f34a6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 31 Oct 2022 21:20:59 +0100 Subject: ACPI: video: Add backlight=native DMI quirk for Dell G15 5515 The Dell G15 5515 has the WMI interface (and WMI call returns) expected by the nvidia-wmi-ec-backlight interface. But the backlight class device registered by the nvidia-wmi-ec-backlight driver does not actually work. The amdgpu_bl0 native GPU backlight class device does actually work, add a backlight=native DMI quirk for this. Reported-by: Iris Reviewed-by: Daniel Dadap Signed-off-by: Hans de Goede --- Changes in v2: - Add a comment that this needs to be revisited when dynamic-mux support gets added (suggested by: Daniel Dadap) --- drivers/acpi/video_detect.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index c02e960cdbe3..b2a616287638 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -645,6 +645,20 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, + /* + * Models which have nvidia-ec-wmi support, but should not use it. + * Note this indicates a likely firmware bug on these models and should + * be revisited if/when Linux gets support for dynamic mux mode. + */ + { + .callback = video_detect_force_native, + /* Dell G15 5515 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"), + }, + }, + /* * Desktops which falsely report a backlight and which our heuristics * for this do not catch. -- cgit v1.2.3 From a231224a601c1924b9df620281ad04472900d75f Mon Sep 17 00:00:00 2001 From: Manyi Li Date: Tue, 18 Oct 2022 17:53:23 +0800 Subject: platform/x86: ideapad-laptop: Disable touchpad_switch Ideapads for "Lenovo Yoga 3 Pro 1370" and "ZhaoYang K4e-IML" do not use EC to switch touchpad. Reading VPCCMD_R_TOUCHPAD will return zero thus touchpad may be blocked unexpectedly. Signed-off-by: Manyi Li Link: https://lore.kernel.org/r/20221018095323.14591-1-limanyi@uniontech.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/ideapad-laptop.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index abd0c81d62c4..33b3dfdd1b08 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -1533,6 +1533,24 @@ static const struct dmi_system_id hw_rfkill_list[] = { {} }; +static const struct dmi_system_id no_touchpad_switch_list[] = { + { + .ident = "Lenovo Yoga 3 Pro 1370", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3"), + }, + }, + { + .ident = "ZhaoYang K4e-IML", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ZhaoYang K4e-IML"), + }, + }, + {} +}; + static void ideapad_check_features(struct ideapad_private *priv) { acpi_handle handle = priv->adev->handle; @@ -1541,7 +1559,12 @@ static void ideapad_check_features(struct ideapad_private *priv) priv->features.hw_rfkill_switch = dmi_check_system(hw_rfkill_list); /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */ - priv->features.touchpad_ctrl_via_ec = !acpi_dev_present("ELAN0634", NULL, -1); + if (acpi_dev_present("ELAN0634", NULL, -1)) + priv->features.touchpad_ctrl_via_ec = 0; + else if (dmi_check_system(no_touchpad_switch_list)) + priv->features.touchpad_ctrl_via_ec = 0; + else + priv->features.touchpad_ctrl_via_ec = 1; if (!read_ec_data(handle, VPCCMD_R_FAN, &val)) priv->features.fan_mode = true; -- cgit v1.2.3 From 0df044b34bf33e7e35c32b3bf6747fde6279c162 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 25 Oct 2022 16:11:31 +0200 Subject: platform/x86: touchscreen_dmi: Add info for the RCA Cambio W101 v2 2-in-1 Add touchscreen info for the RCA Cambio W101 v2 2-in-1. Link: https://github.com/onitake/gsl-firmware/discussions/193 Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20221025141131.509211-1-hdegoede@redhat.com --- drivers/platform/x86/touchscreen_dmi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index bc97bfa8e8a6..baae3120efd0 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -770,6 +770,22 @@ static const struct ts_dmi_data predia_basic_data = { .properties = predia_basic_props, }; +static const struct property_entry rca_cambio_w101_v2_props[] = { + PROPERTY_ENTRY_U32("touchscreen-min-x", 4), + PROPERTY_ENTRY_U32("touchscreen-min-y", 20), + PROPERTY_ENTRY_U32("touchscreen-size-x", 1644), + PROPERTY_ENTRY_U32("touchscreen-size-y", 874), + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-rca-cambio-w101-v2.fw"), + PROPERTY_ENTRY_U32("silead,max-fingers", 10), + { } +}; + +static const struct ts_dmi_data rca_cambio_w101_v2_data = { + .acpi_name = "MSSL1680:00", + .properties = rca_cambio_w101_v2_props, +}; + static const struct property_entry rwc_nanote_p8_props[] = { PROPERTY_ENTRY_U32("touchscreen-min-y", 46), PROPERTY_ENTRY_U32("touchscreen-size-x", 1728), @@ -1409,6 +1425,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = { DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"), }, }, + { + /* RCA Cambio W101 v2 */ + /* https://github.com/onitake/gsl-firmware/discussions/193 */ + .driver_data = (void *)&rca_cambio_w101_v2_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "RCA"), + DMI_MATCH(DMI_PRODUCT_NAME, "W101SA23T1"), + }, + }, { /* RWC NANOTE P8 */ .driver_data = (void *)&rwc_nanote_p8_data, -- cgit v1.2.3 From 1598bfa8e1faa932de42e1ee7628a1c4c4263f0a Mon Sep 17 00:00:00 2001 From: Jorge Lopez Date: Fri, 28 Oct 2022 10:55:27 -0500 Subject: platform/x86: hp_wmi: Fix rfkill causing soft blocked wifi After upgrading BIOS to U82 01.02.01 Rev.A, the console is flooded strange char "^@" which printed out every second and makes login nearly impossible. Also the below messages were shown both in console and journal/dmesg every second: usb 1-3: Device not responding to setup address. usb 1-3: device not accepting address 4, error -71 usb 1-3: device descriptor read/all, error -71 usb usb1-port3: unable to enumerate USB device Wifi is soft blocked by checking rfkill. When unblocked manually, after few seconds it would be soft blocked again. So I was suspecting something triggered rfkill to soft block wifi. At the end it was fixed by removing hp_wmi module. The root cause is the way hp-wmi driver handles command 1B on post-2009 BIOS. In pre-2009 BIOS, command 1Bh return 0x4 to indicate that BIOS no longer controls the power for the wireless devices. Signed-off-by: Jorge Lopez Link: https://bugzilla.kernel.org/show_bug.cgi?id=216468 Reviewed-by: Mario Limonciello Link: https://lore.kernel.org/r/20221028155527.7724-1-jorge.lopez2@hp.com Cc: stable@vger.kernel.org Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/hp-wmi.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 627a6d0eaf83..12449038bed1 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -1300,8 +1300,16 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) wwan_rfkill = NULL; rfkill2_count = 0; - if (hp_wmi_rfkill_setup(device)) - hp_wmi_rfkill2_setup(device); + /* + * In pre-2009 BIOS, command 1Bh return 0x4 to indicate that + * BIOS no longer controls the power for the wireless + * devices. All features supported by this command will no + * longer be supported. + */ + if (!hp_wmi_bios_2009_later()) { + if (hp_wmi_rfkill_setup(device)) + hp_wmi_rfkill2_setup(device); + } err = hp_wmi_hwmon_init(); -- cgit v1.2.3 From bcdfa1f77ea7f67368d20384932a9d1e3047ddd2 Mon Sep 17 00:00:00 2001 From: "David E. Box" Date: Fri, 4 Nov 2022 20:42:28 -0700 Subject: platform/x86/intel/pmt: Sapphire Rapids PMT errata fix On Sapphire Rapids, due to a hardware issue affecting the PUNIT telemetry region, reads that are not done in QWORD quantities and alignment may return incorrect data. Use a custom 64-bit copy for this region. Signed-off-by: David E. Box Link: https://lore.kernel.org/r/20221105034228.1376677-1-david.e.box@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/pmt/class.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c index 53d7fd2943b4..46598dcb634a 100644 --- a/drivers/platform/x86/intel/pmt/class.c +++ b/drivers/platform/x86/intel/pmt/class.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -19,6 +20,7 @@ #define PMT_XA_START 0 #define PMT_XA_MAX INT_MAX #define PMT_XA_LIMIT XA_LIMIT(PMT_XA_START, PMT_XA_MAX) +#define GUID_SPR_PUNIT 0x9956f43f bool intel_pmt_is_early_client_hw(struct device *dev) { @@ -33,6 +35,29 @@ bool intel_pmt_is_early_client_hw(struct device *dev) } EXPORT_SYMBOL_GPL(intel_pmt_is_early_client_hw); +static inline int +pmt_memcpy64_fromio(void *to, const u64 __iomem *from, size_t count) +{ + int i, remain; + u64 *buf = to; + + if (!IS_ALIGNED((unsigned long)from, 8)) + return -EFAULT; + + for (i = 0; i < count/8; i++) + buf[i] = readq(&from[i]); + + /* Copy any remaining bytes */ + remain = count % 8; + if (remain) { + u64 tmp = readq(&from[i]); + + memcpy(&buf[i], &tmp, remain); + } + + return count; +} + /* * sysfs */ @@ -54,7 +79,11 @@ intel_pmt_read(struct file *filp, struct kobject *kobj, if (count > entry->size - off) count = entry->size - off; - memcpy_fromio(buf, entry->base + off, count); + if (entry->guid == GUID_SPR_PUNIT) + /* PUNIT on SPR only supports aligned 64-bit read */ + count = pmt_memcpy64_fromio(buf, entry->base + off, count); + else + memcpy_fromio(buf, entry->base + off, count); return count; } -- cgit v1.2.3 From a977ece5773b6746b814aac410da4776023db239 Mon Sep 17 00:00:00 2001 From: Ivan Hu Date: Wed, 2 Nov 2022 10:05:48 +0800 Subject: platform/x86/intel/hid: Add some ACPI device IDs Add INTC1076 (JasonLake), INTC1077 (MeteorLake) and INTC1078 (RaptorLake) devices IDs. Signed-off-by: Ivan Hu Link: https://lore.kernel.org/r/20221102020548.5225-1-ivan.hu@canonical.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/hid.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c index 79cff1fc675c..b6313ecd190c 100644 --- a/drivers/platform/x86/intel/hid.c +++ b/drivers/platform/x86/intel/hid.c @@ -27,6 +27,9 @@ static const struct acpi_device_id intel_hid_ids[] = { {"INTC1051", 0}, {"INTC1054", 0}, {"INTC1070", 0}, + {"INTC1076", 0}, + {"INTC1077", 0}, + {"INTC1078", 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, intel_hid_ids); -- cgit v1.2.3 From 53eb64c88f17b14b324fbdfd417f56c5d3fa6fee Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 4 Nov 2022 17:49:16 +0200 Subject: platform/x86: p2sb: Don't fail if unknown CPU is found We have accessing P2SB from a very few places for quite known hardware. When a new SoC appears in intel-family.h it's not obvious that it needs to be added to p2sb.c as well. Instead, provide default BDF and refactor p2sb_get_devfn() to always succeed. If in the future we would need to exclude something, we may add a list of unsupported IDs. Without this change the iTCO on Intel Comet Lake SoCs became unavailable: i801_smbus 0000:00:1f.4: failed to create iTCO device Fixes: 5c7b9167ddf8 ("i2c: i801: convert to use common P2SB accessor") Reported-and-tested-by: Jarkko Nikula Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221104154916.35231-1-andriy.shevchenko@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/p2sb.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/p2sb.c b/drivers/platform/x86/p2sb.c index 384d0962ae93..1cf2471d54dd 100644 --- a/drivers/platform/x86/p2sb.c +++ b/drivers/platform/x86/p2sb.c @@ -19,26 +19,23 @@ #define P2SBC 0xe0 #define P2SBC_HIDE BIT(8) +#define P2SB_DEVFN_DEFAULT PCI_DEVFN(31, 1) + static const struct x86_cpu_id p2sb_cpu_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, PCI_DEVFN(13, 0)), - X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, PCI_DEVFN(31, 1)), - X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D, PCI_DEVFN(31, 1)), - X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, PCI_DEVFN(31, 1)), - X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, PCI_DEVFN(31, 1)), - X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, PCI_DEVFN(31, 1)), - X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, PCI_DEVFN(31, 1)), {} }; static int p2sb_get_devfn(unsigned int *devfn) { + unsigned int fn = P2SB_DEVFN_DEFAULT; const struct x86_cpu_id *id; id = x86_match_cpu(p2sb_cpu_ids); - if (!id) - return -ENODEV; + if (id) + fn = (unsigned int)id->driver_data; - *devfn = (unsigned int)id->driver_data; + *devfn = fn; return 0; } -- cgit v1.2.3 From ebb5fd38f41132e6924cb33b647337f4a5d5360c Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 26 Oct 2022 12:42:03 -0700 Subject: mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI Several SDHCI drivers need to deactivate command queueing in their reset hook (see sdhci_cqhci_reset() / sdhci-pci-core.c, for example), and several more are coming. Those reset implementations have some small subtleties (e.g., ordering of initialization of SDHCI vs. CQHCI might leave us resetting with a NULL ->cqe_private), and are often identical across different host drivers. We also don't want to force a dependency between SDHCI and CQHCI, or vice versa; non-SDHCI drivers use CQHCI, and SDHCI drivers might support command queueing through some other means. So, implement a small helper, to avoid repeating the same mistakes in different drivers. Simply stick it in a header, because it's so small it doesn't deserve its own module right now, and inlining to each driver is pretty reasonable. This is marked for -stable, as it is an important prerequisite patch for several SDHCI controller bugfixes that follow. Cc: Signed-off-by: Brian Norris Acked-by: Adrian Hunter Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20221026124150.v4.1.Ie85faa09432bfe1b0890d8c24ff95e17f3097317@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-cqhci.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 drivers/mmc/host/sdhci-cqhci.h (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-cqhci.h b/drivers/mmc/host/sdhci-cqhci.h new file mode 100644 index 000000000000..cf8e7ba71bbd --- /dev/null +++ b/drivers/mmc/host/sdhci-cqhci.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2022 The Chromium OS Authors + * + * Support that applies to the combination of SDHCI and CQHCI, while not + * expressing a dependency between the two modules. + */ + +#ifndef __MMC_HOST_SDHCI_CQHCI_H__ +#define __MMC_HOST_SDHCI_CQHCI_H__ + +#include "cqhci.h" +#include "sdhci.h" + +static inline void sdhci_and_cqhci_reset(struct sdhci_host *host, u8 mask) +{ + if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL) && + host->mmc->cqe_private) + cqhci_deactivate(host->mmc); + + sdhci_reset(host, mask); +} + +#endif /* __MMC_HOST_SDHCI_CQHCI_H__ */ -- cgit v1.2.3 From 5d249ac37fc2396e8acc1adb0650cdacae5a990d Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 26 Oct 2022 12:42:04 -0700 Subject: mmc: sdhci-of-arasan: Fix SDHCI_RESET_ALL for CQHCI SDHCI_RESET_ALL resets will reset the hardware CQE state, but we aren't tracking that properly in software. When out of sync, we may trigger various timeouts. It's not typical to perform resets while CQE is enabled, but one particular case I hit commonly enough: mmc_suspend() -> mmc_power_off(). Typically we will eventually deactivate CQE (cqhci_suspend() -> cqhci_deactivate()), but that's not guaranteed -- in particular, if we perform a partial (e.g., interrupted) system suspend. The same bug was already found and fixed for two other drivers, in v5.7 and v5.9: 5cf583f1fb9c ("mmc: sdhci-msm: Deactivate CQE during SDHC reset") df57d73276b8 ("mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based controllers") The latter is especially prescient, saying "other drivers using CQHCI might benefit from a similar change, if they also have CQHCI reset by SDHCI_RESET_ALL." So like these other patches, deactivate CQHCI when resetting the controller. Do this via the new sdhci_and_cqhci_reset() helper. This patch depends on (and should not compile without) the patch entitled "mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI". Fixes: 84362d79f436 ("mmc: sdhci-of-arasan: Add CQHCI support for arasan,sdhci-5.1") Cc: Signed-off-by: Brian Norris Reviewed-by: Guenter Roeck Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20221026124150.v4.2.I29f6a2189e84e35ad89c1833793dca9e36c64297@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 3997cad1f793..cfb891430174 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -25,6 +25,7 @@ #include #include "cqhci.h" +#include "sdhci-cqhci.h" #include "sdhci-pltfm.h" #define SDHCI_ARASAN_VENDOR_REGISTER 0x78 @@ -366,7 +367,7 @@ static void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); - sdhci_reset(host, mask); + sdhci_and_cqhci_reset(host, mask); if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_FORCE_CDTEST) { ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); -- cgit v1.2.3 From 56baa208f91061ff27ec2d93fbc483f624d373b4 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 26 Oct 2022 12:42:05 -0700 Subject: mmc: sdhci-brcmstb: Fix SDHCI_RESET_ALL for CQHCI [[ NOTE: this is completely untested by the author, but included solely because, as noted in commit df57d73276b8 ("mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based controllers"), "other drivers using CQHCI might benefit from a similar change, if they also have CQHCI reset by SDHCI_RESET_ALL." We've now seen the same bug on at least MSM, Arasan, and Intel hardware. ]] SDHCI_RESET_ALL resets will reset the hardware CQE state, but we aren't tracking that properly in software. When out of sync, we may trigger various timeouts. It's not typical to perform resets while CQE is enabled, but this may occur in some suspend or error recovery scenarios. Include this fix by way of the new sdhci_and_cqhci_reset() helper. I only patch the bcm7216 variant even though others potentially *could* provide the 'supports-cqe' property (and thus enable CQHCI), because d46ba2d17f90 ("mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)") and some Broadcom folks confirm that only the 7216 variant actually supports it. This patch depends on (and should not compile without) the patch entitled "mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI". Fixes: d46ba2d17f90 ("mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)") Signed-off-by: Brian Norris Reviewed-by: Florian Fainelli Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221026124150.v4.3.I6a715feab6d01f760455865e968ecf0d85036018@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-brcmstb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index aff36a933ebe..55d8bd232695 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -12,6 +12,7 @@ #include #include +#include "sdhci-cqhci.h" #include "sdhci-pltfm.h" #include "cqhci.h" @@ -55,7 +56,7 @@ static void brcmstb_reset(struct sdhci_host *host, u8 mask) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host); - sdhci_reset(host, mask); + sdhci_and_cqhci_reset(host, mask); /* Reset will clear this, so re-enable it */ if (priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK) -- cgit v1.2.3 From fb1dec44c6750bb414f47b929c8c175a1a127c31 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 26 Oct 2022 12:42:06 -0700 Subject: mms: sdhci-esdhc-imx: Fix SDHCI_RESET_ALL for CQHCI [[ NOTE: this is completely untested by the author, but included solely because, as noted in commit df57d73276b8 ("mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based controllers"), "other drivers using CQHCI might benefit from a similar change, if they also have CQHCI reset by SDHCI_RESET_ALL." We've now seen the same bug on at least MSM, Arasan, and Intel hardware. ]] SDHCI_RESET_ALL resets will reset the hardware CQE state, but we aren't tracking that properly in software. When out of sync, we may trigger various timeouts. It's not typical to perform resets while CQE is enabled, but this may occur in some suspend or error recovery scenarios. Include this fix by way of the new sdhci_and_cqhci_reset() helper. This patch depends on (and should not compile without) the patch entitled "mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI". Fixes: bb6e358169bf ("mmc: sdhci-esdhc-imx: add CMDQ support") Signed-off-by: Brian Norris Reviewed-by: Haibo Chen Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221026124150.v4.4.I7d01f9ad11bacdc9213dee61b7918982aea39115@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 747df79d90ee..89225faa242a 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -25,6 +25,7 @@ #include #include #include +#include "sdhci-cqhci.h" #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" #include "cqhci.h" @@ -1288,7 +1289,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) static void esdhc_reset(struct sdhci_host *host, u8 mask) { - sdhci_reset(host, mask); + sdhci_and_cqhci_reset(host, mask); sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -- cgit v1.2.3 From 836078449464e6af3b66ae6652dae79af176f21e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 26 Oct 2022 12:42:07 -0700 Subject: mmc: sdhci-tegra: Fix SDHCI_RESET_ALL for CQHCI [[ NOTE: this is completely untested by the author, but included solely because, as noted in commit df57d73276b8 ("mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based controllers"), "other drivers using CQHCI might benefit from a similar change, if they also have CQHCI reset by SDHCI_RESET_ALL." We've now seen the same bug on at least MSM, Arasan, and Intel hardware. ]] SDHCI_RESET_ALL resets will reset the hardware CQE state, but we aren't tracking that properly in software. When out of sync, we may trigger various timeouts. It's not typical to perform resets while CQE is enabled, but this may occur in some suspend or error recovery scenarios. Include this fix by way of the new sdhci_and_cqhci_reset() helper. This patch depends on (and should not compile without) the patch entitled "mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI". Fixes: 3c4019f97978 ("mmc: tegra: HW Command Queue Support for Tegra SDMMC") Signed-off-by: Brian Norris Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221026124150.v4.5.I418c9eaaf754880fcd2698113e8c3ef821a944d7@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-tegra.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 413925bce0ca..c71000a07656 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -28,6 +28,7 @@ #include +#include "sdhci-cqhci.h" #include "sdhci-pltfm.h" #include "cqhci.h" @@ -367,7 +368,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; u32 misc_ctrl, clk_ctrl, pad_ctrl; - sdhci_reset(host, mask); + sdhci_and_cqhci_reset(host, mask); if (!(mask & SDHCI_RESET_ALL)) return; -- cgit v1.2.3 From 162503fd1c3a1d4e14dbe7f399c1d1bec1c8abbc Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 26 Oct 2022 12:42:08 -0700 Subject: mmc: sdhci_am654: Fix SDHCI_RESET_ALL for CQHCI [[ NOTE: this is completely untested by the author, but included solely because, as noted in commit df57d73276b8 ("mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based controllers"), "other drivers using CQHCI might benefit from a similar change, if they also have CQHCI reset by SDHCI_RESET_ALL." We've now seen the same bug on at least MSM, Arasan, and Intel hardware. ]] SDHCI_RESET_ALL resets will reset the hardware CQE state, but we aren't tracking that properly in software. When out of sync, we may trigger various timeouts. It's not typical to perform resets while CQE is enabled, but this may occur in some suspend or error recovery scenarios. Include this fix by way of the new sdhci_and_cqhci_reset() helper. This patch depends on (and should not compile without) the patch entitled "mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI". Fixes: f545702b74f9 ("mmc: sdhci_am654: Add Support for Command Queuing Engine to J721E") Signed-off-by: Brian Norris Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221026124150.v4.6.I35ca9d6220ba48304438b992a76647ca8e5b126f@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 8f1023480e12..c2333c7acac9 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -15,6 +15,7 @@ #include #include "cqhci.h" +#include "sdhci-cqhci.h" #include "sdhci-pltfm.h" /* CTL_CFG Registers */ @@ -378,7 +379,7 @@ static void sdhci_am654_reset(struct sdhci_host *host, u8 mask) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); - sdhci_reset(host, mask); + sdhci_and_cqhci_reset(host, mask); if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST) { ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); @@ -464,7 +465,7 @@ static struct sdhci_ops sdhci_am654_ops = { .set_clock = sdhci_am654_set_clock, .write_b = sdhci_am654_write_b, .irq = sdhci_am654_cqhci_irq, - .reset = sdhci_reset, + .reset = sdhci_and_cqhci_reset, }; static const struct sdhci_pltfm_data sdhci_am654_pdata = { @@ -494,7 +495,7 @@ static struct sdhci_ops sdhci_j721e_8bit_ops = { .set_clock = sdhci_am654_set_clock, .write_b = sdhci_am654_write_b, .irq = sdhci_am654_cqhci_irq, - .reset = sdhci_reset, + .reset = sdhci_and_cqhci_reset, }; static const struct sdhci_pltfm_data sdhci_j721e_8bit_pdata = { -- cgit v1.2.3 From ae64438be1923e3c1102d90fd41db7afcfaf54cc Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 2 Nov 2022 10:54:31 +0100 Subject: can: dev: fix skb drop check In commit a6d190f8c767 ("can: skb: drop tx skb if in listen only mode") the priv->ctrlmode element is read even on virtual CAN interfaces that do not create the struct can_priv at startup. This out-of-bounds read may lead to CAN frame drops for virtual CAN interfaces like vcan and vxcan. This patch mainly reverts the original commit and adds a new helper for CAN interface drivers that provide the required information in struct can_priv. Fixes: a6d190f8c767 ("can: skb: drop tx skb if in listen only mode") Reported-by: Dariusz Stojaczyk Cc: Vincent Mailhol Cc: Max Staudt Signed-off-by: Oliver Hartkopp Acked-by: Vincent Mailhol Link: https://lore.kernel.org/all/20221102095431.36831-1-socketcan@hartkopp.net Cc: stable@vger.kernel.org # 6.0.x [mkl: patch pch_can, too] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/at91_can.c | 2 +- drivers/net/can/c_can/c_can_main.c | 2 +- drivers/net/can/can327.c | 2 +- drivers/net/can/cc770/cc770.c | 2 +- drivers/net/can/ctucanfd/ctucanfd_base.c | 2 +- drivers/net/can/dev/skb.c | 10 +--------- drivers/net/can/flexcan/flexcan-core.c | 2 +- drivers/net/can/grcan.c | 2 +- drivers/net/can/ifi_canfd/ifi_canfd.c | 2 +- drivers/net/can/janz-ican3.c | 2 +- drivers/net/can/kvaser_pciefd.c | 2 +- drivers/net/can/m_can/m_can.c | 2 +- drivers/net/can/mscan/mscan.c | 2 +- drivers/net/can/pch_can.c | 2 +- drivers/net/can/peak_canfd/peak_canfd.c | 2 +- drivers/net/can/rcar/rcar_can.c | 2 +- drivers/net/can/rcar/rcar_canfd.c | 2 +- drivers/net/can/sja1000/sja1000.c | 2 +- drivers/net/can/slcan/slcan-core.c | 2 +- drivers/net/can/softing/softing_main.c | 2 +- drivers/net/can/spi/hi311x.c | 2 +- drivers/net/can/spi/mcp251x.c | 2 +- drivers/net/can/spi/mcp251xfd/mcp251xfd-tx.c | 2 +- drivers/net/can/sun4i_can.c | 2 +- drivers/net/can/ti_hecc.c | 2 +- drivers/net/can/usb/ems_usb.c | 2 +- drivers/net/can/usb/esd_usb.c | 2 +- drivers/net/can/usb/etas_es58x/es58x_core.c | 2 +- drivers/net/can/usb/gs_usb.c | 2 +- drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 2 +- drivers/net/can/usb/mcba_usb.c | 2 +- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 2 +- drivers/net/can/usb/ucan.c | 2 +- drivers/net/can/usb/usb_8dev.c | 2 +- drivers/net/can/xilinx_can.c | 2 +- 35 files changed, 35 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 3a2d109a3792..199cb200f2bd 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -452,7 +452,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned int mb, prio; u32 reg_mid, reg_mcr; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; mb = get_tx_next_mb(priv); diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c index d6605dbb7737..c63f7fc1e691 100644 --- a/drivers/net/can/c_can/c_can_main.c +++ b/drivers/net/can/c_can/c_can_main.c @@ -457,7 +457,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, struct c_can_tx_ring *tx_ring = &priv->tx; u32 idx, obj, cmd = IF_COMM_TX; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; if (c_can_tx_busy(priv, tx_ring)) diff --git a/drivers/net/can/can327.c b/drivers/net/can/can327.c index 0aa1af31d0fe..094197780776 100644 --- a/drivers/net/can/can327.c +++ b/drivers/net/can/can327.c @@ -813,7 +813,7 @@ static netdev_tx_t can327_netdev_start_xmit(struct sk_buff *skb, struct can327 *elm = netdev_priv(dev); struct can_frame *frame = (struct can_frame *)skb->data; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; /* We shouldn't get here after a hardware fault: diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c index 0b9dfc76e769..30909f3aab57 100644 --- a/drivers/net/can/cc770/cc770.c +++ b/drivers/net/can/cc770/cc770.c @@ -429,7 +429,7 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev) struct cc770_priv *priv = netdev_priv(dev); unsigned int mo = obj2msgobj(CC770_OBJ_TX); - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; netif_stop_queue(dev); diff --git a/drivers/net/can/ctucanfd/ctucanfd_base.c b/drivers/net/can/ctucanfd/ctucanfd_base.c index b8da15ea6ad9..64c349fd4600 100644 --- a/drivers/net/can/ctucanfd/ctucanfd_base.c +++ b/drivers/net/can/ctucanfd/ctucanfd_base.c @@ -600,7 +600,7 @@ static netdev_tx_t ctucan_start_xmit(struct sk_buff *skb, struct net_device *nde bool ok; unsigned long flags; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; if (unlikely(!CTU_CAN_FD_TXTNF(priv))) { diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c index 791a51e2f5d6..241ec636e91f 100644 --- a/drivers/net/can/dev/skb.c +++ b/drivers/net/can/dev/skb.c @@ -5,7 +5,6 @@ */ #include -#include #include #define MOD_DESC "CAN device driver interface" @@ -337,8 +336,6 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb) /* Drop a given socketbuffer if it does not contain a valid CAN frame. */ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb) { - struct can_priv *priv = netdev_priv(dev); - switch (ntohs(skb->protocol)) { case ETH_P_CAN: if (!can_is_can_skb(skb)) @@ -359,13 +356,8 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb) goto inval_skb; } - if (!can_skb_headroom_valid(dev, skb)) { + if (!can_skb_headroom_valid(dev, skb)) goto inval_skb; - } else if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) { - netdev_info_once(dev, - "interface in listen only mode, dropping skb\n"); - goto inval_skb; - } return false; diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c index 5ee38e586fd8..9bdadd716f4e 100644 --- a/drivers/net/can/flexcan/flexcan-core.c +++ b/drivers/net/can/flexcan/flexcan-core.c @@ -742,7 +742,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_fd_len2dlc(cfd->len)) << 16); int i; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; netif_stop_queue(dev); diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 6c37aab93eb3..4bedcc3eea0d 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1345,7 +1345,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb, unsigned long flags; u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; /* Trying to transmit in silent mode will generate error interrupts, but diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index 8d42b7e6661f..07eaf724a572 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -860,7 +860,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb, u32 txst, txid, txdlc; int i; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; /* Check if the TX buffer is full */ diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 71a2caae0757..0732a5092141 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1693,7 +1693,7 @@ static netdev_tx_t ican3_xmit(struct sk_buff *skb, struct net_device *ndev) void __iomem *desc_addr; unsigned long flags; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; spin_lock_irqsave(&mod->lock, flags); diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index 4e9680c8eb34..bcad11709bc9 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -772,7 +772,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, int nwords; u8 count; - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index dcb582563d5e..00d11e95fd98 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1721,7 +1721,7 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, { struct m_can_classdev *cdev = netdev_priv(dev); - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; if (cdev->is_peripheral) { diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 2119fbb287ef..a6829cdc0e81 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -191,7 +191,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) int i, rtr, buf_id; u32 can_id; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; out_8(®s->cantier, 0); diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 0558ff67ec6a..2a44b2803e55 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -882,7 +882,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev) int i; u32 id2; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; tx_obj_no = priv->tx_obj; diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c index f8420cc1d907..31c9c127e24b 100644 --- a/drivers/net/can/peak_canfd/peak_canfd.c +++ b/drivers/net/can/peak_canfd/peak_canfd.c @@ -651,7 +651,7 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb, int room_left; u8 len; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; msg_size = ALIGN(sizeof(*msg) + cf->len, 4); diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index 6ee968c59ac9..cc43c9c5e38c 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -590,7 +590,7 @@ static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb, struct can_frame *cf = (struct can_frame *)skb->data; u32 data, i; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */ diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index 198da643ee6d..d530e986f7fa 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -1481,7 +1481,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, unsigned long flags; u32 ch = priv->channel; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; if (cf->can_id & CAN_EFF_FLAG) { diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 1bb1129b0450..aac5956e4a53 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -291,7 +291,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb, u8 cmd_reg_val = 0x00; int i; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; netif_stop_queue(dev); diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index 8d13fdf8c28a..fbb34139daa1 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -594,7 +594,7 @@ static netdev_tx_t slcan_netdev_xmit(struct sk_buff *skb, { struct slcan *sl = netdev_priv(dev); - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; spin_lock(&sl->lock); diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index a5ef57f415f7..c72f505d29fe 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -60,7 +60,7 @@ static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb, struct can_frame *cf = (struct can_frame *)skb->data; uint8_t buf[DPRAM_TX_SIZE]; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; spin_lock(&card->spin); diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index b87dc420428d..e1b8533a602e 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -373,7 +373,7 @@ static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (can_dropped_invalid_skb(net, skb)) + if (can_dev_dropped_skb(net, skb)) return NETDEV_TX_OK; netif_stop_queue(net); diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 24883a65ca66..79c4bab5f724 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -789,7 +789,7 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (can_dropped_invalid_skb(net, skb)) + if (can_dev_dropped_skb(net, skb)) return NETDEV_TX_OK; netif_stop_queue(net); diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tx.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tx.c index ffb6c36b7d9b..160528d3cc26 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tx.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tx.c @@ -172,7 +172,7 @@ netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb, u8 tx_head; int err; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; if (mcp251xfd_tx_busy(priv, tx_ring)) diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 525309da1320..2b78f9197681 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -429,7 +429,7 @@ static netdev_tx_t sun4ican_start_xmit(struct sk_buff *skb, struct net_device *d canid_t id; int i; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; netif_stop_queue(dev); diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index b218fb3c6b76..27700f72eac2 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -470,7 +470,7 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) u32 mbxno, mbx_mask, data; unsigned long flags; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; mbxno = get_tx_head_mb(priv); diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index d31191686a54..050c0b49938a 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -747,7 +747,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN + sizeof(struct cpc_can_msg); - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; /* create a URB, and a buffer for it, and copy the data to the URB */ diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c index 1bcfad11b1e4..81b88e9e5bdc 100644 --- a/drivers/net/can/usb/esd_usb.c +++ b/drivers/net/can/usb/esd_usb.c @@ -725,7 +725,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, int ret = NETDEV_TX_OK; size_t size = sizeof(struct esd_usb_msg); - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; /* create a URB, and a buffer for it, and copy the data to the URB */ diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c index 51294b717040..25f863b4f5f0 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_core.c +++ b/drivers/net/can/usb/etas_es58x/es58x_core.c @@ -1913,7 +1913,7 @@ static netdev_tx_t es58x_start_xmit(struct sk_buff *skb, unsigned int frame_len; int ret; - if (can_dropped_invalid_skb(netdev, skb)) { + if (can_dev_dropped_skb(netdev, skb)) { if (priv->tx_urb) goto xmit_commit; return NETDEV_TX_OK; diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index f0065d40eb24..9c2c25fde3d1 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -723,7 +723,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, unsigned int idx; struct gs_tx_context *txc; - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; /* find an empty context to keep track of transmission */ diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c index e91648ed7386..802e27c0eced 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c @@ -570,7 +570,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, unsigned int i; unsigned long flags; - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; urb = usb_alloc_urb(0, GFP_ATOMIC); diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c index 69346c63021f..218b098b261d 100644 --- a/drivers/net/can/usb/mcba_usb.c +++ b/drivers/net/can/usb/mcba_usb.c @@ -311,7 +311,7 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb, .cmd_id = MBCA_CMD_TRANSMIT_MESSAGE_EV }; - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; ctx = mcba_usb_get_free_ctx(priv, cf); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 225697d70a9a..1d996d3320fe 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -351,7 +351,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb, int i, err; size_t size = dev->adapter->tx_buffer_size; - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++) diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c index 7c35f50fda4e..67c2ff407d06 100644 --- a/drivers/net/can/usb/ucan.c +++ b/drivers/net/can/usb/ucan.c @@ -1120,7 +1120,7 @@ static netdev_tx_t ucan_start_xmit(struct sk_buff *skb, struct can_frame *cf = (struct can_frame *)skb->data; /* check skb */ - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; /* allocate a context and slow down tx path, if fifo state is low */ diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index 64c00abe91cf..8a5596ce4e46 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -602,7 +602,7 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb, int i, err; size_t size = sizeof(struct usb_8dev_tx_msg); - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; /* create a URB, and a buffer for it, and copy the data to the URB */ diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 5d3172795ad0..43c812ea1de0 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -743,7 +743,7 @@ static netdev_tx_t xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct xcan_priv *priv = netdev_priv(ndev); int ret; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; if (priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) -- cgit v1.2.3 From 8b043dfb3dc7c32f9c2c0c93e3c2de346ee5e358 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 28 Oct 2022 12:06:45 +0200 Subject: can: rcar_canfd: Add missing ECC error checks for channels 2-7 When introducing support for R-Car V3U, which has 8 instead of 2 channels, the ECC error bitmask was extended to take into account the extra channels, but rcar_canfd_global_error() was not updated to act upon the extra bits. Replace the RCANFD_GERFL_EEF[01] macros by a new macro that takes the channel number, fixing R-Car V3U while simplifying the code. Fixes: 45721c406dcf50d4 ("can: rcar_canfd: Add support for r8a779a0 SoC") Signed-off-by: Geert Uytterhoeven Reviewed-by: Biju Das Link: https://lore.kernel.org/all/4edb2ea46cc64d0532a08a924179827481e14b4f.1666951503.git.geert+renesas@glider.be Cc: stable@vger.kernel.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/rcar/rcar_canfd.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index d530e986f7fa..b306cf554634 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -81,8 +81,7 @@ enum rcanfd_chip_id { /* RSCFDnCFDGERFL / RSCFDnGERFL */ #define RCANFD_GERFL_EEF0_7 GENMASK(23, 16) -#define RCANFD_GERFL_EEF1 BIT(17) -#define RCANFD_GERFL_EEF0 BIT(16) +#define RCANFD_GERFL_EEF(ch) BIT(16 + (ch)) #define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */ #define RCANFD_GERFL_THLES BIT(2) #define RCANFD_GERFL_MES BIT(1) @@ -90,7 +89,7 @@ enum rcanfd_chip_id { #define RCANFD_GERFL_ERR(gpriv, x) \ ((x) & (reg_v3u(gpriv, RCANFD_GERFL_EEF0_7, \ - RCANFD_GERFL_EEF0 | RCANFD_GERFL_EEF1) | \ + RCANFD_GERFL_EEF(0) | RCANFD_GERFL_EEF(1)) | \ RCANFD_GERFL_MES | \ ((gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0))) @@ -936,12 +935,8 @@ static void rcar_canfd_global_error(struct net_device *ndev) u32 ridx = ch + RCANFD_RFFIFO_IDX; gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL); - if ((gerfl & RCANFD_GERFL_EEF0) && (ch == 0)) { - netdev_dbg(ndev, "Ch0: ECC Error flag\n"); - stats->tx_dropped++; - } - if ((gerfl & RCANFD_GERFL_EEF1) && (ch == 1)) { - netdev_dbg(ndev, "Ch1: ECC Error flag\n"); + if (gerfl & RCANFD_GERFL_EEF(ch)) { + netdev_dbg(ndev, "Ch%u: ECC Error flag\n", ch); stats->tx_dropped++; } if (gerfl & RCANFD_GERFL_MES) { -- cgit v1.2.3 From f90daa975911961b65070ec72bd7dd8d448f9ef7 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 28 Oct 2022 16:50:26 +0100 Subject: drm/i915/dmabuf: fix sg_table handling in map_dma_buf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to iterate over the original entries here for the sg_table, pulling out the struct page for each one, to be remapped. However currently this incorrectly iterates over the final dma mapped entries, which is likely just one gigantic sg entry if the iommu is enabled, leading to us only mapping the first struct page (and any physically contiguous pages following it), even if there is potentially lots more data to follow. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/7306 Fixes: 1286ff739773 ("i915: add dmabuf/prime buffer sharing support.") Signed-off-by: Matthew Auld Cc: Lionel Landwerlin Cc: Tvrtko Ursulin Cc: Ville Syrjälä Cc: Michael J. Ruhl Cc: # v3.5+ Reviewed-by: Michael J. Ruhl Link: https://patchwork.freedesktop.org/patch/msgid/20221028155029.494736-1-matthew.auld@intel.com (cherry picked from commit 28d52f99bbca7227008cf580c9194c9b3516968e) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index f5062d0c6333..824971a1ceec 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -40,13 +40,13 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme goto err; } - ret = sg_alloc_table(st, obj->mm.pages->nents, GFP_KERNEL); + ret = sg_alloc_table(st, obj->mm.pages->orig_nents, GFP_KERNEL); if (ret) goto err_free; src = obj->mm.pages->sgl; dst = st->sgl; - for (i = 0; i < obj->mm.pages->nents; i++) { + for (i = 0; i < obj->mm.pages->orig_nents; i++) { sg_set_page(dst, sg_page(src), src->length, 0); dst = sg_next(dst); src = sg_next(src); -- cgit v1.2.3 From 4ff4ebac3f1378f4ba6e11fe5ad4a4ac590bb8a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 24 Oct 2022 08:46:49 +0300 Subject: drm/i915/psr: Send update also on invalidate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are observing mouse cursor stuttering when using xrandr --scaling=1.2x1.2. X scaling/transformation seems to be doing fronbuffer rendering. When moving mouse cursor X seems to perform several invalidates and only one DirtyFB. I.e. it seems to be assuming updates are sent to panel while drawing is done. Earlier we were disabling PSR in frontbuffer invalidate call back (when drawing in X started). PSR was re-enabled in frontbuffer flush callback (dirtyfb ioctl). This was working fine with X scaling/transformation. Now we are just enabling continuous full frame (cff) in PSR invalidate callback. Enabling cff doesn't trigger any updates. It just configures PSR to send full frame when updates are sent. I.e. there are no updates on screen before PSR flush callback is made. X seems to be doing several updates in frontbuffer before doing dirtyfb ioctl. Fix this by sending single update on every invalidate callback. Cc: José Roberto de Souza Cc: Ville Syrjälä Cc: Mika Kahola Fixes: 805f04d42a6b ("drm/i915/display/psr: Use continuos full frame to handle frontbuffer invalidations") Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6679 Signed-off-by: Jouni Högander Reported-by: Brian J. Tarricone Tested-by: Brian J. Tarricone Reviewed-by: Mika Kahola Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20221024054649.31299-1-jouni.hogander@intel.com (cherry picked from commit d755f89220a2b49bc90b7b520bb6edeb4adb5f01) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/display/intel_psr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d4cce627d7a8..15c3e448aa0e 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -2201,8 +2201,11 @@ static void _psr_invalidate_handle(struct intel_dp *intel_dp) if (intel_dp->psr.psr2_sel_fetch_enabled) { u32 val; - if (intel_dp->psr.psr2_sel_fetch_cff_enabled) + if (intel_dp->psr.psr2_sel_fetch_cff_enabled) { + /* Send one update otherwise lag is observed in screen */ + intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0); return; + } val = man_trk_ctl_enable_bit_get(dev_priv) | man_trk_ctl_partial_frame_bit_get(dev_priv) | -- cgit v1.2.3 From 19b168136395150a4a6e011f944eb30d3d85094b Mon Sep 17 00:00:00 2001 From: Niranjana Vishwanathapura Date: Tue, 1 Nov 2022 22:14:16 -0700 Subject: drm/i915: Do not set cache_dirty for DGFX Currently on DG1, which does not have LLC, we hit the below warning while rebinding an userptr invalidated object. WARNING: CPU: 4 PID: 13008 at drivers/gpu/drm/i915/gem/i915_gem_pages.c:34 __i915_gem_object_set_pages+0x296/0x2d0 [i915] ... RIP: 0010:__i915_gem_object_set_pages+0x296/0x2d0 [i915] ... Call Trace: i915_gem_userptr_get_pages+0x175/0x1a0 [i915] ____i915_gem_object_get_pages+0x32/0xb0 [i915] i915_gem_object_userptr_submit_init+0x286/0x470 [i915] eb_lookup_vmas+0x2ff/0xcf0 [i915] ? __intel_wakeref_get_first+0x55/0xb0 [i915] i915_gem_do_execbuffer+0x785/0x21d0 [i915] i915_gem_execbuffer2_ioctl+0xe7/0x3d0 [i915] We shouldn't be setting the obj->cache_dirty for DGFX, fix it. Fixes: d70af57944a1 ("drm/i915/shmem: ensure flush during swap-in on non-LLC") Suggested-by: Matthew Auld Reported-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Acked-by: Nirmoy Das Reviewed-by: Matthew Auld Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20221102051416.27327-1-niranjana.vishwanathapura@intel.com (cherry picked from commit 0aeec60c76ca2631696b4228f3fc99fe3a80013d) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 11125c32dd35..2f7804492cd5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -369,14 +369,14 @@ __i915_gem_object_release_shmem(struct drm_i915_gem_object *obj, __start_cpu_write(obj); /* - * On non-LLC platforms, force the flush-on-acquire if this is ever + * On non-LLC igfx platforms, force the flush-on-acquire if this is ever * swapped-in. Our async flush path is not trust worthy enough yet(and * happens in the wrong order), and with some tricks it's conceivable * for userspace to change the cache-level to I915_CACHE_NONE after the * pages are swapped-in, and since execbuf binds the object before doing * the async flush, we have a race window. */ - if (!HAS_LLC(i915)) + if (!HAS_LLC(i915) && !IS_DGFX(i915)) obj->cache_dirty = true; } -- cgit v1.2.3 From 178e31ce82d0308a9e5f2f15bfb4493160136729 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 28 Oct 2022 14:06:35 +0100 Subject: drm/i915/userptr: restore probe_range behaviour The conversion looks harmless, however the addr value is updated inside the loop with the previous vm_end, which then incorrectly leads to for_each_vma_range() iterating over stuff outside the range we care about. Fix this by storing the end value separately. Also fix the case where the range doesn't intersect with any vma, or if the vma itself doesn't extend the entire range, which must mean we have hole at the end. Both should result in an error, as per the previous behaviour. v2: Fix the cases where the range is empty, or if there's a hole at the end of the range Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/7247 Testcase: igt@gem_userptr_blits@probe Fixes: f683b9d61319 ("i915: use the VMA iterator") Reported-by: kernel test robot Signed-off-by: Matthew Auld Cc: Tvrtko Ursulin Cc: Matthew Wilcox (Oracle) Cc: Liam R. Howlett Cc: Vlastimil Babka Cc: Yu Zhao Reviewed-by: Liam R. Howlett Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/20221028130635.465839-1-matthew.auld@intel.com (cherry picked from commit 6f7de35b50860c345babf8ed0aa0d75f9315eee4) Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index f34e01a7fefb..ba14b18d65f3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -428,9 +428,10 @@ probe_range(struct mm_struct *mm, unsigned long addr, unsigned long len) { VMA_ITERATOR(vmi, mm, addr); struct vm_area_struct *vma; + unsigned long end = addr + len; mmap_read_lock(mm); - for_each_vma_range(vmi, vma, addr + len) { + for_each_vma_range(vmi, vma, end) { /* Check for holes, note that we also update the addr below */ if (vma->vm_start > addr) break; @@ -442,7 +443,7 @@ probe_range(struct mm_struct *mm, unsigned long addr, unsigned long len) } mmap_read_unlock(mm); - if (vma) + if (vma || addr < end) return -EFAULT; return 0; } -- cgit v1.2.3 From bee55f2e7a44e7a7676e264b42f026e34bd244d9 Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Tue, 18 Oct 2022 14:17:23 +0200 Subject: pinctrl: rockchip: list all pins in a possible mux route for PX30 The mux routes are incomplete for the PX30. This was discovered because we had a HW design using cif-clkoutm1 with the correct pinmux in the Device Tree but the clock would still not work. There are actually two muxing required: the pin muxing (performed by the usual Device Tree pinctrl nodes) and the "function" muxing (m0 vs m1; performed by the mux routing inside the driver). The pin muxing was correct but the function muxing was not. This adds the missing pins and their configuration for the mux routes that are already specified in the driver. Note that there are some "conflicts": it is possible *in Device Tree* to (attempt to) mux the pins for e.g. clkoutm1 and clkinm0 at the same time but this is actually not possible in hardware (because both share the same bit for the function muxing). Since it is an impossible hardware design, it is not deemed necessary to prevent the user from attempting to "misconfigure" the pins/functions. Fixes: 87065ca9b8e5 ("pinctrl: rockchip: Add pinctrl support for PX30") Signed-off-by: Quentin Schulz Link: https://lore.kernel.org/r/20221017-upstream-px30-cif-clkoutm1-v1-0-4ea1389237f7@theobroma-systems.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-rockchip.c | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 53bdfc40f055..da974ff2d75d 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -679,14 +679,54 @@ static void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin, } static struct rockchip_mux_route_data px30_mux_route_data[] = { + RK_MUXROUTE_SAME(2, RK_PB4, 1, 0x184, BIT(16 + 7)), /* cif-d0m0 */ + RK_MUXROUTE_SAME(3, RK_PA1, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d0m1 */ + RK_MUXROUTE_SAME(2, RK_PB6, 1, 0x184, BIT(16 + 7)), /* cif-d1m0 */ + RK_MUXROUTE_SAME(3, RK_PA2, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d1m1 */ RK_MUXROUTE_SAME(2, RK_PA0, 1, 0x184, BIT(16 + 7)), /* cif-d2m0 */ RK_MUXROUTE_SAME(3, RK_PA3, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d2m1 */ + RK_MUXROUTE_SAME(2, RK_PA1, 1, 0x184, BIT(16 + 7)), /* cif-d3m0 */ + RK_MUXROUTE_SAME(3, RK_PA5, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d3m1 */ + RK_MUXROUTE_SAME(2, RK_PA2, 1, 0x184, BIT(16 + 7)), /* cif-d4m0 */ + RK_MUXROUTE_SAME(3, RK_PA7, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d4m1 */ + RK_MUXROUTE_SAME(2, RK_PA3, 1, 0x184, BIT(16 + 7)), /* cif-d5m0 */ + RK_MUXROUTE_SAME(3, RK_PB0, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d5m1 */ + RK_MUXROUTE_SAME(2, RK_PA4, 1, 0x184, BIT(16 + 7)), /* cif-d6m0 */ + RK_MUXROUTE_SAME(3, RK_PB1, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d6m1 */ + RK_MUXROUTE_SAME(2, RK_PA5, 1, 0x184, BIT(16 + 7)), /* cif-d7m0 */ + RK_MUXROUTE_SAME(3, RK_PB4, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d7m1 */ + RK_MUXROUTE_SAME(2, RK_PA6, 1, 0x184, BIT(16 + 7)), /* cif-d8m0 */ + RK_MUXROUTE_SAME(3, RK_PB6, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d8m1 */ + RK_MUXROUTE_SAME(2, RK_PA7, 1, 0x184, BIT(16 + 7)), /* cif-d9m0 */ + RK_MUXROUTE_SAME(3, RK_PB7, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d9m1 */ + RK_MUXROUTE_SAME(2, RK_PB7, 1, 0x184, BIT(16 + 7)), /* cif-d10m0 */ + RK_MUXROUTE_SAME(3, RK_PC6, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d10m1 */ + RK_MUXROUTE_SAME(2, RK_PC0, 1, 0x184, BIT(16 + 7)), /* cif-d11m0 */ + RK_MUXROUTE_SAME(3, RK_PC7, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-d11m1 */ + RK_MUXROUTE_SAME(2, RK_PB0, 1, 0x184, BIT(16 + 7)), /* cif-vsyncm0 */ + RK_MUXROUTE_SAME(3, RK_PD1, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-vsyncm1 */ + RK_MUXROUTE_SAME(2, RK_PB1, 1, 0x184, BIT(16 + 7)), /* cif-hrefm0 */ + RK_MUXROUTE_SAME(3, RK_PD2, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-hrefm1 */ + RK_MUXROUTE_SAME(2, RK_PB2, 1, 0x184, BIT(16 + 7)), /* cif-clkinm0 */ + RK_MUXROUTE_SAME(3, RK_PD3, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-clkinm1 */ + RK_MUXROUTE_SAME(2, RK_PB3, 1, 0x184, BIT(16 + 7)), /* cif-clkoutm0 */ + RK_MUXROUTE_SAME(3, RK_PD0, 3, 0x184, BIT(16 + 7) | BIT(7)), /* cif-clkoutm1 */ RK_MUXROUTE_SAME(3, RK_PC6, 2, 0x184, BIT(16 + 8)), /* pdm-m0 */ RK_MUXROUTE_SAME(2, RK_PC6, 1, 0x184, BIT(16 + 8) | BIT(8)), /* pdm-m1 */ + RK_MUXROUTE_SAME(3, RK_PD3, 2, 0x184, BIT(16 + 8)), /* pdm-sdi0m0 */ + RK_MUXROUTE_SAME(2, RK_PC5, 2, 0x184, BIT(16 + 8) | BIT(8)), /* pdm-sdi0m1 */ RK_MUXROUTE_SAME(1, RK_PD3, 2, 0x184, BIT(16 + 10)), /* uart2-rxm0 */ RK_MUXROUTE_SAME(2, RK_PB6, 2, 0x184, BIT(16 + 10) | BIT(10)), /* uart2-rxm1 */ + RK_MUXROUTE_SAME(1, RK_PD2, 2, 0x184, BIT(16 + 10)), /* uart2-txm0 */ + RK_MUXROUTE_SAME(2, RK_PB4, 2, 0x184, BIT(16 + 10) | BIT(10)), /* uart2-txm1 */ RK_MUXROUTE_SAME(0, RK_PC1, 2, 0x184, BIT(16 + 9)), /* uart3-rxm0 */ RK_MUXROUTE_SAME(1, RK_PB7, 2, 0x184, BIT(16 + 9) | BIT(9)), /* uart3-rxm1 */ + RK_MUXROUTE_SAME(0, RK_PC0, 2, 0x184, BIT(16 + 9)), /* uart3-txm0 */ + RK_MUXROUTE_SAME(1, RK_PB6, 2, 0x184, BIT(16 + 9) | BIT(9)), /* uart3-txm1 */ + RK_MUXROUTE_SAME(0, RK_PC2, 2, 0x184, BIT(16 + 9)), /* uart3-ctsm0 */ + RK_MUXROUTE_SAME(1, RK_PB4, 2, 0x184, BIT(16 + 9) | BIT(9)), /* uart3-ctsm1 */ + RK_MUXROUTE_SAME(0, RK_PC3, 2, 0x184, BIT(16 + 9)), /* uart3-rtsm0 */ + RK_MUXROUTE_SAME(1, RK_PB5, 2, 0x184, BIT(16 + 9) | BIT(9)), /* uart3-rtsm1 */ }; static struct rockchip_mux_route_data rv1126_mux_route_data[] = { -- cgit v1.2.3 From 7df140e84a75c89962feef659d686303d3ce75e5 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 21 Oct 2022 18:53:04 +0200 Subject: mtd: rawnand: qcom: handle ret from parse with codeword_fixup With use_codeword_fixup enabled, any return from mtd_device_parse_register gets overwritten. Aside from the clear bug, this is also problematic as a parser can EPROBE_DEFER and because this is not correctly handled, the nand is never rescanned later in the bootup process. An example of this problem is when smem requires additional time to be probed and nandc use qcomsmempart as parser. Parser will return EPROBE_DEFER but in the current code this ret gets overwritten by qcom_nand_host_parse_boot_partitions and qcom_nand_host_init_and_register return 0. Correctly handle the return code from mtd_device_parse_register so that any error from this function is not ignored. Fixes: 862bdedd7f4b ("mtd: nand: raw: qcom_nandc: add support for unprotected spare data pages") Cc: stable@vger.kernel.org # v6.0+ Signed-off-by: Christian Marangi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20221021165304.19991-1-ansuelsmth@gmail.com --- drivers/mtd/nand/raw/qcom_nandc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 8f80019a9f01..198a44794d2d 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -3167,16 +3167,18 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, ret = mtd_device_parse_register(mtd, probes, NULL, NULL, 0); if (ret) - nand_cleanup(chip); + goto err; if (nandc->props->use_codeword_fixup) { ret = qcom_nand_host_parse_boot_partitions(nandc, host, dn); - if (ret) { - nand_cleanup(chip); - return ret; - } + if (ret) + goto err; } + return 0; + +err: + nand_cleanup(chip); return ret; } -- cgit v1.2.3 From 83f0869e9bf3333d778d62f055b0f8e1de1cc812 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Mon, 24 Oct 2022 11:20:26 +0200 Subject: mtd: rawnand: placate "$VARIABLE is used uninitialized" warnings The compiler is not smart enough to notice that it's impossible for them to be actually used uninitialized. Which exact variables trip here varies depending on random surrounding code; none triggered in 6.1-rc1 but 6.1-rc2 fails on three of these five, despite variables declared in the very same line having identical flow. Signed-off-by: Adam Borowski Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20221024092026.42123-1-kilobyte@angband.pl --- drivers/mtd/nand/raw/nand_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 33f2c98a030e..c3cc66039925 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5834,7 +5834,7 @@ nand_match_ecc_req(struct nand_chip *chip, int req_step = requirements->step_size; int req_strength = requirements->strength; int req_corr, step_size, strength, nsteps, ecc_bytes, ecc_bytes_total; - int best_step, best_strength, best_ecc_bytes; + int best_step = 0, best_strength = 0, best_ecc_bytes = 0; int best_ecc_bytes_total = INT_MAX; int i, j; @@ -5915,7 +5915,7 @@ nand_maximize_ecc(struct nand_chip *chip, int step_size, strength, nsteps, ecc_bytes, corr; int best_corr = 0; int best_step = 0; - int best_strength, best_ecc_bytes; + int best_strength = 0, best_ecc_bytes = 0; int i, j; for (i = 0; i < caps->nstepinfos; i++) { -- cgit v1.2.3 From c717b9b7d6de9e024e47f7cd5bbff49f581d3db9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 7 Nov 2022 10:15:20 +0100 Subject: mtd: onenand: omap2: add dependency on GPMC OMAP2 OneNAND driver uses gpmc_omap_onenand_set_timings() provided by OMAP_GPMC driver, so the latter cannot be module if OneNAND driver is built-in: /usr/bin/arm-linux-gnueabi-ld: drivers/mtd/nand/onenand/onenand_omap2.o: in function `omap2_onenand_probe': onenand_omap2.c:(.text+0x520): undefined reference to `gpmc_omap_onenand_set_timings' The OMAP_GPMC is also a runtime dependency. Reported-by: kernel test robot Fixes: 854fd9209b20 ("memory: omap-gpmc: Allow building as a module") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Roger Quadros Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20221107091520.127053-1-krzysztof.kozlowski@linaro.org --- drivers/mtd/nand/onenand/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/onenand/Kconfig b/drivers/mtd/nand/onenand/Kconfig index 34d9a7a82ad4..c94bf483541e 100644 --- a/drivers/mtd/nand/onenand/Kconfig +++ b/drivers/mtd/nand/onenand/Kconfig @@ -26,6 +26,7 @@ config MTD_ONENAND_OMAP2 tristate "OneNAND on OMAP2/OMAP3 support" depends on ARCH_OMAP2 || ARCH_OMAP3 || (COMPILE_TEST && ARM) depends on OF || COMPILE_TEST + depends on OMAP_GPMC help Support for a OneNAND flash device connected to an OMAP2/OMAP3 SoC via the GPMC memory controller. -- cgit v1.2.3 From b8ebf250997c5fb253582f42bfe98673801ebebd Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 7 Nov 2022 10:21:40 -0800 Subject: Input: iforce - invert valid length check when fetching device IDs syzbot is reporting uninitialized value at iforce_init_device() [1], for commit 6ac0aec6b0a6 ("Input: iforce - allow callers supply data buffer when fetching device IDs") is checking that valid length is shorter than bytes to read. Since iforce_get_id_packet() stores valid length when returning 0, the caller needs to check that valid length is longer than or equals to bytes to read. Reported-by: syzbot Signed-off-by: Tetsuo Handa Fixes: 6ac0aec6b0a6 ("Input: iforce - allow callers supply data buffer when fetching device IDs") Link: https://lore.kernel.org/r/531fb432-7396-ad37-ecba-3e42e7f56d5c@I-love.SAKURA.ne.jp Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b86de1312512..84b87526b7ba 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -273,22 +273,22 @@ int iforce_init_device(struct device *parent, u16 bustype, * Get device info. */ - if (!iforce_get_id_packet(iforce, 'M', buf, &len) || len < 3) + if (!iforce_get_id_packet(iforce, 'M', buf, &len) && len >= 3) input_dev->id.vendor = get_unaligned_le16(buf + 1); else dev_warn(&iforce->dev->dev, "Device does not respond to id packet M\n"); - if (!iforce_get_id_packet(iforce, 'P', buf, &len) || len < 3) + if (!iforce_get_id_packet(iforce, 'P', buf, &len) && len >= 3) input_dev->id.product = get_unaligned_le16(buf + 1); else dev_warn(&iforce->dev->dev, "Device does not respond to id packet P\n"); - if (!iforce_get_id_packet(iforce, 'B', buf, &len) || len < 3) + if (!iforce_get_id_packet(iforce, 'B', buf, &len) && len >= 3) iforce->device_memory.end = get_unaligned_le16(buf + 1); else dev_warn(&iforce->dev->dev, "Device does not respond to id packet B\n"); - if (!iforce_get_id_packet(iforce, 'N', buf, &len) || len < 2) + if (!iforce_get_id_packet(iforce, 'N', buf, &len) && len >= 2) ff_effects = buf[1]; else dev_warn(&iforce->dev->dev, "Device does not respond to id packet N\n"); -- cgit v1.2.3 From 8e9ada1d0e72b4737df400fe1bba48dc42a68df7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 7 Nov 2022 10:30:25 -0800 Subject: Input: soc_button_array - add use_low_level_irq module parameter It seems that the Windows drivers for the ACPI0011 soc_button_array device use low level triggered IRQs rather then using edge triggering. Some ACPI tables depend on this, directly poking the GPIO controller's registers to clear the trigger type when closing a laptop's/2-in-1's lid and re-instating the trigger when opening the lid again. Linux sets the edge/level on which to trigger to both low+high since it is using edge type IRQs, the ACPI tables then ends up also setting the bit for level IRQs and since both low and high level have been selected by Linux we get an IRQ storm leading to soft lockups. As a workaround for this the soc_button_array already contains a DMI quirk table with device models known to have this issue. Add a module parameter for this so that users can easily test if their device is affected too and so that they can use the module parameter as a workaround. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20221106215320.67109-1-hdegoede@redhat.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/soc_button_array.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index 480476121c01..50497dd05027 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -18,6 +18,10 @@ #include #include +static bool use_low_level_irq; +module_param(use_low_level_irq, bool, 0444); +MODULE_PARM_DESC(use_low_level_irq, "Use low-level triggered IRQ instead of edge triggered"); + struct soc_button_info { const char *name; int acpi_index; @@ -164,7 +168,8 @@ soc_button_device_create(struct platform_device *pdev, } /* See dmi_use_low_level_irq[] comment */ - if (!autorepeat && dmi_check_system(dmi_use_low_level_irq)) { + if (!autorepeat && (use_low_level_irq || + dmi_check_system(dmi_use_low_level_irq))) { irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW); gpio_keys[n_buttons].irq = irq; gpio_keys[n_buttons].gpio = -ENOENT; -- cgit v1.2.3 From e13757f52496444b994a7ac67b6e517a15d89bbc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 7 Nov 2022 10:30:41 -0800 Subject: Input: soc_button_array - add Acer Switch V 10 to dmi_use_low_level_irq[] Like on the Acer Switch 10 SW5-012, the Acer Switch V 10 SW5-017's _LID method messes with home- and power-button GPIO IRQ settings, causing an IRQ storm. Add a quirk entry for the Acer Switch V 10 to the dmi_use_low_level_irq[] DMI quirk list, to use low-level IRQs on this model, fixing the IRQ storm. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20221106215320.67109-2-hdegoede@redhat.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/soc_button_array.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index 50497dd05027..09489380afda 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -77,6 +77,13 @@ static const struct dmi_system_id dmi_use_low_level_irq[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"), }, }, + { + /* Acer Switch V 10 SW5-017, same issue as Acer Switch 10 SW5-012. */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "SW5-017"), + }, + }, { /* * Acer One S1003. _LID method messes with power-button GPIO -- cgit v1.2.3 From 62fa3ce05d5d73c5eccc40b2db493f55fecfc446 Mon Sep 17 00:00:00 2001 From: Brian King Date: Wed, 26 Oct 2022 13:13:56 -0500 Subject: scsi: ibmvfc: Avoid path failures during live migration Fix an issue reported when performing a live migration when multipath is configured with a short fast fail timeout of 5 seconds and also to have no_path_retry set to fail. In this scenario, all paths would go into the devloss state while the ibmvfc driver went through discovery to log back in. On a loaded system, the discovery might take longer than 5 seconds, which was resulting in all paths being marked failed, which then resulted in a read only filesystem. This patch changes the migration code in ibmvfc to avoid deleting rports at all in this scenario, so we avoid losing all paths. Signed-off-by: Brian King Link: https://lore.kernel.org/r/20221026181356.148517-1-brking@linux.vnet.ibm.com Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 00684e11976b..1a0c0b7289d2 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -708,8 +708,13 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost) memset(vhost->async_crq.msgs.async, 0, PAGE_SIZE); vhost->async_crq.cur = 0; - list_for_each_entry(tgt, &vhost->targets, queue) - ibmvfc_del_tgt(tgt); + list_for_each_entry(tgt, &vhost->targets, queue) { + if (vhost->client_migrated) + tgt->need_login = 1; + else + ibmvfc_del_tgt(tgt); + } + scsi_block_requests(vhost->host); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); vhost->job_step = ibmvfc_npiv_login; @@ -3235,9 +3240,12 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost, /* We need to re-setup the interpartition connection */ dev_info(vhost->dev, "Partition migrated, Re-enabling adapter\n"); vhost->client_migrated = 1; + + scsi_block_requests(vhost->host); ibmvfc_purge_requests(vhost, DID_REQUEUE); - ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_set_host_state(vhost, IBMVFC_LINK_DOWN); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_REENABLE); + wake_up(&vhost->work_wait_q); } else if (crq->format == IBMVFC_PARTNER_FAILED || crq->format == IBMVFC_PARTNER_DEREGISTER) { dev_err(vhost->dev, "Host partner adapter deregistered or failed (rc=%d)\n", crq->format); ibmvfc_purge_requests(vhost, DID_ERROR); -- cgit v1.2.3 From 5fd974d164b4240652259e7058e2c72a68662cb0 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 2 Nov 2022 10:10:43 -0700 Subject: drm/i915/mtl: add initial definitions for GSC CS Starting on MTL, the GSC is no longer managed with direct MMIO access, but we instead have a dedicated command streamer for it. As a first step for adding support for this CS, add the required definitions. Note that, although it is now a CS, the GSC retains its old class:instance value (OTHER_CLASS instance 6) Bspec: 65308, 45605 Signed-off-by: Daniele Ceraolo Spurio Cc: Matt Roper Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20221102171047.2787951-2-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 8 ++++++++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 1 + drivers/gpu/drm/i915/gt/intel_engine_user.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 1 + 4 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 3b7d750ad054..e0fbfac03979 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -244,6 +244,13 @@ static const struct engine_info intel_engines[] = { { .graphics_ver = 12, .base = GEN12_COMPUTE3_RING_BASE } } }, + [GSC0] = { + .class = OTHER_CLASS, + .instance = OTHER_GSC_INSTANCE, + .mmio_bases = { + { .graphics_ver = 12, .base = MTL_GSC_RING_BASE } + } + }, }; /** @@ -324,6 +331,7 @@ u32 intel_engine_context_size(struct intel_gt *gt, u8 class) case VIDEO_DECODE_CLASS: case VIDEO_ENHANCEMENT_CLASS: case COPY_ENGINE_CLASS: + case OTHER_CLASS: if (GRAPHICS_VER(gt->i915) < 8) return 0; return GEN8_LR_CONTEXT_OTHER_SIZE; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 6b5d4ea22b67..4fd54fb8810f 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -136,6 +136,7 @@ enum intel_engine_id { CCS2, CCS3, #define _CCS(n) (CCS0 + (n)) + GSC0, I915_NUM_ENGINES #define INVALID_ENGINE ((enum intel_engine_id)-1) }; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c index 46a174f8aa00..79312b734690 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_user.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c @@ -140,6 +140,7 @@ const char *intel_engine_class_repr(u8 class) [COPY_ENGINE_CLASS] = "bcs", [VIDEO_DECODE_CLASS] = "vcs", [VIDEO_ENHANCEMENT_CLASS] = "vecs", + [OTHER_CLASS] = "other", [COMPUTE_CLASS] = "ccs", }; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1c0da50c0dc7..d056c3117ef2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -970,6 +970,7 @@ #define GEN11_VEBOX2_RING_BASE 0x1d8000 #define XEHP_VEBOX3_RING_BASE 0x1e8000 #define XEHP_VEBOX4_RING_BASE 0x1f8000 +#define MTL_GSC_RING_BASE 0x11a000 #define GEN12_COMPUTE0_RING_BASE 0x1a000 #define GEN12_COMPUTE1_RING_BASE 0x1c000 #define GEN12_COMPUTE2_RING_BASE 0x1e000 -- cgit v1.2.3 From c9c12ba72e740e3adb5a2287f6d0372fa45721c3 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 2 Nov 2022 10:10:44 -0700 Subject: drm/i915/mtl: pass the GSC CS info to the GuC We need to tell the GuC that the GSC CS is there. Signed-off-by: Daniele Ceraolo Spurio Cc: Matt Roper Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20221102171047.2787951-3-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 11 +++++------ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 7 +++++-- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index a419d60166c8..a7f737c4792e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -488,6 +488,11 @@ static void fill_engine_enable_masks(struct intel_gt *gt, info_map_write(info_map, engine_enabled_masks[GUC_BLITTER_CLASS], BCS_MASK(gt)); info_map_write(info_map, engine_enabled_masks[GUC_VIDEO_CLASS], VDBOX_MASK(gt)); info_map_write(info_map, engine_enabled_masks[GUC_VIDEOENHANCE_CLASS], VEBOX_MASK(gt)); + + /* The GSC engine is an instance (6) of OTHER_CLASS */ + if (gt->engine[GSC0]) + info_map_write(info_map, engine_enabled_masks[GUC_GSC_OTHER_CLASS], + BIT(gt->engine[GSC0]->instance)); } #define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) @@ -529,9 +534,6 @@ static int guc_prep_golden_context(struct intel_guc *guc) } for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) { - if (engine_class == OTHER_CLASS) - continue; - guc_class = engine_class_to_guc_class(engine_class); if (!info_map_read(&info_map, engine_enabled_masks[guc_class])) @@ -609,9 +611,6 @@ static void guc_init_golden_context(struct intel_guc *guc) addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) { - if (engine_class == OTHER_CLASS) - continue; - guc_class = engine_class_to_guc_class(engine_class); if (!ads_blob_read(guc, system_info.engine_enabled_masks[guc_class])) continue; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 968ebd79dce7..4ae5fc2f6002 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -47,7 +47,8 @@ #define GUC_VIDEOENHANCE_CLASS 2 #define GUC_BLITTER_CLASS 3 #define GUC_COMPUTE_CLASS 4 -#define GUC_LAST_ENGINE_CLASS GUC_COMPUTE_CLASS +#define GUC_GSC_OTHER_CLASS 5 +#define GUC_LAST_ENGINE_CLASS GUC_GSC_OTHER_CLASS #define GUC_MAX_ENGINE_CLASSES 16 #define GUC_MAX_INSTANCES_PER_CLASS 32 @@ -169,6 +170,7 @@ static u8 engine_class_guc_class_map[] = { [COPY_ENGINE_CLASS] = GUC_BLITTER_CLASS, [VIDEO_DECODE_CLASS] = GUC_VIDEO_CLASS, [VIDEO_ENHANCEMENT_CLASS] = GUC_VIDEOENHANCE_CLASS, + [OTHER_CLASS] = GUC_GSC_OTHER_CLASS, [COMPUTE_CLASS] = GUC_COMPUTE_CLASS, }; @@ -178,12 +180,13 @@ static u8 guc_class_engine_class_map[] = { [GUC_VIDEO_CLASS] = VIDEO_DECODE_CLASS, [GUC_VIDEOENHANCE_CLASS] = VIDEO_ENHANCEMENT_CLASS, [GUC_COMPUTE_CLASS] = COMPUTE_CLASS, + [GUC_GSC_OTHER_CLASS] = OTHER_CLASS, }; static inline u8 engine_class_to_guc_class(u8 class) { BUILD_BUG_ON(ARRAY_SIZE(engine_class_guc_class_map) != MAX_ENGINE_CLASS + 1); - GEM_BUG_ON(class > MAX_ENGINE_CLASS || class == OTHER_CLASS); + GEM_BUG_ON(class > MAX_ENGINE_CLASS); return engine_class_guc_class_map[class]; } -- cgit v1.2.3 From c07ee636901d1496caf81594f90fc68e9a9c7ba5 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 2 Nov 2022 10:10:45 -0700 Subject: drm/i915/mtl: add GSC CS interrupt support The GSC CS re-uses the same interrupt bits that the GSC used in older platforms. This means that we can now have an engine interrupt coming out of OTHER_CLASS, so we need to handle that appropriately. v2: clean up the if statement for the engine irq (Tvrtko) Signed-off-by: Daniele Ceraolo Spurio Cc: Matt Roper Cc: Tvrtko Ursulin Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20221102171047.2787951-4-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/intel_gt_irq.c | 75 ++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index f26882fdc24c..b197f0e9794f 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -81,35 +81,27 @@ gen11_other_irq_handler(struct intel_gt *gt, const u8 instance, instance, iir); } -static void -gen11_engine_irq_handler(struct intel_gt *gt, const u8 class, - const u8 instance, const u16 iir) +static struct intel_gt *pick_gt(struct intel_gt *gt, u8 class, u8 instance) { - struct intel_engine_cs *engine; - - /* - * Platforms with standalone media have their media engines in another - * GT. - */ - if (MEDIA_VER(gt->i915) >= 13 && - (class == VIDEO_DECODE_CLASS || class == VIDEO_ENHANCEMENT_CLASS)) { - if (!gt->i915->media_gt) - goto err; + struct intel_gt *media_gt = gt->i915->media_gt; - gt = gt->i915->media_gt; + /* we expect the non-media gt to be passed in */ + GEM_BUG_ON(gt == media_gt); + + if (!media_gt) + return gt; + + switch (class) { + case VIDEO_DECODE_CLASS: + case VIDEO_ENHANCEMENT_CLASS: + return media_gt; + case OTHER_CLASS: + if (instance == OTHER_GSC_INSTANCE && HAS_ENGINE(media_gt, GSC0)) + return media_gt; + fallthrough; + default: + return gt; } - - if (instance <= MAX_ENGINE_INSTANCE) - engine = gt->engine_class[class][instance]; - else - engine = NULL; - - if (likely(engine)) - return intel_engine_cs_irq(engine, iir); - -err: - WARN_ONCE(1, "unhandled engine interrupt class=0x%x, instance=0x%x\n", - class, instance); } static void @@ -122,8 +114,17 @@ gen11_gt_identity_handler(struct intel_gt *gt, const u32 identity) if (unlikely(!intr)) return; - if (class <= COPY_ENGINE_CLASS || class == COMPUTE_CLASS) - return gen11_engine_irq_handler(gt, class, instance, intr); + /* + * Platforms with standalone media have the media and GSC engines in + * another GT. + */ + gt = pick_gt(gt, class, instance); + + if (class <= MAX_ENGINE_CLASS && instance <= MAX_ENGINE_INSTANCE) { + struct intel_engine_cs *engine = gt->engine_class[class][instance]; + if (engine) + return intel_engine_cs_irq(engine, intr); + } if (class == OTHER_CLASS) return gen11_other_irq_handler(gt, instance, intr); @@ -206,7 +207,7 @@ void gen11_gt_irq_reset(struct intel_gt *gt) intel_uncore_write(uncore, GEN11_VCS_VECS_INTR_ENABLE, 0); if (CCS_MASK(gt)) intel_uncore_write(uncore, GEN12_CCS_RSVD_INTR_ENABLE, 0); - if (HAS_HECI_GSC(gt->i915)) + if (HAS_HECI_GSC(gt->i915) || HAS_ENGINE(gt, GSC0)) intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE, 0); /* Restore masks irqs on RCS, BCS, VCS and VECS engines. */ @@ -233,7 +234,7 @@ void gen11_gt_irq_reset(struct intel_gt *gt) intel_uncore_write(uncore, GEN12_CCS0_CCS1_INTR_MASK, ~0); if (HAS_ENGINE(gt, CCS2) || HAS_ENGINE(gt, CCS3)) intel_uncore_write(uncore, GEN12_CCS2_CCS3_INTR_MASK, ~0); - if (HAS_HECI_GSC(gt->i915)) + if (HAS_HECI_GSC(gt->i915) || HAS_ENGINE(gt, GSC0)) intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~0); intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0); @@ -249,7 +250,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) { struct intel_uncore *uncore = gt->uncore; u32 irqs = GT_RENDER_USER_INTERRUPT; - const u32 gsc_mask = GSC_IRQ_INTF(0) | GSC_IRQ_INTF(1); + u32 gsc_mask = 0; u32 dmask; u32 smask; @@ -261,6 +262,11 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) dmask = irqs << 16 | irqs; smask = irqs << 16; + if (HAS_ENGINE(gt, GSC0)) + gsc_mask = irqs; + else if (HAS_HECI_GSC(gt->i915)) + gsc_mask = GSC_IRQ_INTF(0) | GSC_IRQ_INTF(1); + BUILD_BUG_ON(irqs & 0xffff0000); /* Enable RCS, BCS, VCS and VECS class interrupts. */ @@ -268,9 +274,8 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) intel_uncore_write(uncore, GEN11_VCS_VECS_INTR_ENABLE, dmask); if (CCS_MASK(gt)) intel_uncore_write(uncore, GEN12_CCS_RSVD_INTR_ENABLE, smask); - if (HAS_HECI_GSC(gt->i915)) - intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE, - gsc_mask); + if (gsc_mask) + intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE, gsc_mask); /* Unmask irqs on RCS, BCS, VCS and VECS engines. */ intel_uncore_write(uncore, GEN11_RCS0_RSVD_INTR_MASK, ~smask); @@ -296,7 +301,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) intel_uncore_write(uncore, GEN12_CCS0_CCS1_INTR_MASK, ~dmask); if (HAS_ENGINE(gt, CCS2) || HAS_ENGINE(gt, CCS3)) intel_uncore_write(uncore, GEN12_CCS2_CCS3_INTR_MASK, ~dmask); - if (HAS_HECI_GSC(gt->i915)) + if (gsc_mask) intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~gsc_mask); /* -- cgit v1.2.3 From ef8281abb149c1ed66fe80e28faca4e350ff4c60 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 2 Nov 2022 10:10:46 -0700 Subject: drm/i915/mtl: add GSC CS reset support The GSC CS has its own dedicated bit in the GDRST register. Bspec: 52549 Signed-off-by: Daniele Ceraolo Spurio Cc: Matt Roper Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20221102171047.2787951-5-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 1 + drivers/gpu/drm/i915/gt/intel_gt_regs.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index e0fbfac03979..f63829abf66c 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -423,6 +423,7 @@ static u32 get_reset_domain(u8 ver, enum intel_engine_id id) [CCS1] = GEN11_GRDOM_RENDER, [CCS2] = GEN11_GRDOM_RENDER, [CCS3] = GEN11_GRDOM_RENDER, + [GSC0] = GEN12_GRDOM_GSC, }; GEM_BUG_ON(id >= ARRAY_SIZE(engine_reset_domains) || !engine_reset_domains[id]); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 70177d3f2e94..8aa06b0327e5 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -643,6 +643,7 @@ #define XEHPC_GRDOM_BLT3 REG_BIT(26) #define XEHPC_GRDOM_BLT2 REG_BIT(25) #define XEHPC_GRDOM_BLT1 REG_BIT(24) +#define GEN12_GRDOM_GSC REG_BIT(21) #define GEN11_GRDOM_SFC3 REG_BIT(20) #define GEN11_GRDOM_SFC2 REG_BIT(19) #define GEN11_GRDOM_SFC1 REG_BIT(18) -- cgit v1.2.3 From 194babe26bdcf6b9dec98907dc13f319baf01e43 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 2 Nov 2022 10:10:47 -0700 Subject: drm/i915/mtl: don't expose GSC command streamer to the user There is no userspace user for this CS yet, we only need it for internal kernel ops (e.g. HuC, PXP), so don't expose it. v2: even if it's not exposed, rename the engine so it is easier to identify in the debug logs (Matt) Signed-off-by: Daniele Ceraolo Spurio Cc: Matt Roper Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20221102171047.2787951-6-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_user.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c index 79312b734690..cd4f1b126f75 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_user.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c @@ -191,6 +191,15 @@ static void add_legacy_ring(struct legacy_ring *ring, ring->instance++; } +static void engine_rename(struct intel_engine_cs *engine, const char *name, u16 instance) +{ + char old[sizeof(engine->name)]; + + memcpy(old, engine->name, sizeof(engine->name)); + scnprintf(engine->name, sizeof(engine->name), "%s%u", name, instance); + drm_dbg(&engine->i915->drm, "renamed %s to %s\n", old, engine->name); +} + void intel_engines_driver_register(struct drm_i915_private *i915) { struct legacy_ring ring = {}; @@ -206,11 +215,19 @@ void intel_engines_driver_register(struct drm_i915_private *i915) struct intel_engine_cs *engine = container_of((struct rb_node *)it, typeof(*engine), uabi_node); - char old[sizeof(engine->name)]; if (intel_gt_has_unrecoverable_error(engine->gt)) continue; /* ignore incomplete engines */ + /* + * We don't want to expose the GSC engine to the users, but we + * still rename it so it is easier to identify in the debug logs + */ + if (engine->id == GSC0) { + engine_rename(engine, "gsc", 0); + continue; + } + GEM_BUG_ON(engine->class >= ARRAY_SIZE(uabi_classes)); engine->uabi_class = uabi_classes[engine->class]; @@ -220,11 +237,9 @@ void intel_engines_driver_register(struct drm_i915_private *i915) i915->engine_uabi_class_count[engine->uabi_class]++; /* Replace the internal name with the final user facing name */ - memcpy(old, engine->name, sizeof(engine->name)); - scnprintf(engine->name, sizeof(engine->name), "%s%u", - intel_engine_class_repr(engine->class), - engine->uabi_instance); - DRM_DEBUG_DRIVER("renamed %s to %s\n", old, engine->name); + engine_rename(engine, + intel_engine_class_repr(engine->class), + engine->uabi_instance); rb_link_node(&engine->uabi_node, prev, p); rb_insert_color(&engine->uabi_node, &i915->uabi_engines); -- cgit v1.2.3 From 8b693ea26c209757a4c96cf4463cc597a3625e19 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 2 Nov 2022 14:43:10 -0700 Subject: drm/i915/guc: don't hardcode BCS0 in guc_hang selftest On MTL there are no BCS engines on the media GT, so we can't always use BCS0 in the test. There is no actual reason to use a BCS engine over an engine of a different class, so switch to using any available engine. Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Acked-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20221102214310.2829310-1-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c index 01f8cd3c3134..d91b58f70403 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c @@ -35,11 +35,14 @@ static int intel_hang_guc(void *arg) struct i915_request *rq; intel_wakeref_t wakeref; struct i915_gpu_error *global = >->i915->gpu_error; - struct intel_engine_cs *engine; + struct intel_engine_cs *engine = intel_selftest_find_any_engine(gt); unsigned int reset_count; u32 guc_status; u32 old_beat; + if (!engine) + return 0; + ctx = kernel_context(gt->i915, NULL); if (IS_ERR(ctx)) { drm_err(>->i915->drm, "Failed get kernel context: %ld\n", PTR_ERR(ctx)); @@ -48,14 +51,13 @@ static int intel_hang_guc(void *arg) wakeref = intel_runtime_pm_get(gt->uncore->rpm); - ce = intel_context_create(gt->engine[BCS0]); + ce = intel_context_create(engine); if (IS_ERR(ce)) { ret = PTR_ERR(ce); drm_err(>->i915->drm, "Failed to create spinner request: %d\n", ret); goto err; } - engine = ce->engine; reset_count = i915_reset_count(global); old_beat = engine->props.heartbeat_interval_ms; -- cgit v1.2.3 From ed4314f7729714d788698ade4f9905ee5378ebc0 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Fri, 4 Nov 2022 09:30:04 +0100 Subject: net: stmmac: dwmac-meson8b: fix meson8b_devm_clk_prepare_enable() There are two problems with meson8b_devm_clk_prepare_enable(), introduced in commit a54dc4a49045 ("net: stmmac: dwmac-meson8b: Make the clock enabling code re-usable"): - It doesn't pass the clk argument, but instead always the rgmii_tx_clk of the device. - It silently ignores the return value of devm_add_action_or_reset(). The former didn't become an actual bug until another user showed up in the next commit 9308c47640d5 ("net: stmmac: dwmac-meson8b: add support for the RX delay configuration"). The latter means the callers could end up with the clock not actually prepared/enabled. Fixes: a54dc4a49045 ("net: stmmac: dwmac-meson8b: Make the clock enabling code re-usable") Signed-off-by: Rasmus Villemoes Reviewed-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20221104083004.2212520-1-linux@rasmusvillemoes.dk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index c7a6588d9398..e8b507f88fbc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c @@ -272,11 +272,9 @@ static int meson8b_devm_clk_prepare_enable(struct meson8b_dwmac *dwmac, if (ret) return ret; - devm_add_action_or_reset(dwmac->dev, - (void(*)(void *))clk_disable_unprepare, - dwmac->rgmii_tx_clk); - - return 0; + return devm_add_action_or_reset(dwmac->dev, + (void(*)(void *))clk_disable_unprepare, + clk); } static int meson8b_init_rgmii_delays(struct meson8b_dwmac *dwmac) -- cgit v1.2.3 From 5d7bebf2dfb0dc97aac1fbace0910e557ecdb16f Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 7 Nov 2022 20:48:28 +0800 Subject: scsi: scsi_transport_sas: Fix error handling in sas_phy_add() If transport_add_device() fails in sas_phy_add(), the kernel will crash trying to delete the device in transport_remove_device() called from sas_remove_host(). Unable to handle kernel NULL pointer dereference at virtual address 0000000000000108 CPU: 61 PID: 42829 Comm: rmmod Kdump: loaded Tainted: G W 6.1.0-rc1+ #173 pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : device_del+0x54/0x3d0 lr : device_del+0x37c/0x3d0 Call trace: device_del+0x54/0x3d0 attribute_container_class_device_del+0x28/0x38 transport_remove_classdev+0x6c/0x80 attribute_container_device_trigger+0x108/0x110 transport_remove_device+0x28/0x38 sas_phy_delete+0x30/0x60 [scsi_transport_sas] do_sas_phy_delete+0x6c/0x80 [scsi_transport_sas] device_for_each_child+0x68/0xb0 sas_remove_children+0x40/0x50 [scsi_transport_sas] sas_remove_host+0x20/0x38 [scsi_transport_sas] hisi_sas_remove+0x40/0x68 [hisi_sas_main] hisi_sas_v2_remove+0x20/0x30 [hisi_sas_v2_hw] platform_remove+0x2c/0x60 Fix this by checking and handling return value of transport_add_device() in sas_phy_add(). Fixes: c7ebbbce366c ("[SCSI] SAS transport class") Suggested-by: John Garry Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221107124828.115557-1-yangyingliang@huawei.com Reviewed-by: John Garry Reviewed-by: Jason Yan Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_sas.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 2f88c61216ee..74b99f2b0b74 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -722,12 +722,17 @@ int sas_phy_add(struct sas_phy *phy) int error; error = device_add(&phy->dev); - if (!error) { - transport_add_device(&phy->dev); - transport_configure_device(&phy->dev); + if (error) + return error; + + error = transport_add_device(&phy->dev); + if (error) { + device_del(&phy->dev); + return error; } + transport_configure_device(&phy->dev); - return error; + return 0; } EXPORT_SYMBOL(sas_phy_add); -- cgit v1.2.3 From 02f5999e652952d69c341a03d4313310703fd7f1 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sat, 5 Nov 2022 14:34:42 +0800 Subject: octeontx2-pf: fix build error when CONFIG_OCTEONTX2_PF=y If CONFIG_MACSEC=m and CONFIG_OCTEONTX2_PF=y, it leads a build error: ld: drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.o: in function `otx2_pfaf_mbox_up_handler': otx2_pf.c:(.text+0x181c): undefined reference to `cn10k_handle_mcs_event' ld: drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.o: in function `otx2_probe': otx2_pf.c:(.text+0x437e): undefined reference to `cn10k_mcs_init' ld: drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.o: in function `otx2_remove': otx2_pf.c:(.text+0x5031): undefined reference to `cn10k_mcs_free' ld: drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.o: in function `otx2_mbox_up_handler_mcs_intr_notify': otx2_pf.c:(.text+0x5f11): undefined reference to `cn10k_handle_mcs_event' Make CONFIG_OCTEONTX2_PF depends on CONFIG_MACSEC to fix it. Because it has empty stub functions of cn10k, CONFIG_OCTEONTX2_PF can be enabled if CONFIG_MACSEC is disabled Fixes: c54ffc73601c ("octeontx2-pf: mcs: Introduce MACSEC hardware offloading") Reported-by: kernel test robot Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221105063442.2013981-1-yangyingliang@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig index 993ac180a5db..6b4f640163f7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/Kconfig +++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig @@ -32,6 +32,7 @@ config OCTEONTX2_PF tristate "Marvell OcteonTX2 NIC Physical Function driver" select OCTEONTX2_MBOX select NET_DEVLINK + depends on MACSEC || !MACSEC depends on (64BIT && COMPILE_TEST) || ARM64 select DIMLIB depends on PCI -- cgit v1.2.3 From 8d820bc9d12b8beebca836cceaf2bbe68216c2f8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 5 Nov 2022 17:02:45 +0800 Subject: net: broadcom: Fix BCMGENET Kconfig While BCMGENET select BROADCOM_PHY as y, but PTP_1588_CLOCK_OPTIONAL is m, kconfig warning and build errors: WARNING: unmet direct dependencies detected for BROADCOM_PHY Depends on [m]: NETDEVICES [=y] && PHYLIB [=y] && PTP_1588_CLOCK_OPTIONAL [=m] Selected by [y]: - BCMGENET [=y] && NETDEVICES [=y] && ETHERNET [=y] && NET_VENDOR_BROADCOM [=y] && HAS_IOMEM [=y] && ARCH_BCM2835 [=y] drivers/net/phy/broadcom.o: In function `bcm54xx_suspend': broadcom.c:(.text+0x6ac): undefined reference to `bcm_ptp_stop' drivers/net/phy/broadcom.o: In function `bcm54xx_phy_probe': broadcom.c:(.text+0x784): undefined reference to `bcm_ptp_probe' drivers/net/phy/broadcom.o: In function `bcm54xx_config_init': broadcom.c:(.text+0xd4c): undefined reference to `bcm_ptp_config_init' Fixes: 99addbe31f55 ("net: broadcom: Select BROADCOM_PHY for BCMGENET") Signed-off-by: YueHaibing Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20221105090245.8508-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index f4e1ca68d831..55dfdb34e37b 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -77,7 +77,7 @@ config BCMGENET select BCM7XXX_PHY select MDIO_BCM_UNIMAC select DIMLIB - select BROADCOM_PHY if ARCH_BCM2835 + select BROADCOM_PHY if (ARCH_BCM2835 && PTP_1588_CLOCK_OPTIONAL) help This driver supports the built-in Ethernet MACs found in the Broadcom BCM7xxx Set Top Box family chipset. -- cgit v1.2.3 From ecb8c2580d37dbb641451049376d80c8afaa387f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 2 Nov 2022 12:32:48 -0700 Subject: scsi: scsi_debug: Make the READ CAPACITY response compliant with ZBC From ZBC-1: - RC BASIS = 0: The RETURNED LOGICAL BLOCK ADDRESS field indicates the highest LBA of a contiguous range of zones that are not sequential write required zones starting with the first zone. - RC BASIS = 1: The RETURNED LOGICAL BLOCK ADDRESS field indicates the LBA of the last logical block on the logical unit. The current scsi_debug READ CAPACITY response does not comply with the above if there are one or more sequential write required zones. SCSI initiators need a way to retrieve the largest valid LBA from SCSI devices. Reporting the largest valid LBA if there are one or more sequential zones requires to set the RC BASIS field in the READ CAPACITY response to one. Hence this patch. Cc: Douglas Gilbert Cc: Damien Le Moal Suggested-by: Damien Le Moal Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20221102193248.3177608-1-bvanassche@acm.org Reviewed-by: Damien Le Moal Acked-by: Douglas Gilbert Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 697fc57bc711..629853662b82 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1899,6 +1899,13 @@ static int resp_readcap16(struct scsi_cmnd *scp, arr[14] |= 0x40; } + /* + * Since the scsi_debug READ CAPACITY implementation always reports the + * total disk capacity, set RC BASIS = 1 for host-managed ZBC devices. + */ + if (devip->zmodel == BLK_ZONED_HM) + arr[12] |= 1 << 4; + arr[15] = sdebug_lowest_aligned & 0xff; if (have_dif_prot) { -- cgit v1.2.3 From b3d726cb8497c6b12106fd617d46eef11763ea86 Mon Sep 17 00:00:00 2001 From: Doug Brown Date: Mon, 5 Sep 2022 17:07:09 -0700 Subject: dmaengine: pxa_dma: use platform_get_irq_optional The first IRQ is required, but IRQs 1 through (nb_phy_chans - 1) are optional, because on some platforms (e.g. PXA168) there is a single IRQ shared between all channels. This change inhibits a flood of "IRQ index # not found" messages at startup. Tested on a PXA168-based device. Fixes: 7723f4c5ecdb ("driver core: platform: Add an error message to platform_get_irq*()") Signed-off-by: Doug Brown Link: https://lore.kernel.org/r/20220906000709.52705-1-doug@schmorgal.com Signed-off-by: Vinod Koul --- drivers/dma/pxa_dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index e7034f6f3994..22a392fe6d32 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -1247,14 +1247,14 @@ static int pxad_init_phys(struct platform_device *op, return -ENOMEM; for (i = 0; i < nb_phy_chans; i++) - if (platform_get_irq(op, i) > 0) + if (platform_get_irq_optional(op, i) > 0) nr_irq++; for (i = 0; i < nb_phy_chans; i++) { phy = &pdev->phys[i]; phy->base = pdev->base; phy->idx = i; - irq = platform_get_irq(op, i); + irq = platform_get_irq_optional(op, i); if ((nr_irq > 1) && (irq > 0)) ret = devm_request_irq(&op->dev, irq, pxad_chan_handler, -- cgit v1.2.3 From e8dbd6445dd6b38c4c50410a86f13158486ee99a Mon Sep 17 00:00:00 2001 From: Xiaochen Shen Date: Sat, 1 Oct 2022 04:15:27 +0800 Subject: dmaengine: idxd: Fix max batch size for Intel IAA >From Intel IAA spec [1], Intel IAA does not support batch processing. Two batch related default values for IAA are incorrect in current code: (1) The max batch size of device is set during device initialization, that indicates batch is supported. It should be always 0 on IAA. (2) The max batch size of work queue is set to WQ_DEFAULT_MAX_BATCH (32) as the default value regardless of Intel DSA or IAA device during work queue setup and cleanup. It should be always 0 on IAA. Fix the issues by setting the max batch size of device and max batch size of work queue to 0 on IAA device, that means batch is not supported. [1]: https://cdrdv2.intel.com/v1/dl/getContent/721858 Fixes: 23084545dbb0 ("dmaengine: idxd: set max_xfer and max_batch for RO device") Fixes: 92452a72ebdf ("dmaengine: idxd: set defaults for wq configs") Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Xiaochen Shen Reviewed-by: Dave Jiang Reviewed-by: Fenghua Yu Link: https://lore.kernel.org/r/20220930201528.18621-2-xiaochen.shen@intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/device.c | 6 +++--- drivers/dma/idxd/idxd.h | 32 ++++++++++++++++++++++++++++++++ drivers/dma/idxd/init.c | 4 ++-- drivers/dma/idxd/sysfs.c | 2 +- 4 files changed, 38 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index 2c1e6f6daa62..670b71927db0 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -390,7 +390,7 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq) clear_bit(WQ_FLAG_ATS_DISABLE, &wq->flags); memset(wq->name, 0, WQ_NAME_SIZE); wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER; - wq->max_batch_size = WQ_DEFAULT_MAX_BATCH; + idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH); if (wq->opcap_bmap) bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS); } @@ -869,7 +869,7 @@ static int idxd_wq_config_write(struct idxd_wq *wq) /* bytes 12-15 */ wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes); - wq->wqcfg->max_batch_shift = ilog2(wq->max_batch_size); + idxd_wqcfg_set_max_batch_shift(idxd->data->type, wq->wqcfg, ilog2(wq->max_batch_size)); /* bytes 32-63 */ if (idxd->hw.wq_cap.op_config && wq->opcap_bmap) { @@ -1051,7 +1051,7 @@ static int idxd_wq_load_config(struct idxd_wq *wq) wq->priority = wq->wqcfg->priority; wq->max_xfer_bytes = 1ULL << wq->wqcfg->max_xfer_shift; - wq->max_batch_size = 1ULL << wq->wqcfg->max_batch_shift; + idxd_wq_set_max_batch_size(idxd->data->type, wq, 1U << wq->wqcfg->max_batch_shift); for (i = 0; i < WQCFG_STRIDES(idxd); i++) { wqcfg_offset = WQCFG_OFFSET(idxd, wq->id, i); diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index 1196ab342f01..7ced8d283d98 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -548,6 +548,38 @@ static inline int idxd_wq_refcount(struct idxd_wq *wq) return wq->client_count; }; +/* + * Intel IAA does not support batch processing. + * The max batch size of device, max batch size of wq and + * max batch shift of wqcfg should be always 0 on IAA. + */ +static inline void idxd_set_max_batch_size(int idxd_type, struct idxd_device *idxd, + u32 max_batch_size) +{ + if (idxd_type == IDXD_TYPE_IAX) + idxd->max_batch_size = 0; + else + idxd->max_batch_size = max_batch_size; +} + +static inline void idxd_wq_set_max_batch_size(int idxd_type, struct idxd_wq *wq, + u32 max_batch_size) +{ + if (idxd_type == IDXD_TYPE_IAX) + wq->max_batch_size = 0; + else + wq->max_batch_size = max_batch_size; +} + +static inline void idxd_wqcfg_set_max_batch_shift(int idxd_type, union wqcfg *wqcfg, + u32 max_batch_shift) +{ + if (idxd_type == IDXD_TYPE_IAX) + wqcfg->max_batch_shift = 0; + else + wqcfg->max_batch_shift = max_batch_shift; +} + int __must_check __idxd_driver_register(struct idxd_device_driver *idxd_drv, struct module *module, const char *mod_name); #define idxd_driver_register(driver) \ diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 2b18d512cbfc..09cbf0c179ba 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -183,7 +183,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd) init_completion(&wq->wq_dead); init_completion(&wq->wq_resurrect); wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER; - wq->max_batch_size = WQ_DEFAULT_MAX_BATCH; + idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH); wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); if (!wq->wqcfg) { @@ -418,7 +418,7 @@ static void idxd_read_caps(struct idxd_device *idxd) idxd->max_xfer_bytes = 1ULL << idxd->hw.gen_cap.max_xfer_shift; dev_dbg(dev, "max xfer size: %llu bytes\n", idxd->max_xfer_bytes); - idxd->max_batch_size = 1U << idxd->hw.gen_cap.max_batch_shift; + idxd_set_max_batch_size(idxd->data->type, idxd, 1U << idxd->hw.gen_cap.max_batch_shift); dev_dbg(dev, "max batch size: %u\n", idxd->max_batch_size); if (idxd->hw.gen_cap.config_en) set_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags); diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index bdaccf9e0436..7269bd54554f 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -1046,7 +1046,7 @@ static ssize_t wq_max_batch_size_store(struct device *dev, struct device_attribu if (batch_size > idxd->max_batch_size) return -EINVAL; - wq->max_batch_size = (u32)batch_size; + idxd_wq_set_max_batch_size(idxd->data->type, wq, (u32)batch_size); return count; } -- cgit v1.2.3 From 0b8c97a1d8c1bb6a853b8bb1778e8fef17b86fc9 Mon Sep 17 00:00:00 2001 From: Fengqian Gao Date: Fri, 30 Sep 2022 11:28:35 +0800 Subject: dmaengine: idxd: fix RO device state error after been disabled/reset When IDXD is not configurable, that means its WQ, engine, and group configurations cannot be changed. But it can be disabled and its state should be set as disabled regardless it's configurable or not. Fix this by setting device state IDXD_DEV_DISABLED for read-only device as well in idxd_device_clear_state(). Fixes: cf4ac3fef338 ("dmaengine: idxd: fix lockdep warning on device driver removal") Signed-off-by: Fengqian Gao Reviewed-by: Xiaochen Shen Reviewed-by: Dave Jiang Reviewed-by: Fenghua Yu Link: https://lore.kernel.org/r/20220930032835.2290-1-fengqian.gao@intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/device.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index 670b71927db0..6f44fa8f78a5 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -730,13 +730,21 @@ static void idxd_device_wqs_clear_state(struct idxd_device *idxd) void idxd_device_clear_state(struct idxd_device *idxd) { - if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) - return; + /* IDXD is always disabled. Other states are cleared only when IDXD is configurable. */ + if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) { + /* + * Clearing wq state is protected by wq lock. + * So no need to be protected by device lock. + */ + idxd_device_wqs_clear_state(idxd); + + spin_lock(&idxd->dev_lock); + idxd_groups_clear_state(idxd); + idxd_engines_clear_state(idxd); + } else { + spin_lock(&idxd->dev_lock); + } - idxd_device_wqs_clear_state(idxd); - spin_lock(&idxd->dev_lock); - idxd_groups_clear_state(idxd); - idxd_engines_clear_state(idxd); idxd->state = IDXD_DEV_DISABLED; spin_unlock(&idxd->dev_lock); } -- cgit v1.2.3 From 8454f880c24bca0d9d4bfb6ed4a4a5429a4d9b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Wed, 19 Oct 2022 15:23:23 +0200 Subject: dmaengine: apple-admac: Fix grabbing of channels in of_xlate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The of_xlate callback is supposed to return the channel after already having 'grabbed' it for private use, so fill that in. Fixes: b127315d9a78 ("dmaengine: apple-admac: Add Apple ADMAC driver") Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20221019132324.8585-1-povik+lin@cutebit.org Signed-off-by: Vinod Koul --- drivers/dma/apple-admac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c index 317ca76ccafd..a2cc520225d3 100644 --- a/drivers/dma/apple-admac.c +++ b/drivers/dma/apple-admac.c @@ -493,7 +493,7 @@ static struct dma_chan *admac_dma_of_xlate(struct of_phandle_args *dma_spec, return NULL; } - return &ad->channels[index].chan; + return dma_get_slave_channel(&ad->channels[index].chan); } static int admac_drain_reports(struct admac_data *ad, int channo) -- cgit v1.2.3 From 081195d17a0c4c636da2b869bd5809d42e8cbb13 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 24 Oct 2022 21:50:09 +0200 Subject: dmaengine: mv_xor_v2: Fix a resource leak in mv_xor_v2_remove() A clk_prepare_enable() call in the probe is not balanced by a corresponding clk_disable_unprepare() in the remove function. Add the missing call. Fixes: 3cd2c313f1d6 ("dmaengine: mv_xor_v2: Fix clock resource by adding a register clock") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/e9e3837a680c9bd2438e4db2b83270c6c052d005.1666640987.git.christophe.jaillet@wanadoo.fr Signed-off-by: Vinod Koul --- drivers/dma/mv_xor_v2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index f629ef6fd3c2..113834e1167b 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -893,6 +893,7 @@ static int mv_xor_v2_remove(struct platform_device *pdev) tasklet_kill(&xor_dev->irq_tasklet); clk_disable_unprepare(xor_dev->clk); + clk_disable_unprepare(xor_dev->reg_clk); return 0; } -- cgit v1.2.3 From ac2b9f34f02052709aea7b34bb2a165e1853eb41 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 20 Oct 2022 14:28:27 +0800 Subject: dmaengine: ti: k3-udma-glue: fix memory leak when register device fail If device_register() fails, it should call put_device() to give up reference, the name allocated in dev_set_name() can be freed in callback function kobject_cleanup(). Fixes: 5b65781d06ea ("dmaengine: ti: k3-udma-glue: Add support for K3 PKTDMA") Signed-off-by: Yang Yingliang Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20221020062827.2914148-1-yangyingliang@huawei.com Signed-off-by: Vinod Koul --- drivers/dma/ti/k3-udma-glue.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c index 4fdd9f06b723..4f1aeb81e9c7 100644 --- a/drivers/dma/ti/k3-udma-glue.c +++ b/drivers/dma/ti/k3-udma-glue.c @@ -299,6 +299,7 @@ struct k3_udma_glue_tx_channel *k3_udma_glue_request_tx_chn(struct device *dev, ret = device_register(&tx_chn->common.chan_dev); if (ret) { dev_err(dev, "Channel Device registration failed %d\n", ret); + put_device(&tx_chn->common.chan_dev); tx_chn->common.chan_dev.parent = NULL; goto err; } @@ -917,6 +918,7 @@ k3_udma_glue_request_rx_chn_priv(struct device *dev, const char *name, ret = device_register(&rx_chn->common.chan_dev); if (ret) { dev_err(dev, "Channel Device registration failed %d\n", ret); + put_device(&rx_chn->common.chan_dev); rx_chn->common.chan_dev.parent = NULL; goto err; } @@ -1048,6 +1050,7 @@ k3_udma_glue_request_remote_rx_chn(struct device *dev, const char *name, ret = device_register(&rx_chn->common.chan_dev); if (ret) { dev_err(dev, "Channel Device registration failed %d\n", ret); + put_device(&rx_chn->common.chan_dev); rx_chn->common.chan_dev.parent = NULL; goto err; } -- cgit v1.2.3 From 140fd5e74a1cc7413df88c735fff5ec64d33c1d3 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Mon, 24 Oct 2022 10:36:11 +0200 Subject: dmaengine: stm32-dma: fix potential race between pause and resume When disabling dma channel, a TCF flag is set and as TCIE is enabled, an interrupt is raised. On a busy system, the interrupt may have latency and the user can ask for dmaengine_resume while stm32-dma driver has not yet managed the complete pause (backup of registers to restore state in resume). To avoid such a case, instead of waiting the interrupt to backup the registers, do it just after disabling the channel and discard Transfer Complete interrupt in case the channel is paused. Fixes: 099a9a94be0e ("dmaengine: stm32-dma: add device_pause/device_resume support") Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20221024083611.132588-1-amelie.delaunay@foss.st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 4891a1767e5a..37674029cb42 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -675,6 +675,8 @@ static void stm32_dma_handle_chan_paused(struct stm32_dma_chan *chan) chan->chan_reg.dma_sndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id)); + chan->status = DMA_PAUSED; + dev_dbg(chan2dev(chan), "vchan %pK: paused\n", &chan->vchan); } @@ -789,9 +791,7 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) if (status & STM32_DMA_TCI) { stm32_dma_irq_clear(chan, STM32_DMA_TCI); if (scr & STM32_DMA_SCR_TCIE) { - if (chan->status == DMA_PAUSED && !(scr & STM32_DMA_SCR_EN)) - stm32_dma_handle_chan_paused(chan); - else + if (chan->status != DMA_PAUSED) stm32_dma_handle_chan_done(chan, scr); } status &= ~STM32_DMA_TCI; @@ -838,13 +838,11 @@ static int stm32_dma_pause(struct dma_chan *c) return -EPERM; spin_lock_irqsave(&chan->vchan.lock, flags); + ret = stm32_dma_disable_chan(chan); - /* - * A transfer complete flag is set to indicate the end of transfer due to the stream - * interruption, so wait for interrupt - */ if (!ret) - chan->status = DMA_PAUSED; + stm32_dma_handle_chan_paused(chan); + spin_unlock_irqrestore(&chan->vchan.lock, flags); return ret; -- cgit v1.2.3 From f1171bbdd2ba2a50ee64bb198a78c268a5baf5f1 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:35 +0300 Subject: dmaengine: at_hdmac: Fix at_lli struct definition Those hardware registers are all of 32 bits, while dma_addr_t ca be of type u64 or u32 depending on CONFIG_ARCH_DMA_ADDR_T_64BIT. Force u32 to comply with what the hardware expects. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-2-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac_regs.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index 4d1ebc040031..d4d382d74607 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -186,13 +186,13 @@ /* LLI == Linked List Item; aka DMA buffer descriptor */ struct at_lli { /* values that are not changed by hardware */ - dma_addr_t saddr; - dma_addr_t daddr; + u32 saddr; + u32 daddr; /* value that may get written back: */ - u32 ctrla; + u32 ctrla; /* more values that are not changed by hardware */ - u32 ctrlb; - dma_addr_t dscr; /* chain to next lli */ + u32 ctrlb; + u32 dscr; /* chain to next lli */ }; /** -- cgit v1.2.3 From 7176a6a8982d311e50a7c1168868d26e65bbba19 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:36 +0300 Subject: dmaengine: at_hdmac: Don't start transactions at tx_submit level tx_submit is supposed to push the current transaction descriptor to a pending queue, waiting for issue_pending() to be called. issue_pending() must start the transfer, not tx_submit(), thus remove atc_dostart() from atc_tx_submit(). Clients of at_xdmac that assume that tx_submit() starts the transfer must be updated and call dma_async_issue_pending() if they miss to call it. The vdbg print was moved to after the lock is released. It is desirable to do the prints without the lock held if possible, and because the if statement disappears there's no reason why to do the print while holding the lock. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-3-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 5a50423b7378..3f71f4d2f467 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -691,19 +691,11 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx) spin_lock_irqsave(&atchan->lock, flags); cookie = dma_cookie_assign(tx); - if (list_empty(&atchan->active_list)) { - dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n", - desc->txd.cookie); - atc_dostart(atchan, desc); - list_add_tail(&desc->desc_node, &atchan->active_list); - } else { - dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n", - desc->txd.cookie); - list_add_tail(&desc->desc_node, &atchan->queue); - } - + list_add_tail(&desc->desc_node, &atchan->queue); spin_unlock_irqrestore(&atchan->lock, flags); + dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n", + desc->txd.cookie); return cookie; } -- cgit v1.2.3 From 8a47221fc28417ff8a32a4f92d4448a56c3cf7e1 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:37 +0300 Subject: dmaengine: at_hdmac: Start transfer for cyclic channels in issue_pending Cyclic channels must too call issue_pending in order to start a transfer. Start the transfer in issue_pending regardless of the type of channel. This wrongly worked before, because in the past the transfer was started at tx_submit level when only a desc in the transfer list. Fixes: 53830cc75974 ("dmaengine: at_hdmac: add cyclic DMA operation support") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-4-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 3f71f4d2f467..e9d0c3632868 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1536,10 +1536,6 @@ static void atc_issue_pending(struct dma_chan *chan) dev_vdbg(chan2dev(chan), "issue_pending\n"); - /* Not needed for cyclic transfers */ - if (atc_chan_is_cyclic(atchan)) - return; - atc_advance_work(atchan); } -- cgit v1.2.3 From fcd37565efdaffeac179d0f0ce980ac79bfdf569 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:38 +0300 Subject: dmaengine: at_hdmac: Fix premature completion of desc in issue_pending Multiple calls to atc_issue_pending() could result in a premature completion of a descriptor from the atchan->active list, as the method always completed the first active descriptor from the list. Instead, issue_pending() should just take the first transaction descriptor from the pending queue, move it to active_list and start the transfer. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-5-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index e9d0c3632868..cb5522417db6 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1527,16 +1527,26 @@ atc_tx_status(struct dma_chan *chan, } /** - * atc_issue_pending - try to finish work + * atc_issue_pending - takes the first transaction descriptor in the pending + * queue and starts the transfer. * @chan: target DMA channel */ static void atc_issue_pending(struct dma_chan *chan) { - struct at_dma_chan *atchan = to_at_dma_chan(chan); + struct at_dma_chan *atchan = to_at_dma_chan(chan); + struct at_desc *desc; + unsigned long flags; dev_vdbg(chan2dev(chan), "issue_pending\n"); - atc_advance_work(atchan); + spin_lock_irqsave(&atchan->lock, flags); + if (atc_chan_is_enabled(atchan) || list_empty(&atchan->queue)) + return spin_unlock_irqrestore(&atchan->lock, flags); + + desc = atc_first_queued(atchan); + list_move_tail(&desc->desc_node, &atchan->active_list); + atc_dostart(atchan, desc); + spin_unlock_irqrestore(&atchan->lock, flags); } /** -- cgit v1.2.3 From f645f85ae1104f8bd882f962ac0a69a1070076dd Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:39 +0300 Subject: dmaengine: at_hdmac: Do not call the complete callback on device_terminate_all The method was wrong because it violated the dmaengine API. For aborted transfers the complete callback should not be called. Fix the behavior and do not call the complete callback on device_terminate_all. Fixes: 808347f6a317 ("dmaengine: at_hdmac: add DMA slave transfers") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-6-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index cb5522417db6..11816484843e 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1437,11 +1437,8 @@ static int atc_terminate_all(struct dma_chan *chan) struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma *atdma = to_at_dma(chan->device); int chan_id = atchan->chan_common.chan_id; - struct at_desc *desc, *_desc; unsigned long flags; - LIST_HEAD(list); - dev_vdbg(chan2dev(chan), "%s\n", __func__); /* @@ -1460,15 +1457,11 @@ static int atc_terminate_all(struct dma_chan *chan) cpu_relax(); /* active_list entries will end up before queued entries */ - list_splice_init(&atchan->queue, &list); - list_splice_init(&atchan->active_list, &list); + list_splice_tail_init(&atchan->queue, &atchan->free_list); + list_splice_tail_init(&atchan->active_list, &atchan->free_list); spin_unlock_irqrestore(&atchan->lock, flags); - /* Flush all pending and queued descriptors */ - list_for_each_entry_safe(desc, _desc, &list, desc_node) - atc_chain_complete(atchan, desc); - clear_bit(ATC_IS_PAUSED, &atchan->status); /* if channel dedicated to cyclic operations, free it */ clear_bit(ATC_IS_CYCLIC, &atchan->status); -- cgit v1.2.3 From 6e5ad28d16f082efeae3d0bd2e31f24bed218019 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:40 +0300 Subject: dmaengine: at_hdmac: Protect atchan->status with the channel lock Now that the complete callback call was removed from device_terminate_all(), we can protect the atchan->status with the channel lock. The atomic bitops on atchan->status do not substitute proper locking on the status, as one could still modify the status after the lock was dropped in atc_terminate_all() but before the atomic bitops were executed. Fixes: 078a6506141a ("dmaengine: at_hdmac: Fix deadlocks") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-7-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 11816484843e..deb4c6027436 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1460,12 +1460,12 @@ static int atc_terminate_all(struct dma_chan *chan) list_splice_tail_init(&atchan->queue, &atchan->free_list); list_splice_tail_init(&atchan->active_list, &atchan->free_list); - spin_unlock_irqrestore(&atchan->lock, flags); - clear_bit(ATC_IS_PAUSED, &atchan->status); /* if channel dedicated to cyclic operations, free it */ clear_bit(ATC_IS_CYCLIC, &atchan->status); + spin_unlock_irqrestore(&atchan->lock, flags); + return 0; } -- cgit v1.2.3 From c6babed879fbe82796a601bf097649e07382db46 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:41 +0300 Subject: dmaengine: at_hdmac: Fix concurrency problems by removing atc_complete_all() atc_complete_all() had concurrency bugs, thus remove it: 1/ atc_complete_all() in its entirety was buggy, as when the atchan->queue list (the one that contains descriptors that are not yet issued to the hardware) contained descriptors, it fired just the first from the atchan->queue, but moved all the desc from atchan->queue to atchan->active_list and considered them all as fired. This could result in calling the completion of a descriptor that was not yet issued to the hardware. 2/ when in tasklet at atc_advance_work() time, atchan->active_list was queried without holding the lock of the chan. This can result in atchan->active_list concurrency problems between the tasklet and issue_pending(). Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-8-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 49 ++++--------------------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index deb4c6027436..f1e6fa6af6c2 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -485,42 +485,6 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) dma_run_dependencies(txd); } -/** - * atc_complete_all - finish work for all transactions - * @atchan: channel to complete transactions for - * - * Eventually submit queued descriptors if any - * - * Assume channel is idle while calling this function - * Called with atchan->lock held and bh disabled - */ -static void atc_complete_all(struct at_dma_chan *atchan) -{ - struct at_desc *desc, *_desc; - LIST_HEAD(list); - unsigned long flags; - - dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n"); - - spin_lock_irqsave(&atchan->lock, flags); - - /* - * Submit queued descriptors ASAP, i.e. before we go through - * the completed ones. - */ - if (!list_empty(&atchan->queue)) - atc_dostart(atchan, atc_first_queued(atchan)); - /* empty active_list now it is completed */ - list_splice_init(&atchan->active_list, &list); - /* empty queue list by moving descriptors (if any) to active_list */ - list_splice_init(&atchan->queue, &atchan->active_list); - - spin_unlock_irqrestore(&atchan->lock, flags); - - list_for_each_entry_safe(desc, _desc, &list, desc_node) - atc_chain_complete(atchan, desc); -} - /** * atc_advance_work - at the end of a transaction, move forward * @atchan: channel where the transaction ended @@ -528,25 +492,20 @@ static void atc_complete_all(struct at_dma_chan *atchan) static void atc_advance_work(struct at_dma_chan *atchan) { unsigned long flags; - int ret; dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n"); spin_lock_irqsave(&atchan->lock, flags); - ret = atc_chan_is_enabled(atchan); + if (atc_chan_is_enabled(atchan) || list_empty(&atchan->active_list)) + return spin_unlock_irqrestore(&atchan->lock, flags); spin_unlock_irqrestore(&atchan->lock, flags); - if (ret) - return; - - if (list_empty(&atchan->active_list) || - list_is_singular(&atchan->active_list)) - return atc_complete_all(atchan); atc_chain_complete(atchan, atc_first_active(atchan)); /* advance work */ spin_lock_irqsave(&atchan->lock, flags); - atc_dostart(atchan, atc_first_active(atchan)); + if (!list_empty(&atchan->active_list)) + atc_dostart(atchan, atc_first_active(atchan)); spin_unlock_irqrestore(&atchan->lock, flags); } -- cgit v1.2.3 From 06988949df8c3007ad82036d3606d8ae72ed9000 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:42 +0300 Subject: dmaengine: at_hdmac: Fix concurrency over descriptor The descriptor was added to the free_list before calling the callback, which could result in reissuing of the same descriptor and calling of a single callback for both. Move the decriptor to the free list after the callback is invoked. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-9-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index f1e6fa6af6c2..2012ecc57826 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -469,11 +469,8 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) desc->memset_buffer = false; } - /* move children to free_list */ - list_splice_init(&desc->tx_list, &atchan->free_list); - /* move myself to free_list */ - list_move(&desc->desc_node, &atchan->free_list); - + /* Remove transfer node from the active list. */ + list_del_init(&desc->desc_node); spin_unlock_irqrestore(&atchan->lock, flags); dma_descriptor_unmap(txd); @@ -483,6 +480,13 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) dmaengine_desc_get_callback_invoke(txd, NULL); dma_run_dependencies(txd); + + spin_lock_irqsave(&atchan->lock, flags); + /* move children to free_list */ + list_splice_init(&desc->tx_list, &atchan->free_list); + /* add myself to free_list */ + list_add(&desc->desc_node, &atchan->free_list); + spin_unlock_irqrestore(&atchan->lock, flags); } /** -- cgit v1.2.3 From 6ba826cbb57d675f447b59323204d1473bbd5593 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:43 +0300 Subject: dmaengine: at_hdmac: Free the memset buf without holding the chan lock There's no need to hold the channel lock when freeing the memset buf, as the operation has already completed. Free the memset buf without holding the channel lock. Fixes: 4d112426c344 ("dmaengine: hdmac: Add memset capabilities") Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-10-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 2012ecc57826..0fb44f622d35 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -462,13 +462,6 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) if (!atc_chan_is_cyclic(atchan)) dma_cookie_complete(txd); - /* If the transfer was a memset, free our temporary buffer */ - if (desc->memset_buffer) { - dma_pool_free(atdma->memset_pool, desc->memset_vaddr, - desc->memset_paddr); - desc->memset_buffer = false; - } - /* Remove transfer node from the active list. */ list_del_init(&desc->desc_node); spin_unlock_irqrestore(&atchan->lock, flags); @@ -487,6 +480,13 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) /* add myself to free_list */ list_add(&desc->desc_node, &atchan->free_list); spin_unlock_irqrestore(&atchan->lock, flags); + + /* If the transfer was a memset, free our temporary buffer */ + if (desc->memset_buffer) { + dma_pool_free(atdma->memset_pool, desc->memset_vaddr, + desc->memset_paddr); + desc->memset_buffer = false; + } } /** -- cgit v1.2.3 From 03ed9ba357cc78116164b90b87f45eacab60b561 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:44 +0300 Subject: dmaengine: at_hdmac: Fix concurrency over the active list The tasklet (atc_advance_work()) did not held the channel lock when retrieving the first active descriptor, causing concurrency problems if issue_pending() was called in between. If issue_pending() was called exactly after the lock was released in the tasklet (atc_advance_work()), atc_chain_complete() could complete a descriptor for which the controller has not yet raised an interrupt. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-11-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 0fb44f622d35..b53a9fc15dd9 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -462,8 +462,6 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) if (!atc_chan_is_cyclic(atchan)) dma_cookie_complete(txd); - /* Remove transfer node from the active list. */ - list_del_init(&desc->desc_node); spin_unlock_irqrestore(&atchan->lock, flags); dma_descriptor_unmap(txd); @@ -495,6 +493,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) */ static void atc_advance_work(struct at_dma_chan *atchan) { + struct at_desc *desc; unsigned long flags; dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n"); @@ -502,9 +501,12 @@ static void atc_advance_work(struct at_dma_chan *atchan) spin_lock_irqsave(&atchan->lock, flags); if (atc_chan_is_enabled(atchan) || list_empty(&atchan->active_list)) return spin_unlock_irqrestore(&atchan->lock, flags); - spin_unlock_irqrestore(&atchan->lock, flags); - atc_chain_complete(atchan, atc_first_active(atchan)); + desc = atc_first_active(atchan); + /* Remove the transfer node from the active list. */ + list_del_init(&desc->desc_node); + spin_unlock_irqrestore(&atchan->lock, flags); + atc_chain_complete(atchan, desc); /* advance work */ spin_lock_irqsave(&atchan->lock, flags); -- cgit v1.2.3 From ba2423633ba646e1df20e30cb3cf35495c16f173 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:45 +0300 Subject: dmaengine: at_hdmac: Fix descriptor handling when issuing it to hardware As it was before, the descriptor was issued to the hardware without adding it to the active (issued) list. This could result in a completion of other descriptor, or/and in the descriptor never being completed. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-12-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index b53a9fc15dd9..9e5a30396c1c 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -510,8 +510,11 @@ static void atc_advance_work(struct at_dma_chan *atchan) /* advance work */ spin_lock_irqsave(&atchan->lock, flags); - if (!list_empty(&atchan->active_list)) - atc_dostart(atchan, atc_first_active(atchan)); + if (!list_empty(&atchan->active_list)) { + desc = atc_first_queued(atchan); + list_move_tail(&desc->desc_node, &atchan->active_list); + atc_dostart(atchan, desc); + } spin_unlock_irqrestore(&atchan->lock, flags); } @@ -523,6 +526,7 @@ static void atc_advance_work(struct at_dma_chan *atchan) static void atc_handle_error(struct at_dma_chan *atchan) { struct at_desc *bad_desc; + struct at_desc *desc; struct at_desc *child; unsigned long flags; @@ -540,8 +544,11 @@ static void atc_handle_error(struct at_dma_chan *atchan) list_splice_init(&atchan->queue, atchan->active_list.prev); /* Try to restart the controller */ - if (!list_empty(&atchan->active_list)) - atc_dostart(atchan, atc_first_active(atchan)); + if (!list_empty(&atchan->active_list)) { + desc = atc_first_queued(atchan); + list_move_tail(&desc->desc_node, &atchan->active_list); + atc_dostart(atchan, desc); + } /* * KERN_CRITICAL may seem harsh, but since this only happens -- cgit v1.2.3 From ef2cb4f0ce479f77607b04c4b0414bf32f863ee8 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:46 +0300 Subject: dmaengine: at_hdmac: Fix completion of unissued descriptor in case of errors In case the controller detected an error, the code took the chance to move all the queued (submitted) descriptors to the active (issued) list. This was wrong as if there were any descriptors in the submitted list they were moved to the issued list without actually issuing them to the controller, thus a completion could be raised without even fireing the descriptor. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-13-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 9e5a30396c1c..80eeb4fb88ef 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -539,10 +539,6 @@ static void atc_handle_error(struct at_dma_chan *atchan) bad_desc = atc_first_active(atchan); list_del_init(&bad_desc->desc_node); - /* As we are stopped, take advantage to push queued descriptors - * in active_list */ - list_splice_init(&atchan->queue, atchan->active_list.prev); - /* Try to restart the controller */ if (!list_empty(&atchan->active_list)) { desc = atc_first_queued(atchan); -- cgit v1.2.3 From 580ee84405c27d6ed419abe4d2b3de1968abdafd Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:47 +0300 Subject: dmaengine: at_hdmac: Don't allow CPU to reorder channel enable at_hdmac uses __raw_writel for register writes. In the absence of a barrier, the CPU may reorder the register operations. Introduce a write memory barrier so that the CPU does not reorder the channel enable, thus the start of the transfer, without making sure that all the pre-required register fields are already written. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Reported-by: Peter Rosin Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/ Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-14-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 80eeb4fb88ef..968a5aba47cd 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -256,6 +256,8 @@ static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first) ATC_SPIP_BOUNDARY(first->boundary)); channel_writel(atchan, DPIP, ATC_DPIP_HOLE(first->dst_hole) | ATC_DPIP_BOUNDARY(first->boundary)); + /* Don't allow CPU to reorder channel enable. */ + wmb(); dma_writel(atdma, CHER, atchan->mask); vdbg_dump_regs(atchan); -- cgit v1.2.3 From 28cbe5a0a46a6637adbda52337d7b2777fc04027 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:48 +0300 Subject: dmaengine: at_hdmac: Fix impossible condition The iterator can not be greater than ATC_MAX_DSCR_TRIALS, as the for loop will stop when i == ATC_MAX_DSCR_TRIALS. While here, use the common "i" name for the iterator. Fixes: 93dce3a6434f ("dmaengine: at_hdmac: fix residue computation") Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-15-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 968a5aba47cd..afcbad3e1718 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -318,7 +318,8 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie) struct at_desc *desc_first = atc_first_active(atchan); struct at_desc *desc; int ret; - u32 ctrla, dscr, trials; + u32 ctrla, dscr; + unsigned int i; /* * If the cookie doesn't match to the currently running transfer then @@ -388,7 +389,7 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie) dscr = channel_readl(atchan, DSCR); rmb(); /* ensure DSCR is read before CTRLA */ ctrla = channel_readl(atchan, CTRLA); - for (trials = 0; trials < ATC_MAX_DSCR_TRIALS; ++trials) { + for (i = 0; i < ATC_MAX_DSCR_TRIALS; ++i) { u32 new_dscr; rmb(); /* ensure DSCR is read after CTRLA */ @@ -414,7 +415,7 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie) rmb(); /* ensure DSCR is read before CTRLA */ ctrla = channel_readl(atchan, CTRLA); } - if (unlikely(trials >= ATC_MAX_DSCR_TRIALS)) + if (unlikely(i == ATC_MAX_DSCR_TRIALS)) return -ETIMEDOUT; /* for the first descriptor we can be more accurate */ -- cgit v1.2.3 From c47e6403fa099f200868d6b106701cb42d181d2b Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Tue, 25 Oct 2022 12:02:49 +0300 Subject: dmaengine: at_hdmac: Check return code of dma_async_device_register dma_async_device_register() can fail, check the return code and display an error. Fixes: dc78baa2b90b ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller") Signed-off-by: Tudor Ambarus Cc: stable@vger.kernel.org Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20221025090306.297886-16-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index afcbad3e1718..858bd64f1313 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1928,7 +1928,11 @@ static int __init at_dma_probe(struct platform_device *pdev) dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "", plat_dat->nr_channels); - dma_async_device_register(&atdma->dma_common); + err = dma_async_device_register(&atdma->dma_common); + if (err) { + dev_err(&pdev->dev, "Unable to register: %d.\n", err); + goto err_dma_async_device_register; + } /* * Do not return an error if the dmac node is not present in order to @@ -1948,6 +1952,7 @@ static int __init at_dma_probe(struct platform_device *pdev) err_of_dma_controller_register: dma_async_device_unregister(&atdma->dma_common); +err_dma_async_device_register: dma_pool_destroy(atdma->memset_pool); err_memset_pool_create: dma_pool_destroy(atdma->dma_desc_pool); -- cgit v1.2.3 From ea045fd344cb15c164e9ffc8b8cffb6883df8475 Mon Sep 17 00:00:00 2001 From: Shin'ichiro Kawasaki Date: Mon, 7 Nov 2022 13:02:29 +0900 Subject: ata: libata-scsi: fix SYNCHRONIZE CACHE (16) command failure SAT SCSI/ATA Translation specification requires SCSI SYNCHRONIZE CACHE (10) and (16) commands both shall be translated to ATA flush command. Also, ZBC Zoned Block Commands specification mandates SYNCHRONIZE CACHE (16) command support. However, libata translates only SYNCHRONIZE CACHE (10). This results in SYNCHRONIZE CACHE (16) command failures on SATA drives and then libata translation does not conform to ZBC. To avoid the failure, add support for SYNCHRONIZE CACHE (16). Signed-off-by: Shin'ichiro Kawasaki Cc: stable@vger.kernel.org Reviewed-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Signed-off-by: Damien Le Moal --- drivers/ata/libata-scsi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index e2ebb0b065e2..61cd4e90e4e7 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3264,6 +3264,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) case REPORT_LUNS: case REQUEST_SENSE: case SYNCHRONIZE_CACHE: + case SYNCHRONIZE_CACHE_16: case REZERO_UNIT: case SEEK_6: case SEEK_10: @@ -3922,6 +3923,7 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) return ata_scsi_write_same_xlat; case SYNCHRONIZE_CACHE: + case SYNCHRONIZE_CACHE_16: if (ata_try_flush_cache(dev)) return ata_scsi_flush_xlat; break; @@ -4145,6 +4147,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) * turning this into a no-op. */ case SYNCHRONIZE_CACHE: + case SYNCHRONIZE_CACHE_16: fallthrough; /* no-op's, complete with success */ -- cgit v1.2.3 From 28adfe402909dd8bca741c72619eae6f52364987 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:59 +0200 Subject: drm/i915/gvt: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20220521111145.81697-49-Julia.Lawall@inria.fr Acked-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index b4f69364f9a1..ce0eb03709c3 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -2341,7 +2341,7 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, gvt_vgpu_err("fail to populate guest ggtt entry\n"); /* guest driver may read/write the entry when partial * update the entry in this situation p2m will fail - * settting the shadow entry to point to a scratch page + * setting the shadow entry to point to a scratch page */ ops->set_pfn(&m, gvt->gtt.scratch_mfn); } else -- cgit v1.2.3 From 63ba856bf1e3627fd2c86cc6e7229d92dd3e887e Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Tue, 24 May 2022 16:37:33 +0800 Subject: drm/i915/gvt: Fix kernel-doc Fix the following W=1 kernel warnings: drivers/gpu/drm/i915/gvt/handlers.c:3066: warning: expecting prototype for intel_t_default_mmio_write(). Prototype was for intel_vgpu_default_mmio_write() instead. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20220524083733.67148-2-jiapeng.chong@linux.alibaba.com Acked-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index e7e33f95cc51..c1490b657c14 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -3052,7 +3052,7 @@ int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, } /** - * intel_t_default_mmio_write - default MMIO write handler + * intel_vgpu_default_mmio_write() - default MMIO write handler * @vgpu: a vGPU * @offset: access offset * @p_data: write data buffer -- cgit v1.2.3 From 400c0563bf2a9328eda5c4d67b3369100364c5c8 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Tue, 24 May 2022 16:37:32 +0800 Subject: drm/i915/gvt: Fix kernel-doc Fix the following W=1 kernel warnings: drivers/gpu/drm/i915/gvt/mmio_context.c:560: warning: expecting prototype for intel_gvt_switch_render_mmio(). Prototype was for intel_gvt_switch_mmio() instead. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20220524083733.67148-1-jiapeng.chong@linux.alibaba.com Acked-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/mmio_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index c85bafe7539e..1c6e941c9666 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c @@ -546,7 +546,7 @@ static void switch_mmio(struct intel_vgpu *pre, } /** - * intel_gvt_switch_render_mmio - switch mmio context of specific engine + * intel_gvt_switch_mmio - switch mmio context of specific engine * @pre: the last vGPU that own the engine * @next: the vGPU to switch to * @engine: the engine -- cgit v1.2.3 From 63dfc0c0fd48c371fa7b0ce718cf0d02f572f404 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Thu, 2 Jun 2022 15:35:19 +0800 Subject: drm/i915/gvt: Fix kernel-doc Fix the following W=1 kernel warnings: drivers/gpu/drm/i915/gvt/aperture_gm.c:308: warning: expecting prototype for inte_gvt_free_vgpu_resource(). Prototype was for intel_vgpu_free_resource() instead. drivers/gpu/drm/i915/gvt/aperture_gm.c:344: warning: expecting prototype for intel_alloc_vgpu_resource(). Prototype was for intel_vgpu_alloc_resource() instead. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20220602073519.22363-1-jiapeng.chong@linux.alibaba.com Acked-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/aperture_gm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index 557f3314291a..3b81a6d35a7b 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -298,7 +298,7 @@ no_enough_resource: } /** - * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU + * intel_vgpu_free_resource() - free HW resource owned by a vGPU * @vgpu: a vGPU * * This function is used to free the HW resource owned by a vGPU. @@ -328,7 +328,7 @@ void intel_vgpu_reset_resource(struct intel_vgpu *vgpu) } /** - * intel_alloc_vgpu_resource - allocate HW resource for a vGPU + * intel_vgpu_alloc_resource() - allocate HW resource for a vGPU * @vgpu: vGPU * @param: vGPU creation params * -- cgit v1.2.3 From 38e0d3fd1ee170ba95f908e1606fbb8763a98593 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 7 Nov 2022 16:04:54 +0200 Subject: drm/i915/pxp: use <> instead of "" for headers in include/ Headers in include/ should be included using the system header #include syntax. Fixes: 887a193b4fb1 ("drm/i915/pxp: add huc authentication and loading command") Cc: Tomas Winkler Cc: Vitaly Lubart Cc: Daniele Ceraolo Spurio Cc: Alan Previn Signed-off-by: Jani Nikula Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20221107140454.2680954-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/pxp/intel_pxp_huc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c index 7ec36d94e758..f6a3f53a1d22 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c @@ -3,7 +3,8 @@ * Copyright(c) 2021-2022, Intel Corporation. All rights reserved. */ -#include "drm/i915_drm.h" +#include + #include "i915_drv.h" #include "gem/i915_gem_region.h" -- cgit v1.2.3 From 308451d9c7fece33d9551230cb8e5eb7f3914988 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 19 Sep 2022 15:32:58 +0200 Subject: drm: panel-orientation-quirks: Add quirk for Nanote UMPC-01 The Nanote UMPC-01 is a mini laptop with a 1200x1920 portrait screen mounted in a landscape oriented clamshell case. Add a quirk for this. Signed-off-by: Hans de Goede Acked-by: Simon Ser Link: https://patchwork.freedesktop.org/patch/msgid/20220919133258.711639-1-hdegoede@redhat.com --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 8a0c0e0bb5bd..f0f6fa306521 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -319,6 +319,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"), }, .driver_data = (void *)&lcd1200x1920_rightside_up, + }, { /* Nanote UMPC-01 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "RWC CO.,LTD"), + DMI_MATCH(DMI_PRODUCT_NAME, "UMPC-01"), + }, + .driver_data = (void *)&lcd1200x1920_rightside_up, }, { /* OneGX1 Pro */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"), -- cgit v1.2.3 From 653f2d94fcda200b02bd79cea2e0307b26c1b747 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 6 Nov 2022 22:50:52 +0100 Subject: drm: panel-orientation-quirks: Add quirk for Acer Switch V 10 (SW5-017) Like the Acer Switch One 10 S1003, for which there already is a quirk, the Acer Switch V 10 (SW5-017) has a 800x1280 portrait screen mounted in the tablet part of a landscape oriented 2-in-1. Add a quirk for this. Cc: Rudolf Polzer Signed-off-by: Hans de Goede Acked-by: Simon Ser Link: https://patchwork.freedesktop.org/patch/msgid/20221106215052.66995-1-hdegoede@redhat.com --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index f0f6fa306521..52d8800a8ab8 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -134,6 +134,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"), }, .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* Acer Switch V 10 (SW5-017) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, }, { /* Anbernic Win600 */ .matches = { DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Anbernic"), -- cgit v1.2.3 From 625b74460ec0978979f883fbee117e1b97e6e35e Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Mon, 7 Nov 2022 16:54:13 +0000 Subject: drm/i915/ttm: fix uaf with lmem_userfault_list handling In the fault handler, make sure we check if the BO maps lmem after we schedule the migration, since the current resource might change from lmem to smem, if the pages are in the non-cpu visible portion of lmem. This then leads to adding the object to the lmem_userfault_list even though the current resource is no longer lmem. If we then destroy the object, the list might still contain a link to the now free object, since we only remove it if the object is still in lmem. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/7469 Fixes: ad74457a6b5a ("drm/i915/dgfx: Release mmap on rpm suspend") Signed-off-by: Matthew Auld Cc: Anshuman Gupta Cc: Rodrigo Vivi Cc: Andrzej Hajda Cc: Nirmoy Das Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/20221107165414.56970-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 25129af70f70..9421dc4dc98f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -1048,9 +1048,6 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf) return VM_FAULT_SIGBUS; } - if (i915_ttm_cpu_maps_iomem(bo->resource)) - wakeref = intel_runtime_pm_get(&to_i915(obj->base.dev)->runtime_pm); - if (!i915_ttm_resource_mappable(bo->resource)) { int err = -ENODEV; int i; @@ -1078,6 +1075,9 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf) } } + if (i915_ttm_cpu_maps_iomem(bo->resource)) + wakeref = intel_runtime_pm_get(&to_i915(obj->base.dev)->runtime_pm); + if (drm_dev_enter(dev, &idx)) { ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, TTM_BO_VM_NUM_PREFAULT); -- cgit v1.2.3 From ccb0e02787d0f80d0081c446aec3756dd8f7bfe0 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Mon, 7 Nov 2022 16:54:14 +0000 Subject: drm/i915/ttm: add some sanity checks for lmem_userfault_list Rather than getting some hard to debug uaf, add some warns to hopefully catch issues with userfault_count being non-zero when destroying the object. Also if we somehow add an object to lmem_userfault_list that somehow doesn't map lmem. References: https://gitlab.freedesktop.org/drm/intel/-/issues/7469 Signed-off-by: Matthew Auld Cc: Anshuman Gupta Cc: Rodrigo Vivi Cc: Andrzej Hajda Cc: Nirmoy Das Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/20221107165414.56970-2-matthew.auld@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 9421dc4dc98f..2c8b2d5ae903 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -1098,6 +1098,8 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf) spin_lock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock); list_add(&obj->userfault_link, &to_i915(obj->base.dev)->runtime_pm.lmem_userfault_list); spin_unlock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock); + + GEM_WARN_ON(!i915_ttm_cpu_maps_iomem(bo->resource)); } if (wakeref & CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND) @@ -1180,6 +1182,8 @@ static void i915_ttm_unmap_virtual(struct drm_i915_gem_object *obj) } } + GEM_WARN_ON(obj->userfault_count); + ttm_bo_unmap_virtual(i915_gem_to_ttm(obj)); if (wakeref) -- cgit v1.2.3 From 3faf7e14ec0c3462c2d747fa6793b8645d1391df Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Nov 2022 09:14:45 +0800 Subject: net: lapbether: fix issue of invalid opcode in lapbeth_open() If lapb_register() failed when lapb device goes to up for the first time, the NAPI is not disabled. As a result, the invalid opcode issue is reported when the lapb device goes to up for the second time. The stack info is as follows: [ 1958.311422][T11356] kernel BUG at net/core/dev.c:6442! [ 1958.312206][T11356] invalid opcode: 0000 [#1] PREEMPT SMP KASAN [ 1958.315979][T11356] RIP: 0010:napi_enable+0x16a/0x1f0 [ 1958.332310][T11356] Call Trace: [ 1958.332817][T11356] [ 1958.336135][T11356] lapbeth_open+0x18/0x90 [ 1958.337446][T11356] __dev_open+0x258/0x490 [ 1958.341672][T11356] __dev_change_flags+0x4d4/0x6a0 [ 1958.345325][T11356] dev_change_flags+0x93/0x160 [ 1958.346027][T11356] devinet_ioctl+0x1276/0x1bf0 [ 1958.346738][T11356] inet_ioctl+0x1c8/0x2d0 [ 1958.349638][T11356] sock_ioctl+0x5d1/0x750 [ 1958.356059][T11356] __x64_sys_ioctl+0x3ec/0x1790 [ 1958.365594][T11356] do_syscall_64+0x35/0x80 [ 1958.366239][T11356] entry_SYSCALL_64_after_hwframe+0x46/0xb0 [ 1958.377381][T11356] Fixes: 514e1150da9c ("net: x25: Queue received packets in the drivers instead of per-CPU queues") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221107011445.207372-1-shaozhengchao@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/wan/lapbether.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index cb360dca3250..d62a904d2e42 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -325,6 +325,7 @@ static int lapbeth_open(struct net_device *dev) err = lapb_register(dev, &lapbeth_callbacks); if (err != LAPB_OK) { + napi_disable(&lapbeth->napi); pr_err("lapb_register error: %d\n", err); return -ENODEV; } -- cgit v1.2.3 From b0c09c7f08c2467b2089bdf4adb2fbbc2464f4a8 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Nov 2022 09:21:59 +0800 Subject: net: ethernet: mtk-star-emac: disable napi when connect and start PHY failed in mtk_star_enable() When failed to connect to and start PHY in mtk_star_enable() for opening device, napi isn't disabled. When open mtk star device next time, it will reports a invalid opcode issue. Fix it. Only be compiled, not be tested. Fixes: 8c7bd5a454ff ("net: ethernet: mtk-star-emac: new driver") Signed-off-by: Zhengchao Shao Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20221107012159.211387-1-shaozhengchao@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mediatek/mtk_star_emac.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mediatek/mtk_star_emac.c b/drivers/net/ethernet/mediatek/mtk_star_emac.c index 7e890f81148e..7050351250b7 100644 --- a/drivers/net/ethernet/mediatek/mtk_star_emac.c +++ b/drivers/net/ethernet/mediatek/mtk_star_emac.c @@ -1026,6 +1026,8 @@ static int mtk_star_enable(struct net_device *ndev) return 0; err_free_irq: + napi_disable(&priv->rx_napi); + napi_disable(&priv->tx_napi); free_irq(ndev->irq, ndev); err_free_skbs: mtk_star_free_rx_skbs(priv); -- cgit v1.2.3 From f0dfc4c88ef39be0ba736aa0ce6119263fc19aeb Mon Sep 17 00:00:00 2001 From: Ratheesh Kannoth Date: Mon, 7 Nov 2022 09:05:05 +0530 Subject: octeontx2-pf: Fix SQE threshold checking Current way of checking available SQE count which is based on HW updated SQB count could result in driver submitting an SQE even before CQE for the previously transmitted SQE at the same index is processed in NAPI resulting losing SKB pointers, hence a leak. Fix this by checking a consumer index which is updated once CQE is processed. Fixes: 3ca6c4c882a7 ("octeontx2-pf: Add packet transmission support") Signed-off-by: Ratheesh Kannoth Reviewed-by: Sunil Kovvuri Goutham Link: https://lore.kernel.org/r/20221107033505.2491464-1-rkannoth@marvell.com Signed-off-by: Paolo Abeni --- .../ethernet/marvell/octeontx2/nic/otx2_common.c | 1 + .../net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 32 +++++++++++++--------- .../net/ethernet/marvell/octeontx2/nic/otx2_txrx.h | 1 + 3 files changed, 21 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 9ac9e6615ae7..9e10e7471b88 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -898,6 +898,7 @@ static int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) } sq->head = 0; + sq->cons_head = 0; sq->sqe_per_sqb = (pfvf->hw.sqb_size / sq->sqe_size) - 1; sq->num_sqbs = (qset->sqe_cnt + sq->sqe_per_sqb) / sq->sqe_per_sqb; /* Set SQE threshold to 10% of total SQEs */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c index 5ec11d71bf60..ef10aef3cda0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c @@ -441,6 +441,7 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int budget) { int tx_pkts = 0, tx_bytes = 0, qidx; + struct otx2_snd_queue *sq; struct nix_cqe_tx_s *cqe; int processed_cqe = 0; @@ -451,6 +452,9 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf, return 0; process_cqe: + qidx = cq->cq_idx - pfvf->hw.rx_queues; + sq = &pfvf->qset.sq[qidx]; + while (likely(processed_cqe < budget) && cq->pend_cqe) { cqe = (struct nix_cqe_tx_s *)otx2_get_next_cqe(cq); if (unlikely(!cqe)) { @@ -458,18 +462,20 @@ process_cqe: return 0; break; } + if (cq->cq_type == CQ_XDP) { - qidx = cq->cq_idx - pfvf->hw.rx_queues; - otx2_xdp_snd_pkt_handler(pfvf, &pfvf->qset.sq[qidx], - cqe); + otx2_xdp_snd_pkt_handler(pfvf, sq, cqe); } else { - otx2_snd_pkt_handler(pfvf, cq, - &pfvf->qset.sq[cq->cint_idx], - cqe, budget, &tx_pkts, &tx_bytes); + otx2_snd_pkt_handler(pfvf, cq, sq, cqe, budget, + &tx_pkts, &tx_bytes); } + cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID; processed_cqe++; cq->pend_cqe--; + + sq->cons_head++; + sq->cons_head &= (sq->sqe_cnt - 1); } /* Free CQEs to HW */ @@ -1072,17 +1078,17 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq, { struct netdev_queue *txq = netdev_get_tx_queue(netdev, qidx); struct otx2_nic *pfvf = netdev_priv(netdev); - int offset, num_segs, free_sqe; + int offset, num_segs, free_desc; struct nix_sqe_hdr_s *sqe_hdr; - /* Check if there is room for new SQE. - * 'Num of SQBs freed to SQ's pool - SQ's Aura count' - * will give free SQE count. + /* Check if there is enough room between producer + * and consumer index. */ - free_sqe = (sq->num_sqbs - *sq->aura_fc_addr) * sq->sqe_per_sqb; + free_desc = (sq->cons_head - sq->head - 1 + sq->sqe_cnt) & (sq->sqe_cnt - 1); + if (free_desc < sq->sqe_thresh) + return false; - if (free_sqe < sq->sqe_thresh || - free_sqe < otx2_get_sqe_count(pfvf, skb)) + if (free_desc < otx2_get_sqe_count(pfvf, skb)) return false; num_segs = skb_shinfo(skb)->nr_frags + 1; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h index fbe62bbfb789..93cac2c2664c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h @@ -79,6 +79,7 @@ struct sg_list { struct otx2_snd_queue { u8 aura_id; u16 head; + u16 cons_head; u16 sqe_size; u32 sqe_cnt; u16 num_sqbs; -- cgit v1.2.3 From e0b26b9482461e9528552f54fa662c2269f75b3f Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Wed, 14 Sep 2022 20:53:31 +0800 Subject: drm/amdgpu: Fix the lpfn checking condition in drm buddy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because the value of man->size is changed during suspend/resume process, use mgr->mm.size instead of man->size here for lpfn checking. Signed-off-by: Ma Jun Suggested-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20220914125331.2467162-1-Jun.Ma2@amd.com Signed-off-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 73a517bcf5c1..80dd1343594c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -435,7 +435,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, if (place->flags & TTM_PL_FLAG_TOPDOWN) vres->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION; - if (fpfn || lpfn != man->size) + if (fpfn || lpfn != mgr->mm.size) /* Allocate blocks in desired range */ vres->flags |= DRM_BUDDY_RANGE_ALLOCATION; -- cgit v1.2.3 From f04a2862f9c3f64962b8709c75d788efba6df26b Mon Sep 17 00:00:00 2001 From: Anjana Hari Date: Thu, 3 Nov 2022 11:10:51 -0700 Subject: pinctrl: qcom: sc8280xp: Rectify UFS reset pins UFS reset pin offsets are wrongly configured for SC8280XP, correcting the same for both UFS instances here. Signed-off-by: Anjana Hari Signed-off-by: Bjorn Andersson Reviewed-by: Andrew Halaney Tested-by: Andrew Halaney # QDrive3 Link: https://lore.kernel.org/r/20221103181051.26912-1-quic_bjorande@quicinc.com Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-sc8280xp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c index aa2075390f3e..e96c00686a25 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c @@ -1873,8 +1873,8 @@ static const struct msm_pingroup sc8280xp_groups[] = { [225] = PINGROUP(225, hs3_mi2s, phase_flag, _, _, _, _, egpio), [226] = PINGROUP(226, hs3_mi2s, phase_flag, _, _, _, _, egpio), [227] = PINGROUP(227, hs3_mi2s, phase_flag, _, _, _, _, egpio), - [228] = UFS_RESET(ufs_reset, 0xf1004), - [229] = UFS_RESET(ufs1_reset, 0xf3004), + [228] = UFS_RESET(ufs_reset, 0xf1000), + [229] = UFS_RESET(ufs1_reset, 0xf3000), [230] = SDC_QDSD_PINGROUP(sdc2_clk, 0xe8000, 14, 6), [231] = SDC_QDSD_PINGROUP(sdc2_cmd, 0xe8000, 11, 3), [232] = SDC_QDSD_PINGROUP(sdc2_data, 0xe8000, 9, 0), -- cgit v1.2.3 From ce9e57feeed81d17d5e80ed86f516ff0d39c3867 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Nov 2022 12:30:32 +0800 Subject: drivers: net: xgene: disable napi when register irq failed in xgene_enet_open() When failed to register irq in xgene_enet_open() for opening device, napi isn't disabled. When open xgene device next time, it will reports a invalid opcode issue. Fix it. Only be compiled, not be tested. Fixes: aeb20b6b3f4e ("drivers: net: xgene: fix: ifconfig up/down crash") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221107043032.357673-1-shaozhengchao@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index d6cfea65a714..390671640388 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1004,8 +1004,10 @@ static int xgene_enet_open(struct net_device *ndev) xgene_enet_napi_enable(pdata); ret = xgene_enet_register_irq(ndev); - if (ret) + if (ret) { + xgene_enet_napi_disable(pdata); return ret; + } if (ndev->phydev) { phy_start(ndev->phydev); -- cgit v1.2.3 From cd136706b4f925aa5d316642543babac90d45910 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 7 Nov 2022 10:07:53 +0100 Subject: USB: bcma: Make GPIO explicitly optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What the code does is to not check the return value from devm_gpiod_get() and then avoid using an erroneous GPIO descriptor with IS_ERR_OR_NULL(). This will miss real errors from the GPIO core that should not be ignored, such as probe deferral. Instead request the GPIO as explicitly optional, which means that if it doesn't exist, the descriptor returned will be NULL. Then we can add error handling and also avoid just doing this on the device tree path, and simplify the site where the optional GPIO descriptor is used. There were some problems with cleaning up this GPIO descriptor use in the past, but this is the proper way to deal with it. Cc: Rafał Miłecki Cc: Chuhong Yuan Signed-off-by: Linus Walleij Cc: stable Link: https://lore.kernel.org/r/20221107090753.1404679-1-linus.walleij@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/bcma-hcd.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 2df52f75f6b3..7558cc4d90cc 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -285,7 +285,7 @@ static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) { struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); - if (IS_ERR_OR_NULL(usb_dev->gpio_desc)) + if (!usb_dev->gpio_desc) return; gpiod_set_value(usb_dev->gpio_desc, val); @@ -406,9 +406,11 @@ static int bcma_hcd_probe(struct bcma_device *core) return -ENOMEM; usb_dev->core = core; - if (core->dev.of_node) - usb_dev->gpio_desc = devm_gpiod_get(&core->dev, "vcc", - GPIOD_OUT_HIGH); + usb_dev->gpio_desc = devm_gpiod_get_optional(&core->dev, "vcc", + GPIOD_OUT_HIGH); + if (IS_ERR(usb_dev->gpio_desc)) + return dev_err_probe(&core->dev, PTR_ERR(usb_dev->gpio_desc), + "error obtaining VCC GPIO"); switch (core->id.id) { case BCMA_CORE_USB20_HOST: -- cgit v1.2.3 From ffb9da4a04c69567bad717707b6fdfbc4c216ef4 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Mon, 7 Nov 2022 18:45:44 -0800 Subject: usb: dwc3: gadget: Return -ESHUTDOWN on ep disable The usb_request API clearly noted that removed requests due to disabled endpoint should have -ESHUTDOWN status returned. Don't change this behavior. Fixes: b44c0e7fef51 ("usb: dwc3: gadget: conditionally remove requests") Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/3421859485cb32d77e2068549679a6c07a7797bc.1667875427.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5fe2d136dff5..026d4029bda6 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1029,7 +1029,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->endpoint.desc = NULL; } - dwc3_remove_requests(dwc, dep, -ECONNRESET); + dwc3_remove_requests(dwc, dep, -ESHUTDOWN); dep->stream_capable = false; dep->type = 0; -- cgit v1.2.3 From 5c294de36e7fb3e0cba0c4e1ef9a5f57bc080d0f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Nov 2022 15:46:48 +0100 Subject: Revert "usb: dwc3: disable USB core PHY management" This reverts commit 6000b8d900cd5f52fbcd0776d0cc396e88c8c2ea. The offending commit disabled the USB core PHY management as the dwc3 already manages the PHYs in question. Unfortunately some platforms have started relying on having USB core also controlling the PHY and this is specifically currently needed on some Exynos platforms for PHY calibration or connected device may fail to enumerate. The PHY calibration was previously handled in the dwc3 driver, but to work around some issues related to how the dwc3 driver interacts with xhci (e.g. using multiple drivers) this was moved to USB core by commits 34c7ed72f4f0 ("usb: core: phy: add support for PHY calibration") and a0a465569b45 ("usb: dwc3: remove generic PHY calibrate() calls"). The same PHY obviously should not be controlled from two different places, which for example do no agree on the PHY mode or power state during suspend, but as the offending patch was backported to stable, let's revert it for now. Reported-by: Stefan Agner Link: https://lore.kernel.org/lkml/808bdba846bb60456adf10a3016911ee@agner.ch/ Fixes: 6000b8d900cd ("usb: dwc3: disable USB core PHY management") Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Tested-by: Marek Szyprowski Acked-by: Thinh Nguyen Link: https://lore.kernel.org/r/20221103144648.14197-1-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/host.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index a7154fe8206d..f6f13e7f1ba1 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -11,13 +11,8 @@ #include #include -#include "../host/xhci-plat.h" #include "core.h" -static const struct xhci_plat_priv dwc3_xhci_plat_priv = { - .quirks = XHCI_SKIP_PHY_INIT, -}; - static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc, int irq, char *name) { @@ -97,11 +92,6 @@ int dwc3_host_init(struct dwc3 *dwc) goto err; } - ret = platform_device_add_data(xhci, &dwc3_xhci_plat_priv, - sizeof(dwc3_xhci_plat_priv)); - if (ret) - goto err; - memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); if (dwc->usb3_lpm_capable) -- cgit v1.2.3 From 341fd15e2e18c24d5c738496cfc3d7a272241201 Mon Sep 17 00:00:00 2001 From: Yassine Oudjana Date: Mon, 7 Nov 2022 18:33:17 +0300 Subject: extcon: usbc-tusb320: Call the Type-C IRQ handler only if a port is registered Commit bf7571c00dca ("extcon: usbc-tusb320: Add USB TYPE-C support") added an optional Type-C interface to the driver but missed to check if it is in use when calling the IRQ handler. This causes an oops on devices currently using the old extcon interface. Check if a Type-C port is registered before calling the Type-C IRQ handler. Fixes: bf7571c00dca ("extcon: usbc-tusb320: Add USB TYPE-C support") Signed-off-by: Yassine Oudjana Reviewed-by: Marek Vasut Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20221107153317.657803-1-y.oudjana@protonmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/extcon/extcon-usbc-tusb320.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c index 41041ff0fadb..2a120d8d3c27 100644 --- a/drivers/extcon/extcon-usbc-tusb320.c +++ b/drivers/extcon/extcon-usbc-tusb320.c @@ -327,7 +327,13 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) return IRQ_NONE; tusb320_extcon_irq_handler(priv, reg); - tusb320_typec_irq_handler(priv, reg); + + /* + * Type-C support is optional. Only call the Type-C handler if a + * port had been registered previously. + */ + if (priv->port) + tusb320_typec_irq_handler(priv, reg); regmap_write(priv->regmap, TUSB320_REG9, reg); -- cgit v1.2.3 From 40bf8f162d0f95e0716e479d7db41443d931765c Mon Sep 17 00:00:00 2001 From: Rajat Khandelwal Date: Mon, 24 Oct 2022 22:46:11 +0530 Subject: usb: typec: mux: Enter safe mode only when pins need to be reconfigured There is no point to enter safe mode during DP/TBT configuration if the DP/TBT was already configured in mux. This is because safe mode is only applicable when there is a need to reconfigure the pins in order to avoid damage within/to port partner. In some chrome systems, IOM/mux is already configured before OS comes up. Thus, when driver is probed, it blindly enters safe mode due to PD negotiations but only after gfx driver lowers dp_phy_ownership, will the IOM complete safe mode and send an ack to PMC. Since, that never happens, we see IPC timeout. Hence, allow safe mode only when pin reconfiguration is not required, which makes sense. Fixes: 43d596e32276 ("usb: typec: intel_pmc_mux: Check the port status before connect") Cc: stable Signed-off-by: Rajat Khandelwal Signed-off-by: Lee Shawn C Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20221024171611.181468-1-rajat.khandelwal@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/mux/intel_pmc_mux.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c index e1f4df7238bf..fdbf3694e21f 100644 --- a/drivers/usb/typec/mux/intel_pmc_mux.c +++ b/drivers/usb/typec/mux/intel_pmc_mux.c @@ -369,13 +369,24 @@ pmc_usb_mux_usb4(struct pmc_usb_port *port, struct typec_mux_state *state) return pmc_usb_command(port, (void *)&req, sizeof(req)); } -static int pmc_usb_mux_safe_state(struct pmc_usb_port *port) +static int pmc_usb_mux_safe_state(struct pmc_usb_port *port, + struct typec_mux_state *state) { u8 msg; if (IOM_PORT_ACTIVITY_IS(port->iom_status, SAFE_MODE)) return 0; + if ((IOM_PORT_ACTIVITY_IS(port->iom_status, DP) || + IOM_PORT_ACTIVITY_IS(port->iom_status, DP_MFD)) && + state->alt && state->alt->svid == USB_TYPEC_DP_SID) + return 0; + + if ((IOM_PORT_ACTIVITY_IS(port->iom_status, TBT) || + IOM_PORT_ACTIVITY_IS(port->iom_status, ALT_MODE_TBT_USB)) && + state->alt && state->alt->svid == USB_TYPEC_TBT_SID) + return 0; + msg = PMC_USB_SAFE_MODE; msg |= port->usb3_port << PMC_USB_MSG_USB3_PORT_SHIFT; @@ -443,7 +454,7 @@ pmc_usb_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) return 0; if (state->mode == TYPEC_STATE_SAFE) - return pmc_usb_mux_safe_state(port); + return pmc_usb_mux_safe_state(port, state); if (state->mode == TYPEC_STATE_USB) return pmc_usb_connect(port, port->role); -- cgit v1.2.3 From 6d8fc203b28ff8f6115fbe5eaf584de8b824f4fa Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Wed, 2 Nov 2022 17:15:42 +0100 Subject: usb: typec: tipd: Prevent uninitialized event{1,2} in IRQ handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If reading TPS_REG_INT_EVENT1/2 fails in the interrupt handler event1 and event2 may be uninitialized when they are used to determine IRQ_HANDLED vs. IRQ_NONE in the error path. Fixes: c7260e29dd20 ("usb: typec: tipd: Add short-circuit for no irqs") Fixes: 45188f27b3d0 ("usb: typec: tipd: Add support for Apple CD321X") Cc: stable Signed-off-by: Sven Peter Reviewed-by: Eric Curtin Reviewed-by: Heikki Krogerus Reviewed-by: Guido Günther Link: https://lore.kernel.org/r/20221102161542.30669-1-sven@svenpeter.dev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tipd/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c index b637e8b378b3..2a77bab948f5 100644 --- a/drivers/usb/typec/tipd/core.c +++ b/drivers/usb/typec/tipd/core.c @@ -474,7 +474,7 @@ static void tps6598x_handle_plug_event(struct tps6598x *tps, u32 status) static irqreturn_t cd321x_interrupt(int irq, void *data) { struct tps6598x *tps = data; - u64 event; + u64 event = 0; u32 status; int ret; @@ -519,8 +519,8 @@ err_unlock: static irqreturn_t tps6598x_interrupt(int irq, void *data) { struct tps6598x *tps = data; - u64 event1; - u64 event2; + u64 event1 = 0; + u64 event2 = 0; u32 status; int ret; -- cgit v1.2.3 From 26c263bf1847d4dadba016a0457c4c5f446407bf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 8 Nov 2022 09:30:52 -0800 Subject: Input: i8042 - apply probe defer to more ASUS ZenBook models There are yet a few more ASUS ZenBook models that require the deferred probe. At least, there are different ZenBook UX325x and UX425x models. Let's extend the DMI matching table entries for adapting those missing models. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20221108142027.28480-1-tiwai@suse.de Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-acpipnpio.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index 0778dc03cd9e..46f8a694291e 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -115,18 +115,18 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_NEVER) }, { - /* ASUS ZenBook UX425UA */ + /* ASUS ZenBook UX425UA/QA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425"), }, .driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER) }, { - /* ASUS ZenBook UM325UA */ + /* ASUS ZenBook UM325UA/QA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325"), }, .driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER) }, -- cgit v1.2.3 From d68cc25b7c7fb3034c5a5b5f350a0b858c6d5a45 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sun, 6 Nov 2022 22:48:04 +0100 Subject: usb: dwc3: Do not get extcon device when usb-role-switch is used The change breaks device tree based platforms with PHY device and use usb-role-switch instead of an extcon switch. extcon_find_edev_by_node() will return EPROBE_DEFER if it can not find a device so probing without an extcon device will be deferred indefinitely. Fix this by explicitly checking for usb-role-switch. At least the out-of-tree USB3 support on Apple silicon based platforms using dwc3 with tipd USB Type-C and PD controller is affected by this issue. Fixes: d182c2e1bc92 ("usb: dwc3: Don't switch OTG -> peripheral if extcon is present") Cc: stable@kernel.org Signed-off-by: Janne Grunau Acked-by: Thinh Nguyen Reviewed-by: Sven Peter Link: https://lore.kernel.org/r/20221106214804.2814-1-j@jannau.net Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c0e7c76dc5c8..1f348bc867c2 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1710,6 +1710,16 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) return extcon_get_extcon_dev(name); + /* + * Check explicitly if "usb-role-switch" is used since + * extcon_find_edev_by_node() can not be used to check the absence of + * an extcon device. In the absence of an device it will always return + * EPROBE_DEFER. + */ + if (IS_ENABLED(CONFIG_USB_ROLE_SWITCH) && + device_property_read_bool(dev, "usb-role-switch")) + return NULL; + /* * Try to get an extcon device from the USB PHY controller's "port" * node. Check if it has the "port" node first, to avoid printing the -- cgit v1.2.3 From f530bc60a30bee47ff51b7fb71511fdd058b774a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:33 +1000 Subject: drm/nouveau/disp: move HDMI config into acquire + infoframe methods v2: - fix typo in sorhdmi/g84 struct initialiser (kbuild test robot) v3: - less convoluted flow control in nvkm_uoutp_mthd_acquire_tmds() (lyude) v4: - we don't support hdmi on original nv50, don't try Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 172 +++++++++------------ drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 14 -- drivers/gpu/drm/nouveau/include/nvif/if0012.h | 24 ++- drivers/gpu/drm/nouveau/include/nvif/outp.h | 5 +- drivers/gpu/drm/nouveau/nvif/outp.c | 28 +++- drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c | 91 ++++++----- drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c | 93 ++++++----- drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c | 85 ++++++---- drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c | 13 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c | 89 +++++++---- drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c | 95 +++++++----- drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h | 23 +-- drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 3 + .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 45 ------ drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 74 +++++++++ 21 files changed, 503 insertions(+), 378 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 0a8404686f16..edf899670287 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -744,123 +745,85 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc, /****************************************************************************** * HDMI *****************************************************************************/ -static void -nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nv50_disp *disp = nv50_disp(encoder->dev); - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_hdmi_pwr_v0 pwr; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) | - (0x0100 << nv_crtc->index), - }; - - nvif_mthd(&disp->disp->object, 0, &args, sizeof(args)); -} - static void nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc, struct nouveau_connector *nv_connector, struct drm_atomic_state *state, - struct drm_display_mode *mode) + struct drm_display_mode *mode, bool hda) { struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nv50_disp *disp = nv50_disp(encoder->dev); - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_hdmi_pwr_v0 pwr; - u8 infoframes[2 * 17]; /* two frames, up to 17 bytes each */ - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) | - (0x0100 << nv_crtc->index), - .pwr.state = 1, - .pwr.rekey = 56, /* binary driver, and tegra, constant */ - }; - struct drm_hdmi_info *hdmi; + struct drm_hdmi_info *hdmi = &nv_connector->base.display_info.hdmi; + union hdmi_infoframe infoframe; + const u8 rekey = 56; /* binary driver, and tegra, constant */ + u8 config, scdc = 0; u32 max_ac_packet; - union hdmi_infoframe avi_frame; - union hdmi_infoframe vendor_frame; - bool high_tmds_clock_ratio = false, scrambling = false; - u8 config; - int ret; - int size; - - if (!drm_detect_hdmi_monitor(nv_connector->edid)) - return; - - hdmi = &nv_connector->base.display_info.hdmi; - - ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, - &nv_connector->base, mode); - if (!ret) { - drm_hdmi_avi_infoframe_quant_range(&avi_frame.avi, - &nv_connector->base, mode, - HDMI_QUANTIZATION_RANGE_FULL); - /* We have an AVI InfoFrame, populate it to the display */ - args.pwr.avi_infoframe_length - = hdmi_infoframe_pack(&avi_frame, args.infoframes, 17); - } - - ret = drm_hdmi_vendor_infoframe_from_display_mode(&vendor_frame.vendor.hdmi, - &nv_connector->base, mode); - if (!ret) { - /* We have a Vendor InfoFrame, populate it to the display */ - args.pwr.vendor_infoframe_length - = hdmi_infoframe_pack(&vendor_frame, - args.infoframes - + args.pwr.avi_infoframe_length, - 17); - } + struct { + struct nvif_outp_infoframe_v0 infoframe; + u8 data[17]; + } args; + int ret, size; max_ac_packet = mode->htotal - mode->hdisplay; - max_ac_packet -= args.pwr.rekey; + max_ac_packet -= rekey; max_ac_packet -= 18; /* constant from tegra */ - args.pwr.max_ac_packet = max_ac_packet / 32; + max_ac_packet /= 32; if (hdmi->scdc.scrambling.supported) { - high_tmds_clock_ratio = mode->clock > 340000; - scrambling = high_tmds_clock_ratio || - hdmi->scdc.scrambling.low_rates; - } + const bool high_tmds_clock_ratio = mode->clock > 340000; - args.pwr.scdc = - NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE * scrambling | - NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 * high_tmds_clock_ratio; + ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &config); + if (ret < 0) { + NV_ERROR(drm, "Failure to read SCDC_TMDS_CONFIG: %d\n", ret); + return; + } - size = sizeof(args.base) - + sizeof(args.pwr) - + args.pwr.avi_infoframe_length - + args.pwr.vendor_infoframe_length; - nvif_mthd(&disp->disp->object, 0, &args, size); + config &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE); + if (high_tmds_clock_ratio || hdmi->scdc.scrambling.low_rates) + config |= SCDC_SCRAMBLING_ENABLE; + if (high_tmds_clock_ratio) + config |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40; - nv50_audio_enable(encoder, nv_crtc, nv_connector, state, mode); + ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, config); + if (ret < 0) + NV_ERROR(drm, "Failure to write SCDC_TMDS_CONFIG = 0x%02x: %d\n", + config, ret); - /* If SCDC is supported by the downstream monitor, update - * divider / scrambling settings to what we programmed above. - */ - if (!hdmi->scdc.scrambling.supported) - return; + if (high_tmds_clock_ratio || hdmi->scdc.scrambling.low_rates) + scdc |= NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_SCRAMBLE; + if (high_tmds_clock_ratio) + scdc |= NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_DIV_BY_4; + } - ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &config); - if (ret < 0) { - NV_ERROR(drm, "Failure to read SCDC_TMDS_CONFIG: %d\n", ret); + ret = nvif_outp_acquire_tmds(&nv_encoder->outp, nv_crtc->index, true, + max_ac_packet, rekey, scdc, hda); + if (ret) return; + + /* AVI InfoFrame. */ + args.infoframe.version = 0; + args.infoframe.head = nv_crtc->index; + + if (!drm_hdmi_avi_infoframe_from_display_mode(&infoframe.avi, &nv_connector->base, mode)) { + drm_hdmi_avi_infoframe_quant_range(&infoframe.avi, &nv_connector->base, mode, + HDMI_QUANTIZATION_RANGE_FULL); + + size = hdmi_infoframe_pack(&infoframe, args.data, 17); + } else { + size = 0; } - config &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE); - config |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 * high_tmds_clock_ratio; - config |= SCDC_SCRAMBLING_ENABLE * scrambling; - ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, config); - if (ret < 0) - NV_ERROR(drm, "Failure to write SCDC_TMDS_CONFIG = 0x%02x: %d\n", - config, ret); + + nvif_outp_infoframe(&nv_encoder->outp, NVIF_OUTP_INFOFRAME_V0_AVI, &args.infoframe, size); + + /* Vendor InfoFrame. */ + if (!drm_hdmi_vendor_infoframe_from_display_mode(&infoframe.vendor.hdmi, + &nv_connector->base, mode)) + size = hdmi_infoframe_pack(&infoframe, args.data, 17); + else + size = 0; + + nvif_outp_infoframe(&nv_encoder->outp, NVIF_OUTP_INFOFRAME_V0_VSI, &args.infoframe, size); + + nv50_audio_enable(encoder, nv_crtc, nv_connector, state, mode); } /****************************************************************************** @@ -1622,7 +1585,6 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *st nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0); nv50_audio_disable(encoder, nv_crtc); - nv50_hdmi_disable(&nv_encoder->base.base, nv_crtc); nvif_outp_release(&nv_encoder->outp); nv_encoder->crtc = NULL; } @@ -1636,6 +1598,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta nv50_head_atom(drm_atomic_get_new_crtc_state(state, &nv_crtc->base)); struct drm_display_mode *mode = &asyh->state.adjusted_mode; struct nv50_disp *disp = nv50_disp(encoder->dev); + struct nvif_outp *outp = &nv_encoder->outp; struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector; @@ -1657,7 +1620,12 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta switch (nv_encoder->dcb->type) { case DCB_OUTPUT_TMDS: - nvif_outp_acquire_tmds(&nv_encoder->outp, hda); + if (disp->disp->object.oclass == NV50_DISP || + !drm_detect_hdmi_monitor(nv_connector->edid)) + nvif_outp_acquire_tmds(outp, nv_crtc->index, false, 0, 0, 0, false); + else + nv50_hdmi_enable(encoder, nv_crtc, nv_connector, state, mode, hda); + if (nv_encoder->outp.or.link & 1) { proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_A; /* Only enable dual-link if: @@ -1673,8 +1641,6 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta } else { proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B; } - - nv50_hdmi_enable(&nv_encoder->base.base, nv_crtc, nv_connector, state, mode); break; case DCB_OUTPUT_LVDS: proto = NV507D_SOR_SET_CONTROL_PROTOCOL_LVDS_CUSTOM; @@ -1900,7 +1866,7 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st switch (nv_encoder->dcb->type) { case DCB_OUTPUT_TMDS: ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC); - nvif_outp_acquire_tmds(&nv_encoder->outp, false); + nvif_outp_acquire_tmds(&nv_encoder->outp, false, false, 0, 0, 0, false); break; case DCB_OUTPUT_DP: ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC); diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index f371fc7a1d10..6389558dda1f 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -29,7 +29,6 @@ struct nv50_disp_scanoutpos_v0 { struct nv50_disp_mthd_v1 { __u8 version; #define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 -#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22 #define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25 #define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26 __u8 method; @@ -44,19 +43,6 @@ struct nv50_disp_sor_hda_eld_v0 { __u8 data[]; }; -struct nv50_disp_sor_hdmi_pwr_v0 { - __u8 version; - __u8 state; - __u8 max_ac_packet; - __u8 rekey; - __u8 avi_infoframe_length; - __u8 vendor_infoframe_length; -#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE (1 << 0) -#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 (1 << 1) - __u8 scdc; - __u8 pad07[1]; -}; - struct nv50_disp_sor_dp_mst_link_v0 { __u8 version; __u8 state; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index 4fcb9e4f5d76..06ed372cbe5a 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -13,6 +13,7 @@ union nvif_outp_args { #define NVIF_OUTP_V0_LOAD_DETECT 0x00 #define NVIF_OUTP_V0_ACQUIRE 0x01 #define NVIF_OUTP_V0_RELEASE 0x02 +#define NVIF_OUTP_V0_INFOFRAME 0x03 union nvif_outp_load_detect_args { struct nvif_outp_load_detect_v0 { @@ -37,8 +38,15 @@ union nvif_outp_acquire_args { __u8 pad04[4]; union { struct { - __u8 hda; - __u8 pad01[7]; + __u8 head; + __u8 hdmi; + __u8 hdmi_max_ac_packet; + __u8 hdmi_rekey; +#define NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_SCRAMBLE (1 << 0) +#define NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_DIV_BY_4 (1 << 1) + __u8 hdmi_scdc; + __u8 hdmi_hda; + __u8 pad06[2]; } tmds; struct { __u8 dual; @@ -57,4 +65,16 @@ union nvif_outp_release_args { struct nvif_outp_release_vn { } vn; }; + +union nvif_outp_infoframe_args { + struct nvif_outp_infoframe_v0 { + __u8 version; +#define NVIF_OUTP_INFOFRAME_V0_AVI 0 +#define NVIF_OUTP_INFOFRAME_V0_VSI 1 + __u8 type; + __u8 head; + __u8 pad03[5]; + __u8 data[]; + } v0; +}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index e247d441afc1..dd7e603d13c9 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -2,6 +2,7 @@ #ifndef __NVIF_OUTP_H__ #define __NVIF_OUTP_H__ #include +#include struct nvif_disp; struct nvif_outp { @@ -17,8 +18,10 @@ int nvif_outp_ctor(struct nvif_disp *, const char *name, int id, struct nvif_out void nvif_outp_dtor(struct nvif_outp *); int nvif_outp_load_detect(struct nvif_outp *, u32 loadval); int nvif_outp_acquire_rgb_crt(struct nvif_outp *); -int nvif_outp_acquire_tmds(struct nvif_outp *, bool hda); +int nvif_outp_acquire_tmds(struct nvif_outp *, int head, + bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda); int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8); int nvif_outp_acquire_dp(struct nvif_outp *, bool hda); void nvif_outp_release(struct nvif_outp *); +int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size); #endif diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 58cd629657fb..987bc3a9e7bf 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -24,7 +24,18 @@ #include #include -#include + +int +nvif_outp_infoframe(struct nvif_outp *outp, u8 type, struct nvif_outp_infoframe_v0 *args, u32 size) +{ + int ret; + + args->type = type; + + ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_INFOFRAME, args, sizeof(*args) + size); + NVIF_ERRON(ret, &outp->object, "[INFOFRAME type:%d size:%d]", type, size); + return ret; +} void nvif_outp_release(struct nvif_outp *outp) @@ -82,16 +93,25 @@ nvif_outp_acquire_lvds(struct nvif_outp *outp, bool dual, bool bpc8) } int -nvif_outp_acquire_tmds(struct nvif_outp *outp, bool hda) +nvif_outp_acquire_tmds(struct nvif_outp *outp, int head, + bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda) { struct nvif_outp_acquire_v0 args; int ret; - args.tmds.hda = hda; + args.tmds.head = head; + args.tmds.hdmi = hdmi; + args.tmds.hdmi_max_ac_packet = max_ac_packet; + args.tmds.hdmi_rekey = rekey; + args.tmds.hdmi_scdc = scdc; + args.tmds.hdmi_hda = hda; ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_TMDS, &args); NVIF_ERRON(ret, &outp->object, - "[ACQUIRE proto:TMDS hda:%d] or:%d link:%d", args.tmds.hda, args.or, args.link); + "[ACQUIRE proto:TMDS head:%d hdmi:%d max_ac_packet:%d rekey:%d scdc:%d hda:%d]" + " or:%d link:%d", args.tmds.head, args.tmds.hdmi, args.tmds.hdmi_max_ac_packet, + args.tmds.hdmi_rekey, args.tmds.hdmi_scdc, args.tmds.hdmi_hda, + args.or, args.link); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index 4966a51af3d7..23ae451ba473 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -29,9 +29,54 @@ #include -void -g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +static void +g84_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe vsi; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000); + if (!size) + return; + + pack_hdmi_infoframe(&vsi, data, size); + + nvkm_wr32(device, 0x616544 + hoff, vsi.header); + nvkm_wr32(device, 0x616548 + hoff, vsi.subpack0_low); + nvkm_wr32(device, 0x61654c + hoff, vsi.subpack0_high); + /* Is there a second (or up to fourth?) set of subpack registers here? */ + /* nvkm_wr32(device, 0x616550 + hoff, vsi.subpack1_low); */ + /* nvkm_wr32(device, 0x616554 + hoff, vsi.subpack1_high); */ + + nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001); +} + +static void +g84_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe avi; + const u32 hoff = head * 0x800; + + pack_hdmi_infoframe(&avi, data, size); + + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + if (!size) + return; + + nvkm_wr32(device, 0x616528 + hoff, avi.header); + nvkm_wr32(device, 0x61652c + hoff, avi.subpack0_low); + nvkm_wr32(device, 0x616530 + hoff, avi.subpack0_high); + nvkm_wr32(device, 0x616534 + hoff, avi.subpack1_low); + nvkm_wr32(device, 0x616538 + hoff, avi.subpack1_high); + + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); +} + + +static void +g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey) { struct nvkm_device *device = ior->disp->engine.subdev.device; const u32 ctrl = 0x40000000 * enable | @@ -39,31 +84,13 @@ g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, max_ac_packet << 16 | rekey; const u32 hoff = head * 0x800; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); if (!(ctrl & 0x40000000)) { nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); return; } - /* AVI InfoFrame */ - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header); - nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); - } - /* Audio InfoFrame */ nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); nvkm_wr32(device, 0x616508 + hoff, 0x000a0184); @@ -71,17 +98,6 @@ g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, nvkm_wr32(device, 0x616510 + hoff, 0x00000000); nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); - /* Vendor InfoFrame */ - nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000); - if (vendor_size) { - nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header); - nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high); - /* Is there a second (or up to fourth?) set of subpack registers here? */ - /* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */ - /* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */ - nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001); - } nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ @@ -96,14 +112,19 @@ g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); } +const struct nvkm_ior_func_hdmi +g84_sor_hdmi = { + .ctrl = g84_sor_hdmi_ctrl, + .infoframe_avi = g84_sor_hdmi_infoframe_avi, + .infoframe_vsi = g84_sor_hdmi_infoframe_vsi, +}; + static const struct nvkm_ior_func g84_sor = { .state = nv50_sor_state, .power = nv50_sor_power, .clock = nv50_sor_clock, - .hdmi = { - .ctrl = g84_sor_hdmi_ctrl, - }, + .hdmi = &g84_sor_hdmi, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c index 7489d0d7fce0..52099b75f52a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c @@ -105,10 +105,7 @@ ga102_sor = { .state = gv100_sor_state, .power = nv50_sor_power, .clock = ga102_sor_clock, - .hdmi = { - .ctrl = gv100_sor_hdmi_ctrl, - .scdc = gm200_sor_hdmi_scdc, - }, + .hdmi = &gv100_sor_hdmi, .dp = &ga102_sor_dp, .hda = &gv100_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index 39822f1b5b95..a48e9bdf4cd0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -202,19 +202,61 @@ gf119_sor_dp = { }; static void -gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +gf119_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe vsi; + const u32 hoff = head * 0x800; + + pack_hdmi_infoframe(&vsi, data, size); + + nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000); + if (!size) + return; + + /* + * These appear to be the audio infoframe registers, + * but no other set of infoframe registers has yet + * been found. + */ + nvkm_wr32(device, 0x616738 + hoff, vsi.header); + nvkm_wr32(device, 0x61673c + hoff, vsi.subpack0_low); + nvkm_wr32(device, 0x616740 + hoff, vsi.subpack0_high); + /* Is there a second (or further?) set of subpack registers here? */ + + nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001); +} + +static void +gf119_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe avi; + const u32 hoff = head * 0x800; + + pack_hdmi_infoframe(&avi, data, size); + + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + if (!size) + return; + + nvkm_wr32(device, 0x61671c + hoff, avi.header); + nvkm_wr32(device, 0x616720 + hoff, avi.subpack0_low); + nvkm_wr32(device, 0x616724 + hoff, avi.subpack0_high); + nvkm_wr32(device, 0x616728 + hoff, avi.subpack1_low); + nvkm_wr32(device, 0x61672c + hoff, avi.subpack1_high); + + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); +} + +static void +gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey) { struct nvkm_device *device = ior->disp->engine.subdev.device; const u32 ctrl = 0x40000000 * enable | max_ac_packet << 16 | rekey; const u32 hoff = head * 0x800; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); if (!(ctrl & 0x40000000)) { nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); @@ -224,32 +266,6 @@ gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe return; } - /* AVI InfoFrame */ - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x61671c + hoff, avi_infoframe.header); - nvkm_wr32(device, 0x616720 + hoff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x616724 + hoff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x616728 + hoff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x61672c + hoff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); - } - - /* GENERIC(?) / Vendor InfoFrame? */ - nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000); - if (vendor_size) { - /* - * These appear to be the audio infoframe registers, - * but no other set of infoframe registers has yet - * been found. - */ - nvkm_wr32(device, 0x616738 + hoff, vendor_infoframe.header); - nvkm_wr32(device, 0x61673c + hoff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x616740 + hoff, vendor_infoframe.subpack0_high); - /* Is there a second (or further?) set of subpack registers here? */ - nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001); - } - /* ??? InfoFrame? */ nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); nvkm_wr32(device, 0x6167ac + hoff, 0x00000010); @@ -259,6 +275,13 @@ gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); } +static const struct nvkm_ior_func_hdmi +gf119_sor_hdmi = { + .ctrl = gf119_sor_hdmi_ctrl, + .infoframe_avi = gf119_sor_hdmi_infoframe_avi, + .infoframe_vsi = gf119_sor_hdmi_infoframe_vsi, +}; + void gf119_sor_clock(struct nvkm_ior *sor) { @@ -305,9 +328,7 @@ gf119_sor = { .state = gf119_sor_state, .power = nv50_sor_power, .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gf119_sor_hdmi_ctrl, - }, + .hdmi = &gf119_sor_hdmi, .dp = &gf119_sor_dp, .hda = &gf119_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index 7248e9ec835e..876a21a0cebb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -30,8 +30,51 @@ #include void -gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +gk104_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe vsi; + const u32 hoff = head * 0x400; + + pack_hdmi_infoframe(&vsi, data, size); + + /* GENERIC(?) / Vendor InfoFrame? */ + nvkm_mask(device, 0x690100 + hoff, 0x00010001, 0x00000000); + if (!size) + return; + + nvkm_wr32(device, 0x690108 + hoff, vsi.header); + nvkm_wr32(device, 0x69010c + hoff, vsi.subpack0_low); + nvkm_wr32(device, 0x690110 + hoff, vsi.subpack0_high); + /* Is there a second (or further?) set of subpack registers here? */ + nvkm_mask(device, 0x690100 + hoff, 0x00000001, 0x00000001); +} + +void +gk104_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe avi; + const u32 hoff = head * 0x400; + + pack_hdmi_infoframe(&avi, data, size); + + /* AVI InfoFrame */ + nvkm_mask(device, 0x690000 + hoff, 0x00000001, 0x00000000); + if (!size) + return; + + nvkm_wr32(device, 0x690008 + hoff, avi.header); + nvkm_wr32(device, 0x69000c + hoff, avi.subpack0_low); + nvkm_wr32(device, 0x690010 + hoff, avi.subpack0_high); + nvkm_wr32(device, 0x690014 + hoff, avi.subpack1_low); + nvkm_wr32(device, 0x690018 + hoff, avi.subpack1_high); + + nvkm_mask(device, 0x690000 + hoff, 0x00000001, 0x00000001); +} + +void +gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey) { struct nvkm_device *device = ior->disp->engine.subdev.device; const u32 ctrl = 0x40000000 * enable | @@ -39,11 +82,6 @@ gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe rekey; const u32 hoff = head * 0x800; const u32 hdmi = head * 0x400; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); if (!(ctrl & 0x40000000)) { nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); @@ -53,28 +91,6 @@ gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe return; } - /* AVI InfoFrame */ - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header); - nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001); - } - - /* GENERIC(?) / Vendor InfoFrame? */ - nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000); - if (vendor_size) { - nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high); - /* Is there a second (or further?) set of subpack registers here? */ - nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001); - } - - /* ??? InfoFrame? */ nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010); @@ -87,14 +103,19 @@ gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); } +const struct nvkm_ior_func_hdmi +gk104_sor_hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .infoframe_avi = gk104_sor_hdmi_infoframe_avi, + .infoframe_vsi = gk104_sor_hdmi_infoframe_vsi, +}; + static const struct nvkm_ior_func gk104_sor = { .state = gf119_sor_state, .power = nv50_sor_power, .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_sor_hdmi_ctrl, - }, + .hdmi = &gk104_sor_hdmi, .dp = &gf119_sor_dp, .hda = &gf119_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index 9e9ef49bd8ac..b4d8e868616f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -70,9 +70,7 @@ gm107_sor = { .state = gf119_sor_state, .power = nv50_sor_power, .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_sor_hdmi_ctrl, - }, + .hdmi = &gk104_sor_hdmi, .dp = &gm107_sor_dp, .hda = &gf119_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c index 4ecc8f98af6e..562ebae57d44 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c @@ -79,6 +79,14 @@ gm200_sor_hdmi_scdc(struct nvkm_ior *ior, u8 scdc) ior->tmds.high_speed = !!(scdc & 0x2); } +const struct nvkm_ior_func_hdmi +gm200_sor_hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + .infoframe_avi = gk104_sor_hdmi_infoframe_avi, + .infoframe_vsi = gk104_sor_hdmi_infoframe_vsi, +}; + void gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) { @@ -131,10 +139,7 @@ gm200_sor = { .state = gf119_sor_state, .power = nv50_sor_power, .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_sor_hdmi_ctrl, - .scdc = gm200_sor_hdmi_scdc, - }, + .hdmi = &gm200_sor_hdmi, .dp = &gm200_sor_dp, .hda = &gf119_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c index 7172a9dfd89b..7f1eb4332040 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c @@ -37,10 +37,7 @@ gp100_sor = { .state = gf119_sor_state, .power = nv50_sor_power, .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_sor_hdmi_ctrl, - .scdc = gm200_sor_hdmi_scdc, - }, + .hdmi = &gm200_sor_hdmi, .dp = &gm200_sor_dp, .hda = &gf119_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index 70c49e7af9cf..a2c7c6f83dcd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -92,9 +92,53 @@ gt215_sor_dp = { .watermark = g94_sor_dp_watermark, }; -void -gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +static void +gt215_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe vsi; + const u32 soff = nv50_ior_base(ior); + + pack_hdmi_infoframe(&vsi, data, size); + + nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000); + if (!size) + return; + + nvkm_wr32(device, 0x61c544 + soff, vsi.header); + nvkm_wr32(device, 0x61c548 + soff, vsi.subpack0_low); + nvkm_wr32(device, 0x61c54c + soff, vsi.subpack0_high); + /* Is there a second (or up to fourth?) set of subpack registers here? */ + /* nvkm_wr32(device, 0x61c550 + soff, vsi.subpack1_low); */ + /* nvkm_wr32(device, 0x61c554 + soff, vsi.subpack1_high); */ + + nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001); +} + +static void +gt215_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe avi; + const u32 soff = nv50_ior_base(ior); + + pack_hdmi_infoframe(&avi, data, size); + + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + if (size) + return; + + nvkm_wr32(device, 0x61c528 + soff, avi.header); + nvkm_wr32(device, 0x61c52c + soff, avi.subpack0_low); + nvkm_wr32(device, 0x61c530 + soff, avi.subpack0_high); + nvkm_wr32(device, 0x61c534 + soff, avi.subpack1_low); + nvkm_wr32(device, 0x61c538 + soff, avi.subpack1_high); + + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); +} + +static void +gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey) { struct nvkm_device *device = ior->disp->engine.subdev.device; const u32 ctrl = 0x40000000 * enable | @@ -102,11 +146,6 @@ gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe max_ac_packet << 16 | rekey; const u32 soff = nv50_ior_base(ior); - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); if (!(ctrl & 0x40000000)) { nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000); @@ -116,17 +155,6 @@ gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe return; } - /* AVI InfoFrame */ - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x61c528 + soff, avi_infoframe.header); - nvkm_wr32(device, 0x61c52c + soff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x61c530 + soff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x61c534 + soff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x61c538 + soff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); - } - /* Audio InfoFrame */ nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); nvkm_wr32(device, 0x61c508 + soff, 0x000a0184); @@ -134,18 +162,6 @@ gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe nvkm_wr32(device, 0x61c510 + soff, 0x00000000); nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001); - /* Vendor InfoFrame */ - nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000); - if (vendor_size) { - nvkm_wr32(device, 0x61c544 + soff, vendor_infoframe.header); - nvkm_wr32(device, 0x61c548 + soff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x61c54c + soff, vendor_infoframe.subpack0_high); - /* Is there a second (or up to fourth?) set of subpack registers here? */ - /* nvkm_wr32(device, 0x61c550 + soff, vendor_infoframe.subpack1_low); */ - /* nvkm_wr32(device, 0x61c554 + soff, vendor_infoframe.subpack1_high); */ - nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001); - } - nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ @@ -159,14 +175,19 @@ gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl); } +const struct nvkm_ior_func_hdmi +gt215_sor_hdmi = { + .ctrl = gt215_sor_hdmi_ctrl, + .infoframe_avi = gt215_sor_hdmi_infoframe_avi, + .infoframe_vsi = gt215_sor_hdmi_infoframe_vsi, +}; + static const struct nvkm_ior_func gt215_sor = { .state = g94_sor_state, .power = nv50_sor_power, .clock = nv50_sor_clock, - .hdmi = { - .ctrl = gt215_sor_hdmi_ctrl, - }, + .hdmi = >215_sor_hdmi, .dp = >215_sor_dp, .hda = >215_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c index 6b9d49270fa7..115d0997fd62 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -96,9 +96,54 @@ gv100_sor_dp = { .watermark = gv100_sor_dp_watermark, }; -void -gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +static void +gv100_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe vsi; + const u32 hoff = head * 0x400; + + pack_hdmi_infoframe(&vsi, data, size); + + nvkm_mask(device, 0x6f0100 + hoff, 0x00010001, 0x00000000); + if (!size) + return; + + nvkm_wr32(device, 0x6f0108 + hoff, vsi.header); + nvkm_wr32(device, 0x6f010c + hoff, vsi.subpack0_low); + nvkm_wr32(device, 0x6f0110 + hoff, vsi.subpack0_high); + nvkm_wr32(device, 0x6f0114 + hoff, 0x00000000); + nvkm_wr32(device, 0x6f0118 + hoff, 0x00000000); + nvkm_wr32(device, 0x6f011c + hoff, 0x00000000); + nvkm_wr32(device, 0x6f0120 + hoff, 0x00000000); + nvkm_wr32(device, 0x6f0124 + hoff, 0x00000000); + nvkm_mask(device, 0x6f0100 + hoff, 0x00000001, 0x00000001); +} + +static void +gv100_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + struct packed_hdmi_infoframe avi; + const u32 hoff = head * 0x400; + + pack_hdmi_infoframe(&avi, data, size); + + nvkm_mask(device, 0x6f0000 + hoff, 0x00000001, 0x00000000); + if (!size) + return; + + nvkm_wr32(device, 0x6f0008 + hoff, avi.header); + nvkm_wr32(device, 0x6f000c + hoff, avi.subpack0_low); + nvkm_wr32(device, 0x6f0010 + hoff, avi.subpack0_high); + nvkm_wr32(device, 0x6f0014 + hoff, avi.subpack1_low); + nvkm_wr32(device, 0x6f0018 + hoff, avi.subpack1_high); + + nvkm_mask(device, 0x6f0000 + hoff, 0x00000001, 0x00000001); +} + +static void +gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey) { struct nvkm_device *device = ior->disp->engine.subdev.device; const u32 ctrl = 0x40000000 * enable | @@ -106,11 +151,6 @@ gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe rekey; const u32 hoff = head * 0x800; const u32 hdmi = head * 0x400; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); if (!(ctrl & 0x40000000)) { nvkm_mask(device, 0x6165c0 + hoff, 0x40000000, 0x00000000); @@ -120,32 +160,6 @@ gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe return; } - /* AVI InfoFrame (AVI). */ - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x6f0008 + hdmi, avi_infoframe.header); - nvkm_wr32(device, 0x6f000c + hdmi, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0010 + hdmi, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x6f0014 + hdmi, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x6f0018 + hdmi, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000001); - } - - /* Vendor-specific InfoFrame (VSI). */ - nvkm_mask(device, 0x6f0100 + hdmi, 0x00010001, 0x00000000); - if (vendor_size) { - nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); - nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0120 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0124 + hdmi, 0x00000000); - nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000001); - } - - /* General Control (GCP). */ nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); nvkm_wr32(device, 0x6f00cc + hdmi, 0x00000010); @@ -158,6 +172,14 @@ gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe nvkm_mask(device, 0x6165c0 + hoff, 0x401f007f, ctrl); } +const struct nvkm_ior_func_hdmi +gv100_sor_hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + .infoframe_avi = gv100_sor_hdmi_infoframe_avi, + .infoframe_vsi = gv100_sor_hdmi_infoframe_vsi, +}; + void gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) { @@ -190,10 +212,7 @@ gv100_sor = { .state = gv100_sor_state, .power = nv50_sor_power, .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_sor_hdmi_ctrl, - .scdc = gm200_sor_hdmi_scdc, - }, + .hdmi = &gv100_sor_hdmi, .dp = &gv100_sor_dp, .hda = &gv100_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h index 671c4674ffcc..da1b1a626ef2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -63,12 +63,12 @@ struct nvkm_ior_func { void (*war_2)(struct nvkm_ior *); void (*war_3)(struct nvkm_ior *); - struct { - void (*ctrl)(struct nvkm_ior *, int head, bool enable, - u8 max_ac_packet, u8 rekey, u8 *avi, u8 avi_size, - u8 *vendor, u8 vendor_size); + const struct nvkm_ior_func_hdmi { + void (*ctrl)(struct nvkm_ior *, int head, bool enable, u8 max_ac_packet, u8 rekey); void (*scdc)(struct nvkm_ior *, u8 scdc); - } hdmi; + void (*infoframe_avi)(struct nvkm_ior *, int head, void *data, u32 size); + void (*infoframe_vsi)(struct nvkm_ior *, int head, void *data, u32 size); + } *hdmi; const struct nvkm_ior_func_dp { u8 lanes[4]; @@ -124,9 +124,10 @@ void nv50_sor_power(struct nvkm_ior *, bool, bool, bool, bool, bool); void nv50_sor_clock(struct nvkm_ior *); int g84_sor_new(struct nvkm_disp *, int); -void g84_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); +extern const struct nvkm_ior_func_hdmi g84_sor_hdmi; int g94_sor_cnt(struct nvkm_disp *, unsigned long *); + void g94_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); extern const struct nvkm_ior_func_dp g94_sor_dp; int g94_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *); @@ -137,7 +138,7 @@ void g94_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void g94_sor_dp_activesym(struct nvkm_ior *, int, u8, u8, u8, u8); void g94_sor_dp_watermark(struct nvkm_ior *, int, u8); -void gt215_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); +extern const struct nvkm_ior_func_hdmi gt215_sor_hdmi; void gt215_sor_dp_audio(struct nvkm_ior *, int, bool); extern const struct nvkm_ior_func_hda gt215_sor_hda; @@ -156,12 +157,16 @@ void gf119_sor_hda_hpd(struct nvkm_ior *, int, bool); void gf119_sor_hda_eld(struct nvkm_ior *, int, u8 *, u8); int gk104_sor_new(struct nvkm_disp *, int); -void gk104_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); +extern const struct nvkm_ior_func_hdmi gk104_sor_hdmi; +void gk104_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8); +void gk104_sor_hdmi_infoframe_avi(struct nvkm_ior *, int, void *, u32); +void gk104_sor_hdmi_infoframe_vsi(struct nvkm_ior *, int, void *, u32); void gm107_sor_dp_pattern(struct nvkm_ior *, int); void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *); int gm200_sor_route_get(struct nvkm_outp *, int *); +extern const struct nvkm_ior_func_hdmi gm200_sor_hdmi; void gm200_sor_hdmi_scdc(struct nvkm_ior *, u8); extern const struct nvkm_ior_func_dp gm200_sor_dp; void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int); @@ -170,7 +175,7 @@ int gp100_sor_new(struct nvkm_disp *, int); int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); void gv100_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); -void gv100_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); +extern const struct nvkm_ior_func_hdmi gv100_sor_hdmi; void gv100_sor_dp_audio(struct nvkm_ior *, int, bool); void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c index 916b1d477b0b..841e3b69fcaf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c @@ -31,9 +31,7 @@ mcp77_sor = { .state = g94_sor_state, .power = nv50_sor_power, .clock = nv50_sor_clock, - .hdmi = { - .ctrl = g84_sor_hdmi_ctrl, - }, + .hdmi = &g84_sor_hdmi, .dp = &g94_sor_dp, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c index a5a0b9439374..f96ba4752655 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c @@ -44,9 +44,7 @@ mcp89_sor = { .state = g94_sor_state, .power = nv50_sor_power, .clock = nv50_sor_clock, - .hdmi = { - .ctrl = gt215_sor_hdmi_ctrl, - }, + .hdmi = >215_sor_hdmi, .dp = &mcp89_sor_dp, .hda = >215_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index 16aadcedcbda..eb9cd1146825 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -60,6 +60,9 @@ struct nvkm_outp { }; struct nvkm_object object; + struct { + struct nvkm_head *head; + } asy; }; int nvkm_outp_new_(const struct nvkm_outp_func *, struct nvkm_disp *, int index, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index f028ab17f8cf..9c481fa49bc5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -121,51 +121,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) ior->func->hda->hpd(ior, hidx, false); } - return 0; - } - break; - case NV50_DISP_MTHD_V1_SOR_HDMI_PWR: { - union { - struct nv50_disp_sor_hdmi_pwr_v0 v0; - } *args = data; - u8 *vendor, vendor_size; - u8 *avi, avi_size; - int ret = -ENOSYS; - - nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d " - "max_ac_packet %d rekey %d scdc %d\n", - args->v0.version, args->v0.state, - args->v0.max_ac_packet, args->v0.rekey, - args->v0.scdc); - if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f) - return -EINVAL; - if ((args->v0.avi_infoframe_length - + args->v0.vendor_infoframe_length) > size) - return -EINVAL; - else - if ((args->v0.avi_infoframe_length - + args->v0.vendor_infoframe_length) < size) - return -E2BIG; - avi = data; - avi_size = args->v0.avi_infoframe_length; - vendor = avi + avi_size; - vendor_size = args->v0.vendor_infoframe_length; - } else - return ret; - - if (!outp->ior->func->hdmi.ctrl) - return -ENODEV; - - outp->ior->func->hdmi.ctrl(outp->ior, hidx, args->v0.state, - args->v0.max_ac_packet, - args->v0.rekey, avi, avi_size, - vendor, vendor_size); - - if (outp->ior->func->hdmi.scdc) - outp->ior->func->hdmi.scdc(outp->ior, args->v0.scdc); - return 0; } break; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c index e4ad1a6f6c88..f5242a672279 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -88,10 +88,7 @@ tu102_sor = { .state = gv100_sor_state, .power = nv50_sor_power, .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_sor_hdmi_ctrl, - .scdc = gm200_sor_hdmi_scdc, - }, + .hdmi = &gv100_sor_hdmi, .dp = &tu102_sor_dp, .hda = &gv100_sor_hda, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index 7e0cef0f80a9..f82100b1a45d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -21,22 +21,88 @@ */ #define nvkm_uoutp(p) container_of((p), struct nvkm_outp, object) #include "outp.h" +#include "head.h" #include "ior.h" #include +static int +nvkm_uoutp_mthd_infoframe(struct nvkm_outp *outp, void *argv, u32 argc) +{ + struct nvkm_ior *ior = outp->ior; + union nvif_outp_infoframe_args *args = argv; + + if (argc < sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + if (!nvkm_head_find(outp->disp, args->v0.head)) + return -EINVAL; + + switch (ior->func->hdmi ? args->v0.type : 0xff) { + case NVIF_OUTP_INFOFRAME_V0_AVI: + ior->func->hdmi->infoframe_avi(ior, args->v0.head, argv, argc); + return 0; + case NVIF_OUTP_INFOFRAME_V0_VSI: + ior->func->hdmi->infoframe_vsi(ior, args->v0.head, argv, argc); + return 0; + default: + break; + } + + return -EINVAL; +} + static int nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc) { + struct nvkm_head *head = outp->asy.head; + struct nvkm_ior *ior = outp->ior; union nvif_outp_release_args *args = argv; if (argc != sizeof(args->vn)) return -ENOSYS; + if (ior->func->hdmi && head) { + ior->func->hdmi->infoframe_avi(ior, head->id, NULL, 0); + ior->func->hdmi->infoframe_vsi(ior, head->id, NULL, 0); + ior->func->hdmi->ctrl(ior, head->id, false, 0, 0); + } + nvkm_outp_release(outp, NVKM_OUTP_USER); return 0; } +static int +nvkm_uoutp_mthd_acquire_tmds(struct nvkm_outp *outp, u8 head, u8 hdmi, u8 hdmi_max_ac_packet, + u8 hdmi_rekey, u8 hdmi_scdc, u8 hdmi_hda) +{ + struct nvkm_ior *ior; + int ret; + + if (!(outp->asy.head = nvkm_head_find(outp->disp, head))) + return -EINVAL; + + ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, hdmi && hdmi_hda); + if (ret) + return ret; + + ior = outp->ior; + + if (hdmi) { + if (!ior->func->hdmi || + hdmi_max_ac_packet > 0x1f || hdmi_rekey > 0x7f || + (hdmi_scdc && !ior->func->hdmi->scdc)) { + nvkm_outp_release(outp, NVKM_OUTP_USER); + return -EINVAL; + } + + ior->func->hdmi->ctrl(ior, head, hdmi, hdmi_max_ac_packet, hdmi_rekey); + if (ior->func->hdmi->scdc) + ior->func->hdmi->scdc(ior, hdmi_scdc); + } + + return 0; +} + static int nvkm_uoutp_mthd_acquire_lvds(struct nvkm_outp *outp, bool dual, bool bpc8) { @@ -63,6 +129,13 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, false); break; case NVIF_OUTP_ACQUIRE_V0_TMDS: + ret = nvkm_uoutp_mthd_acquire_tmds(outp, args->v0.tmds.head, + args->v0.tmds.hdmi, + args->v0.tmds.hdmi_max_ac_packet, + args->v0.tmds.hdmi_rekey, + args->v0.tmds.hdmi_scdc, + args->v0.tmds.hdmi_hda); + break; case NVIF_OUTP_ACQUIRE_V0_DP: ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, args->v0.dp.hda); break; @@ -110,6 +183,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc) { switch (mthd) { case NVIF_OUTP_V0_RELEASE : return nvkm_uoutp_mthd_release (outp, argv, argc); + case NVIF_OUTP_V0_INFOFRAME : return nvkm_uoutp_mthd_infoframe (outp, argv, argc); default: break; } -- cgit v1.2.3 From a9f5d7721923f6016578167640b8dd5cb0c5a698 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:33 +1000 Subject: drm/nouveau/disp: move HDA ELD method Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 50 ++++++++-------------- drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 7 --- drivers/gpu/drm/nouveau/include/nvif/if0012.h | 10 +++++ drivers/gpu/drm/nouveau/include/nvif/outp.h | 1 + drivers/gpu/drm/nouveau/nvif/outp.c | 21 +++++++++ .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 33 -------------- drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 30 +++++++++++++ 7 files changed, 81 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index edf899670287..c61617acaf87 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -673,29 +673,33 @@ nv50_audio_component_fini(struct nouveau_drm *drm) /****************************************************************************** * Audio *****************************************************************************/ +static bool +nv50_audio_supported(struct drm_encoder *encoder) +{ + struct nv50_disp *disp = nv50_disp(encoder->dev); + + if (disp->disp->object.oclass <= GT200_DISP || + disp->disp->object.oclass == GT206_DISP) + return false; + + return true; +} + static void nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) { struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nv50_disp *disp = nv50_disp(encoder->dev); struct nvif_outp *outp = &nv_encoder->outp; - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_hda_eld_v0 eld; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) | - (0x0100 << nv_crtc->index), - }; + + if (!nv50_audio_supported(encoder)) + return; mutex_lock(&drm->audio.lock); if (nv_encoder->audio.enabled) { nv_encoder->audio.enabled = false; nv_encoder->audio.connector = NULL; - nvif_mthd(&disp->disp->object, 0, &args, sizeof(args)); + nvif_outp_hda_eld(&nv_encoder->outp, nv_crtc->index, NULL, 0); } mutex_unlock(&drm->audio.lock); @@ -709,31 +713,15 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc, { struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nv50_disp *disp = nv50_disp(encoder->dev); struct nvif_outp *outp = &nv_encoder->outp; - struct __packed { - struct { - struct nv50_disp_mthd_v1 mthd; - struct nv50_disp_sor_hda_eld_v0 eld; - } base; - u8 data[sizeof(nv_connector->base.eld)]; - } args = { - .base.mthd.version = 1, - .base.mthd.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD, - .base.mthd.hasht = nv_encoder->dcb->hasht, - .base.mthd.hashm = (0xf0ff & nv_encoder->dcb->hashm) | - (0x0100 << nv_crtc->index), - }; - if (!drm_detect_monitor_audio(nv_connector->edid)) + if (!nv50_audio_supported(encoder) || !drm_detect_monitor_audio(nv_connector->edid)) return; mutex_lock(&drm->audio.lock); - memcpy(args.data, nv_connector->base.eld, sizeof(args.data)); - - nvif_mthd(&disp->disp->object, 0, &args, - sizeof(args.base) + drm_eld_size(args.data)); + nvif_outp_hda_eld(&nv_encoder->outp, nv_crtc->index, nv_connector->base.eld, + drm_eld_size(nv_connector->base.eld)); nv_encoder->audio.enabled = true; nv_encoder->audio.connector = &nv_connector->base; diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index 6389558dda1f..a71317733748 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -28,7 +28,6 @@ struct nv50_disp_scanoutpos_v0 { struct nv50_disp_mthd_v1 { __u8 version; -#define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 #define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25 #define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26 __u8 method; @@ -37,12 +36,6 @@ struct nv50_disp_mthd_v1 { __u8 pad06[2]; }; -struct nv50_disp_sor_hda_eld_v0 { - __u8 version; - __u8 pad01[7]; - __u8 data[]; -}; - struct nv50_disp_sor_dp_mst_link_v0 { __u8 version; __u8 state; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index 06ed372cbe5a..938d384f5b1f 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -14,6 +14,7 @@ union nvif_outp_args { #define NVIF_OUTP_V0_ACQUIRE 0x01 #define NVIF_OUTP_V0_RELEASE 0x02 #define NVIF_OUTP_V0_INFOFRAME 0x03 +#define NVIF_OUTP_V0_HDA_ELD 0x04 union nvif_outp_load_detect_args { struct nvif_outp_load_detect_v0 { @@ -77,4 +78,13 @@ union nvif_outp_infoframe_args { __u8 data[]; } v0; }; + +union nvif_outp_hda_eld_args { + struct nvif_outp_hda_eld_v0 { + __u8 version; + __u8 head; + __u8 pad02[6]; + __u8 data[]; + } v0; +}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index dd7e603d13c9..c8879d3428c8 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -24,4 +24,5 @@ int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8); int nvif_outp_acquire_dp(struct nvif_outp *, bool hda); void nvif_outp_release(struct nvif_outp *); int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size); +int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size); #endif diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 987bc3a9e7bf..3a7c2d573e69 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -25,6 +25,27 @@ #include +int +nvif_outp_hda_eld(struct nvif_outp *outp, int head, void *data, u32 size) +{ + struct { + struct nvif_outp_hda_eld_v0 mthd; + u8 data[128]; + } args; + int ret; + + if (WARN_ON(size > ARRAY_SIZE(args.data))) + return -EINVAL; + + args.mthd.version = 0; + args.mthd.head = head; + + memcpy(args.data, data, size); + ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDA_ELD, &args, sizeof(args.mthd) + size); + NVIF_ERRON(ret, &outp->object, "[HDA_ELD head:%d size:%d]", head, size); + return ret; +} + int nvif_outp_infoframe(struct nvif_outp *outp, u8 type, struct nvif_outp_infoframe_v0 *args, u32 size) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index 9c481fa49bc5..a5bb15b62a0c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -91,39 +91,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } switch (mthd * !!outp) { - case NV50_DISP_MTHD_V1_SOR_HDA_ELD: { - union { - struct nv50_disp_sor_hda_eld_v0 v0; - } *args = data; - struct nvkm_ior *ior = outp->ior; - int ret = -ENOSYS; - - nvif_ioctl(object, "disp sor hda eld size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - nvif_ioctl(object, "disp sor hda eld vers %d\n", - args->v0.version); - if (size > 0x60) - return -E2BIG; - } else - return ret; - - if (!ior->hda) - return -ENODEV; - - if (size && args->v0.data[0]) { - if (outp->info.type == DCB_OUTPUT_DP) - ior->func->dp->audio(ior, hidx, true); - ior->func->hda->hpd(ior, hidx, true); - ior->func->hda->eld(ior, hidx, data, size); - } else { - if (outp->info.type == DCB_OUTPUT_DP) - ior->func->dp->audio(ior, hidx, false); - ior->func->hda->hpd(ior, hidx, false); - } - - return 0; - } - break; case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: { union { struct nv50_disp_sor_dp_mst_link_v0 v0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index f82100b1a45d..052b2d14f47a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -26,6 +26,35 @@ #include +static int +nvkm_uoutp_mthd_hda_eld(struct nvkm_outp *outp, void *argv, u32 argc) +{ + struct nvkm_ior *ior = outp->ior; + union nvif_outp_hda_eld_args *args = argv; + + if (argc < sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + argc -= sizeof(args->v0); + + if (!ior->hda || !nvkm_head_find(outp->disp, args->v0.head)) + return -EINVAL; + if (argc > 0x60) + return -E2BIG; + + if (argc && args->v0.data[0]) { + if (outp->info.type == DCB_OUTPUT_DP) + ior->func->dp->audio(ior, args->v0.head, true); + ior->func->hda->hpd(ior, args->v0.head, true); + ior->func->hda->eld(ior, args->v0.head, args->v0.data, argc); + } else { + if (outp->info.type == DCB_OUTPUT_DP) + ior->func->dp->audio(ior, args->v0.head, false); + ior->func->hda->hpd(ior, args->v0.head, false); + } + + return 0; +} + static int nvkm_uoutp_mthd_infoframe(struct nvkm_outp *outp, void *argv, u32 argc) { @@ -184,6 +213,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc) switch (mthd) { case NVIF_OUTP_V0_RELEASE : return nvkm_uoutp_mthd_release (outp, argv, argc); case NVIF_OUTP_V0_INFOFRAME : return nvkm_uoutp_mthd_infoframe (outp, argv, argc); + case NVIF_OUTP_V0_HDA_ELD : return nvkm_uoutp_mthd_hda_eld (outp, argv, argc); default: break; } -- cgit v1.2.3 From 8134437213316a58d1844b87e2042ebf1fd9962c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:33 +1000 Subject: drm/nouveau/disp: move DP link config into acquire Aside from fixing MST->SST switching (KMS never turned off MST link config), this should preserve existing behaviour for the moment, but provide a path for the KMS driver to have more explicit control of the DP link, which has been requested by Lyude. More research into modeset/supervisor interactions is needed before we can have fully explicit control from the KMS driver. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 34 +++------------------- drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 7 ----- drivers/gpu/drm/nouveau/include/nvif/if0012.h | 6 +++- drivers/gpu/drm/nouveau/include/nvif/outp.h | 3 +- drivers/gpu/drm/nouveau/nvif/outp.c | 10 +++++-- drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 19 +++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 2 ++ .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 15 ---------- drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 29 ++++++++++++++++-- 9 files changed, 65 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index c61617acaf87..ca58c6b65339 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1014,7 +1014,7 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st if (!mstm->links++) { /*XXX: MST audio. */ - nvif_outp_acquire_dp(&mstm->outp->outp, false); + nvif_outp_acquire_dp(&mstm->outp->outp, mstm->outp->dp.dpcd, 0, 0, false, true); } if (mstm->outp->outp.or.link & 1) @@ -1380,26 +1380,6 @@ nv50_mstm_remove(struct nv50_mstm *mstm) drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); } -static int -nv50_mstm_enable(struct nv50_mstm *mstm, int state) -{ - struct nouveau_encoder *outp = mstm->outp; - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_dp_mst_link_v0 mst; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_LINK, - .base.hasht = outp->dcb->hasht, - .base.hashm = outp->dcb->hashm, - .mst.state = state, - }; - struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev); - struct nvif_object *disp = &drm->display->disp.object; - - return nvif_mthd(disp, 0, &args, sizeof(args)); -} - int nv50_mstm_detect(struct nouveau_encoder *outp) { @@ -1420,15 +1400,9 @@ nv50_mstm_detect(struct nouveau_encoder *outp) return ret; /* And start enabling */ - ret = nv50_mstm_enable(mstm, true); - if (ret) - return ret; - ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, true); - if (ret) { - nv50_mstm_enable(mstm, false); + if (ret) return ret; - } mstm->is_mst = true; return 1; @@ -1660,7 +1634,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta nvif_outp_acquire_lvds(&nv_encoder->outp, lvds_dual, lvds_8bpc); break; case DCB_OUTPUT_DP: - nvif_outp_acquire_dp(&nv_encoder->outp, hda); + nvif_outp_acquire_dp(&nv_encoder->outp, nv_encoder->dp.dpcd, 0, 0, hda, false); depth = nv50_dp_bpc_to_depth(asyh->or.bpc); if (nv_encoder->outp.or.link & 1) @@ -1858,7 +1832,7 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st break; case DCB_OUTPUT_DP: ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC); - nvif_outp_acquire_dp(&nv_encoder->outp, false); + nvif_outp_acquire_dp(&nv_encoder->outp, nv_encoder->dp.dpcd, 0, 0, false, false); break; default: BUG(); diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index a71317733748..15e30fbdc215 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -28,7 +28,6 @@ struct nv50_disp_scanoutpos_v0 { struct nv50_disp_mthd_v1 { __u8 version; -#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25 #define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26 __u8 method; __u16 hasht; @@ -36,12 +35,6 @@ struct nv50_disp_mthd_v1 { __u8 pad06[2]; }; -struct nv50_disp_sor_dp_mst_link_v0 { - __u8 version; - __u8 state; - __u8 pad02[6]; -}; - struct nv50_disp_sor_dp_mst_vcpi_v0 { __u8 version; __u8 pad01[1]; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index 938d384f5b1f..c67f03d52d8c 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -55,8 +55,12 @@ union nvif_outp_acquire_args { __u8 pad02[6]; } lvds; struct { + __u8 link_nr; /* 0 = highest possible. */ + __u8 link_bw; /* 0 = highest possible, DP BW code otherwise. */ __u8 hda; - __u8 pad01[7]; + __u8 mst; + __u8 pad04[4]; + __u8 dpcd[16]; } dp; }; } v0; diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index c8879d3428c8..88fd2b970304 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -21,7 +21,8 @@ int nvif_outp_acquire_rgb_crt(struct nvif_outp *); int nvif_outp_acquire_tmds(struct nvif_outp *, int head, bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda); int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8); -int nvif_outp_acquire_dp(struct nvif_outp *, bool hda); +int nvif_outp_acquire_dp(struct nvif_outp *, u8 dpcd[16], + int link_nr, int link_bw, bool hda, bool mst); void nvif_outp_release(struct nvif_outp *); int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size); int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size); diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 3a7c2d573e69..1ae5b19a8025 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -84,16 +84,22 @@ nvif_outp_acquire(struct nvif_outp *outp, u8 proto, struct nvif_outp_acquire_v0 } int -nvif_outp_acquire_dp(struct nvif_outp *outp, bool hda) +nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[16], + int link_nr, int link_bw, bool hda, bool mst) { struct nvif_outp_acquire_v0 args; int ret; + args.dp.link_nr = link_nr; + args.dp.link_bw = link_bw; args.dp.hda = hda; + args.dp.mst = mst; + memcpy(args.dp.dpcd, dpcd, sizeof(args.dp.dpcd)); ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DP, &args); NVIF_ERRON(ret, &outp->object, - "[ACQUIRE proto:DP hda:%d] or:%d link:%d", args.dp.hda, args.or, args.link); + "[ACQUIRE proto:DP link_nr:%d link_bw:%02x hda:%d mst:%d] or:%d link:%d", + args.dp.link_nr, args.dp.link_bw, args.dp.hda, args.dp.mst, args.or, args.link); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index c1b3206f27e6..f1887b58f472 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -287,7 +287,7 @@ nvkm_dp_train_links(struct nvkm_outp *outp, int rate) u8 sink[2], data; int ret; - OUTP_DBG(outp, "training %d x %d MB/s", ior->dp.nr, ior->dp.bw * 27); + OUTP_DBG(outp, "training %dx%02x", ior->dp.nr, ior->dp.bw); /* Intersect misc. capabilities of the OR and sink. */ if (disp->engine.subdev.device->chipset < 0x110) @@ -455,6 +455,21 @@ nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps) /* Link training. */ OUTP_DBG(outp, "training"); nvkm_dp_train_init(outp); + + /* Validate and train at configuration requested (if any) on ACQUIRE. */ + if (outp->dp.lt.nr) { + for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) { + for (rate = 0; nr == outp->dp.lt.nr && rate < outp->dp.rates; rate++) { + if (outp->dp.rate[rate].rate / 27000 == outp->dp.lt.bw) { + ior->dp.bw = outp->dp.rate[rate].rate / 27000; + ior->dp.nr = nr; + ret = nvkm_dp_train_links(outp, rate); + } + } + } + } + + /* Otherwise, loop through all valid link configurations that support the data rate. */ for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) { for (rate = 0; ret < 0 && rate < outp->dp.rates; rate++) { if (outp->dp.rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) { @@ -465,6 +480,8 @@ nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps) } } } + + /* Finish up. */ nvkm_dp_train_fini(outp); if (ret < 0) OUTP_ERR(outp, "training failed"); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index eb9cd1146825..d7c989e1cd01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -54,6 +54,8 @@ struct nvkm_outp { struct mutex mutex; struct { atomic_t done; + u8 nr; + u8 bw; bool mst; } lt; } dp; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index a5bb15b62a0c..2f42940367a0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -91,21 +91,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } switch (mthd * !!outp) { - case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: { - union { - struct nv50_disp_sor_dp_mst_link_v0 v0; - } *args = data; - int ret = -ENOSYS; - nvif_ioctl(object, "disp sor dp mst link size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "disp sor dp mst link vers %d state %d\n", - args->v0.version, args->v0.state); - outp->dp.lt.mst = !!args->v0.state; - return 0; - } else - return ret; - } - break; case NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI: { union { struct nv50_disp_sor_dp_mst_vcpi_v0 v0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index 052b2d14f47a..61d41b326f43 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -100,6 +100,23 @@ nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc) return 0; } +static int +nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[16], + u8 link_nr, u8 link_bw, bool hda, bool mst) +{ + int ret; + + ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, hda); + if (ret) + return ret; + + memcpy(outp->dp.dpcd, dpcd, sizeof(outp->dp.dpcd)); + outp->dp.lt.nr = link_nr; + outp->dp.lt.bw = link_bw; + outp->dp.lt.mst = mst; + return 0; +} + static int nvkm_uoutp_mthd_acquire_tmds(struct nvkm_outp *outp, u8 head, u8 hdmi, u8 hdmi_max_ac_packet, u8 hdmi_rekey, u8 hdmi_scdc, u8 hdmi_hda) @@ -152,6 +169,8 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) if (argc != sizeof(args->v0) || args->v0.version != 0) return -ENOSYS; + if (outp->ior) + return -EBUSY; switch (args->v0.proto) { case NVIF_OUTP_ACQUIRE_V0_RGB_CRT: @@ -165,12 +184,16 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc) args->v0.tmds.hdmi_scdc, args->v0.tmds.hdmi_hda); break; - case NVIF_OUTP_ACQUIRE_V0_DP: - ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, args->v0.dp.hda); - break; case NVIF_OUTP_ACQUIRE_V0_LVDS: ret = nvkm_uoutp_mthd_acquire_lvds(outp, args->v0.lvds.dual, args->v0.lvds.bpc8); break; + case NVIF_OUTP_ACQUIRE_V0_DP: + ret = nvkm_uoutp_mthd_acquire_dp(outp, args->v0.dp.dpcd, + args->v0.dp.link_nr, + args->v0.dp.link_bw, + args->v0.dp.hda != 0, + args->v0.dp.mst != 0); + break; default: ret = -EINVAL; break; -- cgit v1.2.3 From a62b749390630fd02525ed8abd29323319f9096e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:34 +1000 Subject: drm/nouveau/disp: add method to control DPAUX pad power This removes the need for NVKM to track DP HPD events, as the KMS driver follows them already, and has better information available. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/if0012.h | 9 +++ drivers/gpu/drm/nouveau/include/nvif/outp.h | 1 + drivers/gpu/drm/nouveau/nouveau_dp.c | 10 ++- drivers/gpu/drm/nouveau/nvif/outp.c | 14 ++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 90 +++++++++++------------- drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 15 ++++ 8 files changed, 93 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index c67f03d52d8c..d1583271f5d4 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -15,6 +15,7 @@ union nvif_outp_args { #define NVIF_OUTP_V0_RELEASE 0x02 #define NVIF_OUTP_V0_INFOFRAME 0x03 #define NVIF_OUTP_V0_HDA_ELD 0x04 +#define NVIF_OUTP_V0_DP_AUX_PWR 0x05 union nvif_outp_load_detect_args { struct nvif_outp_load_detect_v0 { @@ -91,4 +92,12 @@ union nvif_outp_hda_eld_args { __u8 data[]; } v0; }; + +union nvif_outp_dp_aux_pwr_args { + struct nvif_outp_dp_aux_pwr_v0 { + __u8 version; + __u8 state; + __u8 pad02[6]; + } v0; +}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index 88fd2b970304..1c960f6fdd7a 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -26,4 +26,5 @@ int nvif_outp_acquire_dp(struct nvif_outp *, u8 dpcd[16], void nvif_outp_release(struct nvif_outp *); int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size); int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size); +int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 20db8ea1a0ba..b7104e676eb2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -140,12 +140,17 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, * TODO: look into checking this before probing I2C to detect DVI/HDMI */ hpd = nvif_conn_hpd_status(&nv_connector->conn); - if (hpd == NVIF_CONN_HPD_STATUS_NOT_PRESENT) + if (hpd == NVIF_CONN_HPD_STATUS_NOT_PRESENT) { + nvif_outp_dp_aux_pwr(&nv_encoder->outp, false); goto out; + } + nvif_outp_dp_aux_pwr(&nv_encoder->outp, true); status = nouveau_dp_probe_dpcd(nv_connector, nv_encoder); - if (status == connector_status_disconnected) + if (status == connector_status_disconnected) { + nvif_outp_dp_aux_pwr(&nv_encoder->outp, false); goto out; + } /* If we're in MST mode, we're done here */ if (mstm && mstm->can_mst && mstm->is_mst) { @@ -193,6 +198,7 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, ret = NOUVEAU_DP_MST; goto out; } else if (ret != 0) { + nvif_outp_dp_aux_pwr(&nv_encoder->outp, false); goto out; } } diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 1ae5b19a8025..9bd9cc21a039 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -25,6 +25,20 @@ #include +int +nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable) +{ + struct nvif_outp_dp_aux_pwr_v0 args; + int ret; + + args.version = 0; + args.state = enable; + + ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_AUX_PWR, &args, sizeof(args)); + NVIF_ERRON(ret, &outp->object, "[DP_AUX_PWR state:%d]", args.state); + return ret; +} + int nvif_outp_hda_eld(struct nvif_outp *outp, int head, void *data, u32 size) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index f1887b58f472..92c9faecffae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -612,18 +612,38 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp) return outp->dp.rates != 0; } -static bool -nvkm_dp_enable(struct nvkm_outp *outp, bool enable) +void +nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) { + struct nvkm_gpio *gpio = outp->disp->engine.subdev.device->gpio; struct nvkm_i2c_aux *aux = outp->dp.aux; - if (enable) { - if (!outp->dp.present) { - OUTP_DBG(outp, "aux power -> always"); - nvkm_i2c_aux_monitor(aux, true); - outp->dp.present = true; + if (auxpwr && !outp->dp.aux_pwr) { + /* eDP panels need powering on by us (if the VBIOS doesn't default it + * to on) before doing any AUX channel transactions. LVDS panel power + * is handled by the SOR itself, and not required for LVDS DDC. + */ + if (outp->conn->info.type == DCB_CONNECTOR_eDP) { + int power = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); + if (power == 0) { + nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); + outp->dp.aux_pwr_pu = true; + } + + /* We delay here unconditionally, even if already powered, + * because some laptop panels having a significant resume + * delay before the panel begins responding. + * + * This is likely a bit of a hack, but no better idea for + * handling this at the moment. + */ + msleep(300); } + OUTP_DBG(outp, "aux power -> always"); + nvkm_i2c_aux_monitor(aux, true); + outp->dp.aux_pwr = true; + /* Detect any LTTPRs before reading DPCD receiver caps. */ if (!nvkm_rdaux(aux, DPCD_LTTPR_REV, outp->dp.lttpr, sizeof(outp->dp.lttpr)) && outp->dp.lttpr[0] >= 0x14 && outp->dp.lttpr[2]) { @@ -676,19 +696,24 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool enable) outp->dp.rates++; } } - - return true; } - } - - if (outp->dp.present) { + } else + if (!auxpwr && outp->dp.aux_pwr) { OUTP_DBG(outp, "aux power -> demand"); nvkm_i2c_aux_monitor(aux, false); - outp->dp.present = false; - } + outp->dp.aux_pwr = false; + atomic_set(&outp->dp.lt.done, 0); - atomic_set(&outp->dp.lt.done, 0); - return false; + /* Restore eDP panel GPIO to its prior state if we changed it, as + * it could potentially interfere with other outputs. + */ + if (outp->conn->info.type == DCB_CONNECTOR_eDP) { + if (outp->dp.aux_pwr_pu) { + nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 0); + outp->dp.aux_pwr_pu = false; + } + } + } } static int @@ -705,8 +730,6 @@ nvkm_dp_hpd(struct nvkm_notify *notify) if (atomic_read(&outp->dp.lt.done)) outp->func->acquire(outp); rep.mask |= NVIF_NOTIFY_CONN_V0_IRQ; - } else { - nvkm_dp_enable(outp, true); } if (line->mask & NVKM_I2C_UNPLUG) @@ -728,37 +751,8 @@ nvkm_dp_fini(struct nvkm_outp *outp) static void nvkm_dp_init(struct nvkm_outp *outp) { - struct nvkm_gpio *gpio = outp->disp->engine.subdev.device->gpio; - + nvkm_dp_enable(outp, outp->dp.enabled); nvkm_notify_put(&outp->conn->hpd); - - /* eDP panels need powering on by us (if the VBIOS doesn't default it - * to on) before doing any AUX channel transactions. LVDS panel power - * is handled by the SOR itself, and not required for LVDS DDC. - */ - if (outp->conn->info.type == DCB_CONNECTOR_eDP) { - int power = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); - if (power == 0) - nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); - - /* We delay here unconditionally, even if already powered, - * because some laptop panels having a significant resume - * delay before the panel begins responding. - * - * This is likely a bit of a hack, but no better idea for - * handling this at the moment. - */ - msleep(300); - - /* If the eDP panel can't be detected, we need to restore - * the panel power GPIO to avoid breaking another output. - */ - if (!nvkm_dp_enable(outp, true) && power == 0) - nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 0); - } else { - nvkm_dp_enable(outp, true); - } - nvkm_notify_get(&outp->dp.hpd); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h index 1d86baa6a424..9a6be43916bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h @@ -6,6 +6,7 @@ int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *, struct nvkm_outp **); void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *); +void nvkm_dp_enable(struct nvkm_outp *, bool auxpwr); /* DPCD Receiver Capabilities */ #define DPCD_RC00_DPCD_REV 0x00000 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index d7c989e1cd01..66def8ae3165 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -39,7 +39,9 @@ struct nvkm_outp { struct nvkm_i2c_aux *aux; struct nvkm_notify hpd; - bool present; + bool enabled; + bool aux_pwr; + bool aux_pwr_pu; u8 lttpr[6]; u8 lttprs; u8 dpcd[16]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index 61d41b326f43..3bfc3e39778e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -21,11 +21,25 @@ */ #define nvkm_uoutp(p) container_of((p), struct nvkm_outp, object) #include "outp.h" +#include "dp.h" #include "head.h" #include "ior.h" #include +static int +nvkm_uoutp_mthd_dp_aux_pwr(struct nvkm_outp *outp, void *argv, u32 argc) +{ + union nvif_outp_dp_aux_pwr_args *args = argv; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + outp->dp.enabled = !!args->v0.state; + nvkm_dp_enable(outp, outp->dp.enabled); + return 0; +} + static int nvkm_uoutp_mthd_hda_eld(struct nvkm_outp *outp, void *argv, u32 argc) { @@ -250,6 +264,7 @@ nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc switch (mthd) { case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, argv, argc); case NVIF_OUTP_V0_ACQUIRE : return nvkm_uoutp_mthd_acquire (outp, argv, argc); + case NVIF_OUTP_V0_DP_AUX_PWR : return nvkm_uoutp_mthd_dp_aux_pwr (outp, argv, argc); default: break; } -- cgit v1.2.3 From d62f8e982cb857f451a9055d8cc446b1212a6500 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:34 +1000 Subject: drm/nouveau/kms: switch hpd_lock from mutex to spinlock There's no good reason for this to be a mutex, and once the layers of workqueues have been untangled, nouveau_connector_hpd() can be called from IRQ context and won't be able to take a mutex. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nouveau_connector.c | 5 +++-- drivers/gpu/drm/nouveau/nouveau_display.c | 13 ++++++------- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 1991bbb1d05c..c2ff8e91d90d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1166,13 +1166,14 @@ nouveau_connector_hpd(struct drm_connector *connector) { struct nouveau_drm *drm = nouveau_drm(connector->dev); u32 mask = drm_connector_mask(connector); + unsigned long flags; - mutex_lock(&drm->hpd_lock); + spin_lock_irqsave(&drm->hpd_lock, flags); if (!(drm->hpd_pending & mask)) { drm->hpd_pending |= mask; schedule_work(&drm->hpd_work); } - mutex_unlock(&drm->hpd_lock); + spin_unlock_irqrestore(&drm->hpd_lock, flags); } static int diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 2e97186090c8..fb22ebed5424 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -456,9 +456,9 @@ nouveau_display_hpd_resume(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - mutex_lock(&drm->hpd_lock); + spin_lock_irq(&drm->hpd_lock); drm->hpd_pending = ~0; - mutex_unlock(&drm->hpd_lock); + spin_unlock_irq(&drm->hpd_lock); schedule_work(&drm->hpd_work); } @@ -475,10 +475,10 @@ nouveau_display_hpd_work(struct work_struct *work) pm_runtime_get_sync(dev->dev); - mutex_lock(&drm->hpd_lock); + spin_lock_irq(&drm->hpd_lock); pending = drm->hpd_pending; drm->hpd_pending = 0; - mutex_unlock(&drm->hpd_lock); + spin_unlock_irq(&drm->hpd_lock); /* Nothing to do, exit early without updating the last busy counter */ if (!pending) @@ -732,7 +732,7 @@ nouveau_display_create(struct drm_device *dev) } INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work); - mutex_init(&drm->hpd_lock); + spin_lock_init(&drm->hpd_lock); #ifdef CONFIG_ACPI drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy; register_acpi_notifier(&drm->acpi_nb); @@ -766,8 +766,7 @@ nouveau_display_destroy(struct drm_device *dev) nvif_disp_dtor(&disp->disp); - nouveau_drm(dev)->display = NULL; - mutex_destroy(&drm->hpd_lock); + drm->display = NULL; kfree(disp); } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 84df5ddae4d0..1a92c980cb73 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -201,7 +201,7 @@ struct nouveau_drm { struct nvbios vbios; struct nouveau_display *display; struct work_struct hpd_work; - struct mutex hpd_lock; + spinlock_t hpd_lock; u32 hpd_pending; struct work_struct fbcon_work; int fbcon_new_state; -- cgit v1.2.3 From 016dacb60e6d4b301c5941a0dedb49d337926832 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:34 +1000 Subject: drm/nouveau/kms: pass event mask to hpd handler Will be moving the DP link status check / re-train here so it's safe from racing with modeset routing changes. MST message handling etc. will remain where it is. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nouveau_connector.c | 11 +++++------ drivers/gpu/drm/nouveau/nouveau_connector.h | 3 ++- drivers/gpu/drm/nouveau/nouveau_display.c | 20 +++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_dp.c | 12 +++++------- 4 files changed, 29 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index c2ff8e91d90d..bbd17ee60853 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1162,14 +1162,15 @@ nouveau_connector_funcs_lvds = { }; void -nouveau_connector_hpd(struct drm_connector *connector) +nouveau_connector_hpd(struct nouveau_connector *nv_connector, u64 bits) { - struct nouveau_drm *drm = nouveau_drm(connector->dev); - u32 mask = drm_connector_mask(connector); + struct nouveau_drm *drm = nouveau_drm(nv_connector->base.dev); + u32 mask = drm_connector_mask(&nv_connector->base); unsigned long flags; spin_lock_irqsave(&drm->hpd_lock, flags); if (!(drm->hpd_pending & mask)) { + nv_connector->hpd_pending |= bits; drm->hpd_pending |= mask; schedule_work(&drm->hpd_work); } @@ -1185,15 +1186,13 @@ nouveau_connector_hotplug(struct nvif_notify *notify) struct drm_device *dev = connector->dev; struct nouveau_drm *drm = nouveau_drm(dev); const struct nvif_notify_conn_rep_v0 *rep = notify->data; - bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG); if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { nouveau_dp_irq(drm, nv_connector); return NVIF_NOTIFY_KEEP; } - NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", connector->name); - nouveau_connector_hpd(connector); + nouveau_connector_hpd(nv_connector, rep->mask); return NVIF_NOTIFY_KEEP; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index f4e17ff68bf9..1bbf8bf6ba44 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -124,6 +124,7 @@ struct nouveau_connector { u8 *dcb; struct nvif_conn conn; + u64 hpd_pending; struct nvif_notify hpd; struct drm_dp_aux aux; @@ -198,7 +199,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) struct drm_connector * nouveau_connector_create(struct drm_device *, const struct dcb_output *); -void nouveau_connector_hpd(struct drm_connector *connector); +void nouveau_connector_hpd(struct nouveau_connector *, u64 bits); extern int nouveau_tv_disable; extern int nouveau_ignorelid; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index fb22ebed5424..a21dc2a0f92b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -488,14 +488,28 @@ nouveau_display_hpd_work(struct work_struct *work) drm_connector_list_iter_begin(dev, &conn_iter); nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { + struct nouveau_connector *nv_connector = nouveau_connector(connector); enum drm_connector_status old_status = connector->status; - u64 old_epoch_counter = connector->epoch_counter; + u64 bits, old_epoch_counter = connector->epoch_counter; if (!(pending & drm_connector_mask(connector))) continue; - connector->status = drm_helper_probe_detect(connector, NULL, - false); + spin_lock_irq(&drm->hpd_lock); + bits = nv_connector->hpd_pending; + nv_connector->hpd_pending = 0; + spin_unlock_irq(&drm->hpd_lock); + + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] plug:%d unplug:%d irq:%d\n", + connector->base.id, connector->name, + !!(bits & NVIF_NOTIFY_CONN_V0_PLUG), + !!(bits & NVIF_NOTIFY_CONN_V0_UNPLUG), + !!(bits & NVIF_NOTIFY_CONN_V0_IRQ)); + + if (bits & NVIF_NOTIFY_CONN_V0_IRQ) + continue; + + connector->status = drm_helper_probe_detect(connector, NULL, false); if (old_epoch_counter == connector->epoch_counter) continue; diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index b7104e676eb2..d349dc24a003 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -29,8 +29,7 @@ #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include -#include +#include MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)"); static int nouveau_mst = 1; @@ -218,8 +217,8 @@ void nouveau_dp_irq(struct nouveau_drm *drm, struct drm_connector *connector = &nv_connector->base; struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP); struct nv50_mstm *mstm; + u64 hpd = 0; int ret; - bool send_hpd = false; if (!outp) return; @@ -231,14 +230,14 @@ void nouveau_dp_irq(struct nouveau_drm *drm, if (mstm && mstm->is_mst) { if (!nv50_mstm_service(drm, nv_connector, mstm)) - send_hpd = true; + hpd |= NVIF_NOTIFY_CONN_V0_UNPLUG; } else { drm_dp_cec_irq(&nv_connector->aux); if (nouveau_dp_has_sink_count(connector, outp)) { ret = drm_dp_read_sink_count(&nv_connector->aux); if (ret != outp->dp.sink_count) - send_hpd = true; + hpd |= NVIF_NOTIFY_CONN_V0_PLUG; if (ret >= 0) outp->dp.sink_count = ret; } @@ -246,8 +245,7 @@ void nouveau_dp_irq(struct nouveau_drm *drm, mutex_unlock(&outp->dp.hpd_irq_lock); - if (send_hpd) - nouveau_connector_hpd(connector); + nouveau_connector_hpd(nv_connector, NVIF_NOTIFY_CONN_V0_IRQ | hpd); } /* TODO: -- cgit v1.2.3 From 8bb30c882334c0fdbec9b604f09d2e9120b509ab Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:35 +1000 Subject: drm/nouveau/disp: add method to trigger DP link retrain This moves control of link retraining in response to HPD IRQ to the KMS driver's HPD IRQ handler. NVKM still handles checking link status for the moment, this can be moved to the KMS driver when it takes explicit control of link rate selection. v2: - skip source config on retrain (fixes some retrain failures) Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/if0012.h | 6 + drivers/gpu/drm/nouveau/include/nvif/outp.h | 1 + drivers/gpu/drm/nouveau/nouveau_display.c | 6 +- drivers/gpu/drm/nouveau/nouveau_dp.c | 11 ++ drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 + drivers/gpu/drm/nouveau/nvif/outp.c | 8 ++ drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 138 +++++++++++++---------- drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 15 +++ 8 files changed, 124 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index d1583271f5d4..0d2e9a949d98 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -16,6 +16,7 @@ union nvif_outp_args { #define NVIF_OUTP_V0_INFOFRAME 0x03 #define NVIF_OUTP_V0_HDA_ELD 0x04 #define NVIF_OUTP_V0_DP_AUX_PWR 0x05 +#define NVIF_OUTP_V0_DP_RETRAIN 0x06 union nvif_outp_load_detect_args { struct nvif_outp_load_detect_v0 { @@ -100,4 +101,9 @@ union nvif_outp_dp_aux_pwr_args { __u8 pad02[6]; } v0; }; + +union nvif_outp_dp_retrain_args { + struct nvif_outp_dp_retrain_vn { + } vn; +}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index 1c960f6fdd7a..ea3e0a936c8a 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -27,4 +27,5 @@ void nvif_outp_release(struct nvif_outp *); int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size); int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size); int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable); +int nvif_outp_dp_retrain(struct nvif_outp *); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index a21dc2a0f92b..965e1c62d497 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -506,8 +506,10 @@ nouveau_display_hpd_work(struct work_struct *work) !!(bits & NVIF_NOTIFY_CONN_V0_UNPLUG), !!(bits & NVIF_NOTIFY_CONN_V0_IRQ)); - if (bits & NVIF_NOTIFY_CONN_V0_IRQ) - continue; + if (bits & NVIF_NOTIFY_CONN_V0_IRQ) { + if (nouveau_dp_link_check(nv_connector)) + continue; + } connector->status = drm_helper_probe_detect(connector, NULL, false); if (old_epoch_counter == connector->epoch_counter) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index d349dc24a003..bde58d00fbf5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -211,6 +211,17 @@ out: return ret; } +bool +nouveau_dp_link_check(struct nouveau_connector *nv_connector) +{ + struct nouveau_encoder *nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP); + + if (!nv_encoder || nv_encoder->outp.or.id < 0) + return true; + + return nvif_outp_dp_retrain(&nv_encoder->outp) == 0; +} + void nouveau_dp_irq(struct nouveau_drm *drm, struct nouveau_connector *nv_connector) { diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index b6c51fc60d13..8524d211f4e1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -141,6 +141,7 @@ enum nouveau_dp_status { }; int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *); +bool nouveau_dp_link_check(struct nouveau_connector *); void nouveau_dp_irq(struct nouveau_drm *drm, struct nouveau_connector *nv_connector); enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 9bd9cc21a039..56b7c703b137 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -25,6 +25,14 @@ #include +int +nvif_outp_dp_retrain(struct nvif_outp *outp) +{ + int ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_RETRAIN, NULL, 0); + NVIF_ERRON(ret, &outp->object, "[DP_RETRAIN]"); + return ret; +} + int nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 92c9faecffae..730c3a6f3362 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -274,71 +274,18 @@ nvkm_dp_train_cr(struct lt_state *lt) } static int -nvkm_dp_train_links(struct nvkm_outp *outp, int rate) +nvkm_dp_train_link(struct nvkm_outp *outp, int rate) { struct nvkm_ior *ior = outp->ior; - struct nvkm_disp *disp = outp->disp; - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_bios *bios = subdev->device->bios; struct lt_state lt = { .outp = outp, + .pc2 = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED, }; - u32 lnkcmp; u8 sink[2], data; int ret; OUTP_DBG(outp, "training %dx%02x", ior->dp.nr, ior->dp.bw); - /* Intersect misc. capabilities of the OR and sink. */ - if (disp->engine.subdev.device->chipset < 0x110) - outp->dp.dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED; - if (disp->engine.subdev.device->chipset < 0xd0) - outp->dp.dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED; - lt.pc2 = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED; - - if (AMPERE_IED_HACK(disp) && (lnkcmp = lt.outp->dp.info.script[0])) { - /* Execute BeforeLinkTraining script from DP Info table. */ - while (ior->dp.bw < nvbios_rd08(bios, lnkcmp)) - lnkcmp += 3; - lnkcmp = nvbios_rd16(bios, lnkcmp + 1); - - nvbios_init(&outp->disp->engine.subdev, lnkcmp, - init.outp = &outp->info; - init.or = ior->id; - init.link = ior->asy.link; - ); - } - - /* Set desired link configuration on the source. */ - if ((lnkcmp = lt.outp->dp.info.lnkcmp)) { - if (outp->dp.version < 0x30) { - while ((ior->dp.bw * 2700) < nvbios_rd16(bios, lnkcmp)) - lnkcmp += 4; - lnkcmp = nvbios_rd16(bios, lnkcmp + 2); - } else { - while (ior->dp.bw < nvbios_rd08(bios, lnkcmp)) - lnkcmp += 3; - lnkcmp = nvbios_rd16(bios, lnkcmp + 1); - } - - nvbios_init(subdev, lnkcmp, - init.outp = &outp->info; - init.or = ior->id; - init.link = ior->asy.link; - ); - } - - ret = ior->func->dp->links(ior, outp->dp.aux); - if (ret) { - if (ret < 0) { - OUTP_ERR(outp, "train failed with %d", ret); - return ret; - } - return 0; - } - - ior->func->dp->power(ior, ior->dp.nr); - /* Select LTTPR non-transparent mode if we have a valid configuration, * use transparent mode otherwise. */ @@ -393,6 +340,71 @@ nvkm_dp_train_links(struct nvkm_outp *outp, int rate) return ret; } +static int +nvkm_dp_train_links(struct nvkm_outp *outp, int rate) +{ + struct nvkm_ior *ior = outp->ior; + struct nvkm_disp *disp = outp->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_bios *bios = subdev->device->bios; + u32 lnkcmp; + int ret; + + OUTP_DBG(outp, "programming link for %dx%02x", ior->dp.nr, ior->dp.bw); + + /* Intersect misc. capabilities of the OR and sink. */ + if (disp->engine.subdev.device->chipset < 0x110) + outp->dp.dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED; + if (disp->engine.subdev.device->chipset < 0xd0) + outp->dp.dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED; + + if (AMPERE_IED_HACK(disp) && (lnkcmp = outp->dp.info.script[0])) { + /* Execute BeforeLinkTraining script from DP Info table. */ + while (ior->dp.bw < nvbios_rd08(bios, lnkcmp)) + lnkcmp += 3; + lnkcmp = nvbios_rd16(bios, lnkcmp + 1); + + nvbios_init(&outp->disp->engine.subdev, lnkcmp, + init.outp = &outp->info; + init.or = ior->id; + init.link = ior->asy.link; + ); + } + + /* Set desired link configuration on the source. */ + if ((lnkcmp = outp->dp.info.lnkcmp)) { + if (outp->dp.version < 0x30) { + while ((ior->dp.bw * 2700) < nvbios_rd16(bios, lnkcmp)) + lnkcmp += 4; + lnkcmp = nvbios_rd16(bios, lnkcmp + 2); + } else { + while (ior->dp.bw < nvbios_rd08(bios, lnkcmp)) + lnkcmp += 3; + lnkcmp = nvbios_rd16(bios, lnkcmp + 1); + } + + nvbios_init(subdev, lnkcmp, + init.outp = &outp->info; + init.or = ior->id; + init.link = ior->asy.link; + ); + } + + ret = ior->func->dp->links(ior, outp->dp.aux); + if (ret) { + if (ret < 0) { + OUTP_ERR(outp, "train failed with %d", ret); + return ret; + } + return 0; + } + + ior->func->dp->power(ior, ior->dp.nr); + + /* Attempt to train the link in this configuration. */ + return nvkm_dp_train_link(outp, rate); +} + static void nvkm_dp_train_fini(struct nvkm_outp *outp) { @@ -439,6 +451,16 @@ nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps) int ret = -EINVAL, nr, rate; u8 pwr; + /* Retraining link? Skip source configuration, it can mess up the active modeset. */ + if (atomic_read(&outp->dp.lt.done)) { + for (rate = 0; rate < outp->dp.rates; rate++) { + if (outp->dp.rate[rate].rate == ior->dp.bw * 27000) + return nvkm_dp_train_link(outp, ret); + } + WARN_ON(1); + return -EINVAL; + } + /* Ensure sink is not in a low-power state. */ if (!nvkm_rdaux(outp->dp.aux, DPCD_SC00, &pwr, 1)) { if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) { @@ -726,12 +748,8 @@ nvkm_dp_hpd(struct nvkm_notify *notify) struct nvif_notify_conn_rep_v0 rep = {}; OUTP_DBG(outp, "HPD: %d", line->mask); - if (line->mask & NVKM_I2C_IRQ) { - if (atomic_read(&outp->dp.lt.done)) - outp->func->acquire(outp); + if (line->mask & NVKM_I2C_IRQ) rep.mask |= NVIF_NOTIFY_CONN_V0_IRQ; - } - if (line->mask & NVKM_I2C_UNPLUG) rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG; if (line->mask & NVKM_I2C_PLUG) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index 3bfc3e39778e..e12a31d428d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -27,6 +27,20 @@ #include +static int +nvkm_uoutp_mthd_dp_retrain(struct nvkm_outp *outp, void *argv, u32 argc) +{ + union nvif_outp_dp_retrain_args *args = argv; + + if (argc != sizeof(args->vn)) + return -ENOSYS; + + if (!atomic_read(&outp->dp.lt.done)) + return 0; + + return outp->func->acquire(outp); +} + static int nvkm_uoutp_mthd_dp_aux_pwr(struct nvkm_outp *outp, void *argv, u32 argc) { @@ -251,6 +265,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc) case NVIF_OUTP_V0_RELEASE : return nvkm_uoutp_mthd_release (outp, argv, argc); case NVIF_OUTP_V0_INFOFRAME : return nvkm_uoutp_mthd_infoframe (outp, argv, argc); case NVIF_OUTP_V0_HDA_ELD : return nvkm_uoutp_mthd_hda_eld (outp, argv, argc); + case NVIF_OUTP_V0_DP_RETRAIN : return nvkm_uoutp_mthd_dp_retrain (outp, argv, argc); default: break; } -- cgit v1.2.3 From 8c7d980da9ba3eb67a1b40fd4b33bcf49397084b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:35 +1000 Subject: drm/nouveau/disp: move DP MST payload config method Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 26 +++----------- drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 18 ---------- drivers/gpu/drm/nouveau/include/nvif/if0012.h | 12 +++++++ drivers/gpu/drm/nouveau/include/nvif/outp.h | 2 ++ drivers/gpu/drm/nouveau/nvif/outp.c | 21 ++++++++++++ .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 40 ---------------------- drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 17 +++++++++ 7 files changed, 57 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index ca58c6b65339..67087940e304 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -884,16 +884,6 @@ nv50_msto_prepare(struct drm_atomic_state *state, struct nv50_mstc *mstc = msto->mstc; struct nv50_mstm *mstm = mstc->mstm; struct drm_dp_mst_atomic_payload *payload; - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_dp_mst_vcpi_v0 vcpi; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI, - .base.hasht = mstm->outp->dcb->hasht, - .base.hashm = (0xf0ff & mstm->outp->dcb->hashm) | - (0x0100 << msto->head->base.index), - }; NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name); @@ -902,22 +892,16 @@ nv50_msto_prepare(struct drm_atomic_state *state, // TODO: Figure out if we want to do a better job of handling VCPI allocation failures here? if (msto->disabled) { drm_dp_remove_payload(mgr, mst_state, payload); + + nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0); } else { if (msto->enabled) drm_dp_add_payload_part1(mgr, mst_state, payload); - args.vcpi.start_slot = payload->vc_start_slot; - args.vcpi.num_slots = payload->time_slots; - args.vcpi.pbn = payload->pbn; - args.vcpi.aligned_pbn = payload->time_slots * mst_state->pbn_div; + nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, + payload->vc_start_slot, payload->time_slots, + payload->pbn, payload->time_slots * mst_state->pbn_div); } - - NV_ATOMIC(drm, "%s: %s: %02x %02x %04x %04x\n", - msto->encoder.name, msto->head->base.base.name, - args.vcpi.start_slot, args.vcpi.num_slots, - args.vcpi.pbn, args.vcpi.aligned_pbn); - - nvif_mthd(&drm->display->disp.object, 0, &args, sizeof(args)); } static int diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index 15e30fbdc215..75264c89af82 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -25,22 +25,4 @@ struct nv50_disp_scanoutpos_v0 { __u16 htotal; __u16 hline; }; - -struct nv50_disp_mthd_v1 { - __u8 version; -#define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26 - __u8 method; - __u16 hasht; - __u16 hashm; - __u8 pad06[2]; -}; - -struct nv50_disp_sor_dp_mst_vcpi_v0 { - __u8 version; - __u8 pad01[1]; - __u8 start_slot; - __u8 num_slots; - __u16 pbn; - __u16 aligned_pbn; -}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h index 0d2e9a949d98..eb99d84eb844 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -17,6 +17,7 @@ union nvif_outp_args { #define NVIF_OUTP_V0_HDA_ELD 0x04 #define NVIF_OUTP_V0_DP_AUX_PWR 0x05 #define NVIF_OUTP_V0_DP_RETRAIN 0x06 +#define NVIF_OUTP_V0_DP_MST_VCPI 0x07 union nvif_outp_load_detect_args { struct nvif_outp_load_detect_v0 { @@ -106,4 +107,15 @@ union nvif_outp_dp_retrain_args { struct nvif_outp_dp_retrain_vn { } vn; }; + +union nvif_outp_dp_mst_vcpi_args { + struct nvif_outp_dp_mst_vcpi_v0 { + __u8 version; + __u8 head; + __u8 start_slot; + __u8 num_slots; + __u16 pbn; + __u16 aligned_pbn; + } v0; +}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h index ea3e0a936c8a..45daadec3c0c 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/outp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -28,4 +28,6 @@ int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_ int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size); int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable); int nvif_outp_dp_retrain(struct nvif_outp *); +int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head, + u8 start_slot, u8 num_slots, u16 pbn, u16 aligned_pbn); #endif diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 56b7c703b137..7da39f1eae9f 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -25,6 +25,27 @@ #include +int +nvif_outp_dp_mst_vcpi(struct nvif_outp *outp, int head, + u8 start_slot, u8 num_slots, u16 pbn, u16 aligned_pbn) +{ + struct nvif_outp_dp_mst_vcpi_v0 args; + int ret; + + args.version = 0; + args.head = head; + args.start_slot = start_slot; + args.num_slots = num_slots; + args.pbn = pbn; + args.aligned_pbn = aligned_pbn; + + ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_MST_VCPI, &args, sizeof(args)); + NVIF_ERRON(ret, &outp->object, + "[DP_MST_VCPI head:%d start_slot:%02x num_slots:%02x pbn:%04x aligned_pbn:%04x]", + args.head, args.start_slot, args.num_slots, args.pbn, args.aligned_pbn); + return ret; +} + int nvif_outp_dp_retrain(struct nvif_outp *outp) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index 2f42940367a0..3226faff6f38 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -37,7 +37,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) { union { struct nv50_disp_mthd_v0 v0; - struct nv50_disp_mthd_v1 v1; } *args = data; struct nvkm_disp *disp = nvkm_udisp(object); struct nvkm_outp *temp, *outp = NULL; @@ -54,16 +53,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) args->v0.version, args->v0.method, args->v0.head); mthd = args->v0.method; hidx = args->v0.head; - } else - if (!(ret = nvif_unpack(ret, &data, &size, args->v1, 1, 1, true))) { - nvif_ioctl(object, "disp mthd vers %d mthd %02x " - "type %04x mask %04x\n", - args->v1.version, args->v1.method, - args->v1.hasht, args->v1.hashm); - mthd = args->v1.method; - type = args->v1.hasht; - mask = args->v1.hashm; - hidx = ffs((mask >> 8) & 0x0f) - 1; } else return ret; @@ -90,34 +79,5 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) break; } - switch (mthd * !!outp) { - case NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI: { - union { - struct nv50_disp_sor_dp_mst_vcpi_v0 v0; - } *args = data; - int ret = -ENOSYS; - nvif_ioctl(object, "disp sor dp mst vcpi size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "disp sor dp mst vcpi vers %d " - "slot %02x/%02x pbn %04x/%04x\n", - args->v0.version, args->v0.start_slot, - args->v0.num_slots, args->v0.pbn, - args->v0.aligned_pbn); - if (!outp->ior->func->dp->vcpi) - return -ENODEV; - outp->ior->func->dp->vcpi(outp->ior, hidx, - args->v0.start_slot, - args->v0.num_slots, - args->v0.pbn, - args->v0.aligned_pbn); - return 0; - } else - return ret; - } - break; - default: - break; - } - return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c index e12a31d428d6..d10ce1e04d32 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -27,6 +27,22 @@ #include +static int +nvkm_uoutp_mthd_dp_mst_vcpi(struct nvkm_outp *outp, void *argv, u32 argc) +{ + struct nvkm_ior *ior = outp->ior; + union nvif_outp_dp_mst_vcpi_args *args = argv; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + if (!ior->func->dp || !ior->func->dp->vcpi || !nvkm_head_find(outp->disp, args->v0.head)) + return -EINVAL; + + ior->func->dp->vcpi(ior, args->v0.head, args->v0.start_slot, args->v0.num_slots, + args->v0.pbn, args->v0.aligned_pbn); + return 0; +} + static int nvkm_uoutp_mthd_dp_retrain(struct nvkm_outp *outp, void *argv, u32 argc) { @@ -266,6 +282,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc) case NVIF_OUTP_V0_INFOFRAME : return nvkm_uoutp_mthd_infoframe (outp, argv, argc); case NVIF_OUTP_V0_HDA_ELD : return nvkm_uoutp_mthd_hda_eld (outp, argv, argc); case NVIF_OUTP_V0_DP_RETRAIN : return nvkm_uoutp_mthd_dp_retrain (outp, argv, argc); + case NVIF_OUTP_V0_DP_MST_VCPI: return nvkm_uoutp_mthd_dp_mst_vcpi(outp, argv, argc); default: break; } -- cgit v1.2.3 From a2b7eadfef5963138a5aeaba90c4f513414823c2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:36 +1000 Subject: drm/nouveau/disp: add head class v2: remove extra whitespace Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 5 ++ drivers/gpu/drm/nouveau/dispnv50/head.c | 5 ++ drivers/gpu/drm/nouveau/include/nvif/class.h | 1 + drivers/gpu/drm/nouveau/include/nvif/disp.h | 1 + drivers/gpu/drm/nouveau/include/nvif/head.h | 13 +++++ drivers/gpu/drm/nouveau/include/nvif/if0010.h | 1 + drivers/gpu/drm/nouveau/include/nvif/if0013.h | 12 +++++ drivers/gpu/drm/nouveau/nouveau_crtc.h | 3 +- drivers/gpu/drm/nouveau/nvif/Kbuild | 1 + drivers/gpu/drm/nouveau/nvif/disp.c | 5 +- drivers/gpu/drm/nouveau/nvif/head.c | 48 +++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h | 3 ++ drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c | 12 +++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c | 66 ++++++++++++++++++++++++ 16 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvif/head.h create mode 100644 drivers/gpu/drm/nouveau/include/nvif/if0013.h create mode 100644 drivers/gpu/drm/nouveau/nvif/head.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index ee92d576d277..f35c25607508 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -762,6 +762,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) nouveau_bo_unpin(nv_crtc->cursor.nvbo); nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); nvif_notify_dtor(&nv_crtc->vblank); + nvif_head_dtor(&nv_crtc->head); kfree(nv_crtc); } @@ -1341,6 +1342,10 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) nv04_cursor_init(nv_crtc); + ret = nvif_head_ctor(&disp->disp, nv_crtc->base.name, nv_crtc->index, &nv_crtc->head); + if (ret) + return ret; + ret = nvif_notify_ctor(&disp->disp.object, "kmsVbl", nv04_crtc_vblank_handler, false, NV04_DISP_NTFY_VBLANK, &(struct nvif_notify_head_req_v0) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index c3c57be54e1c..8ac3474111c5 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -518,6 +518,7 @@ nv50_head_destroy(struct drm_crtc *crtc) struct nv50_head *head = nv50_head(crtc); nvif_notify_dtor(&head->base.vblank); + nvif_head_dtor(&head->base.head); nv50_lut_fini(&head->olut); drm_crtc_cleanup(crtc); kfree(head); @@ -624,6 +625,10 @@ nv50_head_create(struct drm_device *dev, int index) } } + ret = nvif_head_ctor(disp->disp, head->base.base.name, head->base.index, &head->base.head); + if (ret) + return ERR_PTR(ret); + ret = nvif_notify_ctor(&disp->disp->object, "kmsVbl", nv50_head_vblank_handler, false, NV04_DISP_NTFY_VBLANK, &(struct nvif_notify_head_req_v0) { diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index 8641db649f48..03f0f7c299f2 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -35,6 +35,7 @@ #define NVIF_CLASS_DISP /* if0010.h */ 0x80000010 #define NVIF_CLASS_CONN /* if0011.h */ 0x80000011 #define NVIF_CLASS_OUTP /* if0012.h */ 0x80000012 +#define NVIF_CLASS_HEAD /* if0013.h */ 0x80000013 #define NVIF_CLASS_DISP_CHAN /* if0014.h */ 0x80000014 /* the below match nvidia-assigned (either in hw, or sw) class numbers */ diff --git a/drivers/gpu/drm/nouveau/include/nvif/disp.h b/drivers/gpu/drm/nouveau/include/nvif/disp.h index 742632ad3bea..56eb7293e01c 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/disp.h @@ -7,6 +7,7 @@ struct nvif_disp { struct nvif_object object; unsigned long conn_mask; unsigned long outp_mask; + unsigned long head_mask; }; int nvif_disp_ctor(struct nvif_device *, const char *name, s32 oclass, diff --git a/drivers/gpu/drm/nouveau/include/nvif/head.h b/drivers/gpu/drm/nouveau/include/nvif/head.h new file mode 100644 index 000000000000..09170c7bc0af --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/head.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_HEAD_H__ +#define __NVIF_HEAD_H__ +#include +struct nvif_disp; + +struct nvif_head { + struct nvif_object object; +}; + +int nvif_head_ctor(struct nvif_disp *, const char *name, int id, struct nvif_head *); +void nvif_head_dtor(struct nvif_head *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0010.h b/drivers/gpu/drm/nouveau/include/nvif/if0010.h index fc236ef28965..4c835bbe6fe3 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0010.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0010.h @@ -8,6 +8,7 @@ union nvif_disp_args { __u8 pad01[3]; __u32 conn_mask; __u32 outp_mask; + __u32 head_mask; } v0; }; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0013.h b/drivers/gpu/drm/nouveau/include/nvif/if0013.h new file mode 100644 index 000000000000..218ba6eeba7b --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0013.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0013_H__ +#define __NVIF_IF0013_H__ + +union nvif_head_args { + struct nvif_head_v0 { + __u8 version; + __u8 id; + __u8 pad02[6]; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h index 7f63be2ec35d..e85e74f9a28d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_crtc.h +++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -26,14 +26,15 @@ #ifndef __NOUVEAU_CRTC_H__ #define __NOUVEAU_CRTC_H__ - #include +#include #include struct nouveau_crtc { struct drm_crtc base; + struct nvif_head head; int index; struct nvif_notify vblank; diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild index 6abc4bc42e35..6281291c70dc 100644 --- a/drivers/gpu/drm/nouveau/nvif/Kbuild +++ b/drivers/gpu/drm/nouveau/nvif/Kbuild @@ -6,6 +6,7 @@ nvif-y += nvif/device.o nvif-y += nvif/disp.o nvif-y += nvif/driver.o nvif-y += nvif/fifo.o +nvif-y += nvif/head.o nvif-y += nvif/mem.o nvif-y += nvif/mmu.o nvif-y += nvif/notify.o diff --git a/drivers/gpu/drm/nouveau/nvif/disp.c b/drivers/gpu/drm/nouveau/nvif/disp.c index 926b0c04b1e8..09915f2715af 100644 --- a/drivers/gpu/drm/nouveau/nvif/disp.c +++ b/drivers/gpu/drm/nouveau/nvif/disp.c @@ -72,9 +72,10 @@ nvif_disp_ctor(struct nvif_device *device, const char *name, s32 oclass, struct if (ret) return ret; - NVIF_DEBUG(&disp->object, "[NEW] conn_mask:%08x outp_mask:%08x", - args.conn_mask, args.outp_mask); + NVIF_DEBUG(&disp->object, "[NEW] conn_mask:%08x outp_mask:%08x head_mask:%08x", + args.conn_mask, args.outp_mask, args.head_mask); disp->conn_mask = args.conn_mask; disp->outp_mask = args.outp_mask; + disp->head_mask = args.head_mask; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvif/head.c b/drivers/gpu/drm/nouveau/nvif/head.c new file mode 100644 index 000000000000..01deba462600 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvif/head.c @@ -0,0 +1,48 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include +#include + +#include +#include + +void +nvif_head_dtor(struct nvif_head *head) +{ + nvif_object_dtor(&head->object); +} + +int +nvif_head_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_head *head) +{ + struct nvif_head_v0 args; + int ret; + + args.version = 0; + args.id = id; + + ret = nvif_object_ctor(&disp->object, name ? name : "nvifHead", id, NVIF_CLASS_HEAD, + &args, sizeof(args), &head->object); + NVIF_ERRON(ret, &disp->object, "[NEW head id:%d]", args.id); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index 600072a904be..e403040658b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -34,3 +34,4 @@ nvkm-y += nvkm/engine/disp/rootnv50.o nvkm-y += nvkm/engine/disp/udisp.o nvkm-y += nvkm/engine/disp/uconn.o nvkm-y += nvkm/engine/disp/uoutp.o +nvkm-y += nvkm/engine/disp/uhead.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h index 84a2989193cf..d95d4b591b2e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_HEAD_H__ #define __NVKM_DISP_HEAD_H__ +#include #include "priv.h" struct nvkm_head { @@ -26,6 +27,8 @@ struct nvkm_head { u8 depth; } or; } arm, asy; + + struct nvkm_object object; }; int nvkm_head_new_(const struct nvkm_head_func *, struct nvkm_disp *, int id); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index cb25dfe849f0..9e89615c4f67 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -86,4 +86,5 @@ extern const struct nvkm_event_func gv100_disp_chan_uevent; int nvkm_udisp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); int nvkm_uconn_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); int nvkm_uoutp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_uhead_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c index 0841e7ce0343..93a0b816b33b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c @@ -21,6 +21,7 @@ */ #include "priv.h" #include "conn.h" +#include "head.h" #include "outp.h" #include @@ -43,6 +44,12 @@ nvkm_udisp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *scl return 0; } + if (index-- == 0) { + sclass->base = (struct nvkm_sclass) { 0, 0, NVIF_CLASS_HEAD }; + sclass->ctor = nvkm_uhead_new; + return 0; + } + if (disp->func->user[index].ctor) { sclass->base = disp->func->user[index].base; sclass->ctor = disp->func->user[index].ctor; @@ -89,6 +96,7 @@ nvkm_udisp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv struct nvkm_disp *disp = nvkm_disp(oclass->engine); struct nvkm_conn *conn; struct nvkm_outp *outp; + struct nvkm_head *head; union nvif_disp_args *args = argv; if (argc != sizeof(args->v0) || args->v0.version != 0) @@ -111,5 +119,9 @@ nvkm_udisp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv list_for_each_entry(outp, &disp->outps, head) args->v0.outp_mask |= BIT(outp->index); + args->v0.head_mask = 0; + list_for_each_entry(head, &disp->heads, head) + args->v0.head_mask |= BIT(head->id); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c new file mode 100644 index 000000000000..a58f4b5fcd01 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c @@ -0,0 +1,66 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#define nvkm_uhead(p) container_of((p), struct nvkm_head, object) +#include "head.h" + +#include + +static void * +nvkm_uhead_dtor(struct nvkm_object *object) +{ + struct nvkm_head *head = nvkm_uhead(object); + struct nvkm_disp *disp = head->disp; + + spin_lock(&disp->client.lock); + head->object.func = NULL; + spin_unlock(&disp->client.lock); + return NULL; +} + +static const struct nvkm_object_func +nvkm_uhead = { + .dtor = nvkm_uhead_dtor, +}; + +int +nvkm_uhead_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + struct nvkm_head *head; + union nvif_head_args *args = argv; + int ret; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + if (!(head = nvkm_head_find(disp, args->v0.id))) + return -EINVAL; + + ret = -EBUSY; + spin_lock(&disp->client.lock); + if (!head->object.func) { + nvkm_object_ctor(&nvkm_uhead, oclass, &head->object); + *pobject = &head->object; + ret = 0; + } + spin_unlock(&disp->client.lock); + return ret; +} -- cgit v1.2.3 From 361863ceab1eaa171a304bda84636f2ff0a1d820 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:36 +1000 Subject: drm/nouveau/disp: move head scanoutpos method Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 1 - drivers/gpu/drm/nouveau/include/nvif/cl0046.h | 22 ------ drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 28 -------- drivers/gpu/drm/nouveau/include/nvif/if0013.h | 18 +++++ drivers/gpu/drm/nouveau/nouveau_display.c | 27 +++---- drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild | 3 - drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c | 38 ---------- drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h | 2 - .../gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c | 62 ---------------- .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 83 ---------------------- drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c | 12 ---- drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c | 42 +++++++++++ 13 files changed, 71 insertions(+), 269 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/cl5070.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 67087940e304..e720c01841b2 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h index d490d401870a..b3ac930b01fa 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h @@ -4,26 +4,4 @@ #define NV04_DISP_NTFY_VBLANK 0x00 #define NV04_DISP_NTFY_CONN 0x01 - -struct nv04_disp_mthd_v0 { - __u8 version; -#define NV04_DISP_SCANOUTPOS 0x00 - __u8 method; - __u8 head; - __u8 pad03[5]; -}; - -struct nv04_disp_scanoutpos_v0 { - __u8 version; - __u8 pad01[7]; - __s64 time[2]; - __u16 vblanks; - __u16 vblanke; - __u16 vtotal; - __u16 vline; - __u16 hblanks; - __u16 hblanke; - __u16 htotal; - __u16 hline; -}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h deleted file mode 100644 index 75264c89af82..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL5070_H__ -#define __NVIF_CL5070_H__ - -#define NV50_DISP_MTHD 0x00 - -struct nv50_disp_mthd_v0 { - __u8 version; -#define NV50_DISP_SCANOUTPOS 0x00 - __u8 method; - __u8 head; - __u8 pad03[5]; -}; - -struct nv50_disp_scanoutpos_v0 { - __u8 version; - __u8 pad01[7]; - __s64 time[2]; - __u16 vblanks; - __u16 vblanke; - __u16 vtotal; - __u16 vline; - __u16 hblanks; - __u16 hblanke; - __u16 htotal; - __u16 hline; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0013.h b/drivers/gpu/drm/nouveau/include/nvif/if0013.h index 218ba6eeba7b..4bd9507a200b 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0013.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0013.h @@ -9,4 +9,22 @@ union nvif_head_args { __u8 pad02[6]; } v0; }; + +#define NVIF_HEAD_V0_SCANOUTPOS 0x00 + +union nvif_head_scanoutpos_args { + struct nvif_head_scanoutpos_v0 { + __u8 version; + __u8 pad01[7]; + __s64 time[2]; + __u16 vblanks; + __u16 vblanke; + __u16 vtotal; + __u16 vline; + __u16 hblanks; + __u16 hblanke; + __u16 htotal; + __u16 hline; + } v0; +}; #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 965e1c62d497..2034346f3934 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -42,7 +42,7 @@ #include "nv50_display.h" #include -#include +#include #include #include @@ -84,24 +84,20 @@ static bool nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) { - struct { - struct nv04_disp_mthd_v0 base; - struct nv04_disp_scanoutpos_v0 scan; - } args = { - .base.method = NV04_DISP_SCANOUTPOS, - .base.head = nouveau_crtc(crtc)->index, - }; - struct nouveau_display *disp = nouveau_display(crtc->dev); struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; + struct nvif_head *head = &nouveau_crtc(crtc)->head; + struct nvif_head_scanoutpos_v0 args; int retry = 20; bool ret = false; + args.version = 0; + do { - ret = nvif_mthd(&disp->disp.object, 0, &args, sizeof(args)); + ret = nvif_mthd(&head->object, NVIF_HEAD_V0_SCANOUTPOS, &args, sizeof(args)); if (ret != 0) return false; - if (args.scan.vline) { + if (args.vline) { ret = true; break; } @@ -109,11 +105,10 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, if (retry) ndelay(vblank->linedur_ns); } while (retry--); - *hpos = args.scan.hline; - *vpos = calc(args.scan.vblanks, args.scan.vblanke, - args.scan.vtotal, args.scan.vline); - if (stime) *stime = ns_to_ktime(args.scan.time[0]); - if (etime) *etime = ns_to_ktime(args.scan.time[1]); + *hpos = args.hline; + *vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline); + if (stime) *stime = ns_to_ktime(args.time[0]); + if (etime) *etime = ns_to_ktime(args.time[1]); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index e403040658b6..e1aecd3fe96c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -28,9 +28,6 @@ nvkm-y += nvkm/engine/disp/gv100.o nvkm-y += nvkm/engine/disp/tu102.o nvkm-y += nvkm/engine/disp/ga102.o -nvkm-y += nvkm/engine/disp/rootnv04.o -nvkm-y += nvkm/engine/disp/rootnv50.o - nvkm-y += nvkm/engine/disp/udisp.o nvkm-y += nvkm/engine/disp/uconn.o nvkm-y += nvkm/engine/disp/uoutp.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c index 83152c26fe3e..7f5d13d13c94 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c @@ -39,44 +39,6 @@ nvkm_head_find(struct nvkm_disp *disp, int id) return NULL; } -int -nvkm_head_mthd_scanoutpos(struct nvkm_object *object, - struct nvkm_head *head, void *data, u32 size) -{ - union { - struct nv04_disp_scanoutpos_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(object, "head scanoutpos size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "head scanoutpos vers %d\n", - args->v0.version); - - head->func->state(head, &head->arm); - args->v0.vtotal = head->arm.vtotal; - args->v0.vblanks = head->arm.vblanks; - args->v0.vblanke = head->arm.vblanke; - args->v0.htotal = head->arm.htotal; - args->v0.hblanks = head->arm.hblanks; - args->v0.hblanke = head->arm.hblanke; - - /* We don't support reading htotal/vtotal on pre-NV50 VGA, - * so we have to give up and trigger the timestamping - * fallback in the drm core. - */ - if (!args->v0.vtotal || !args->v0.htotal) - return -ENOTSUPP; - - args->v0.time[0] = ktime_to_ns(ktime_get()); - head->func->rgpos(head, &args->v0.hline, &args->v0.vline); - args->v0.time[1] = ktime_to_ns(ktime_get()); - } else - return ret; - - return 0; -} - void nvkm_head_del(struct nvkm_head **phead) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h index d95d4b591b2e..856252bf559a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -33,8 +33,6 @@ struct nvkm_head { int nvkm_head_new_(const struct nvkm_head_func *, struct nvkm_disp *, int id); void nvkm_head_del(struct nvkm_head **); -int nvkm_head_mthd_scanoutpos(struct nvkm_object *, - struct nvkm_head *, void *, u32); struct nvkm_head *nvkm_head_find(struct nvkm_disp *, int id); struct nvkm_head_func { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index 9e89615c4f67..a98b57f82fe7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -43,8 +43,6 @@ struct nvkm_disp_func { }; int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **); -int nv04_disp_mthd(struct nvkm_object *, u32, void *, u32); -int nv50_disp_root_mthd_(struct nvkm_object *, u32, void *, u32); int nv50_disp_oneinit(struct nvkm_disp *); int nv50_disp_init(struct nvkm_disp *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c deleted file mode 100644 index 9acaec5c271e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "priv.h" -#include "head.h" - -#include - -#include -#include - -int -nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) -{ - struct nvkm_disp *disp = nvkm_disp(object->engine); - union { - struct nv04_disp_mthd_v0 v0; - } *args = data; - struct nvkm_head *head; - int id, ret = -ENOSYS; - - nvif_ioctl(object, "disp mthd size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", - args->v0.version, args->v0.method, args->v0.head); - mthd = args->v0.method; - id = args->v0.head; - } else - return ret; - - if (!(head = nvkm_head_find(disp, id))) - return -ENXIO; - - switch (mthd) { - case NV04_DISP_SCANOUTPOS: - return nvkm_head_mthd_scanoutpos(object, head, data, size); - default: - break; - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c deleted file mode 100644 index 3226faff6f38..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "chan.h" -#include "head.h" -#include "ior.h" -#include "outp.h" - -#include - -#include -#include -#include - -int -nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) -{ - union { - struct nv50_disp_mthd_v0 v0; - } *args = data; - struct nvkm_disp *disp = nvkm_udisp(object); - struct nvkm_outp *temp, *outp = NULL; - struct nvkm_head *head; - u16 type, mask = 0; - int hidx, ret = -ENOSYS; - - if (mthd != NV50_DISP_MTHD) - return -EINVAL; - - nvif_ioctl(object, "disp mthd size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", - args->v0.version, args->v0.method, args->v0.head); - mthd = args->v0.method; - hidx = args->v0.head; - } else - return ret; - - if (!(head = nvkm_head_find(disp, hidx))) - return -ENXIO; - - if (mask) { - list_for_each_entry(temp, &disp->outps, head) { - if ((temp->info.hasht == type) && - (temp->info.hashm & mask) == mask) { - outp = temp; - break; - } - } - if (outp == NULL) - return -ENXIO; - } - - switch (mthd) { - case NV50_DISP_SCANOUTPOS: { - return nvkm_head_mthd_scanoutpos(object, head, data, size); - } - default: - break; - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c index 93a0b816b33b..c9bd32220fe1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c @@ -59,17 +59,6 @@ nvkm_udisp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *scl return -EINVAL; } -static int -nvkm_udisp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) -{ - struct nvkm_disp *disp = nvkm_udisp(object); - - if (disp->engine.subdev.device->card_type >= NV_50) - return nv50_disp_root_mthd_(object, mthd, argv, argc); - - return nv04_disp_mthd(object, mthd, argv, argc); -} - static void * nvkm_udisp_dtor(struct nvkm_object *object) { @@ -85,7 +74,6 @@ nvkm_udisp_dtor(struct nvkm_object *object) static const struct nvkm_object_func nvkm_udisp = { .dtor = nvkm_udisp_dtor, - .mthd = nvkm_udisp_mthd, .ntfy = nvkm_disp_ntfy, .sclass = nvkm_udisp_sclass, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c index a58f4b5fcd01..5f3c4b7dbb75 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c @@ -24,6 +24,47 @@ #include +static int +nvkm_uhead_mthd_scanoutpos(struct nvkm_head *head, void *argv, u32 argc) +{ + union nvif_head_scanoutpos_args *args = argv; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + head->func->state(head, &head->arm); + args->v0.vtotal = head->arm.vtotal; + args->v0.vblanks = head->arm.vblanks; + args->v0.vblanke = head->arm.vblanke; + args->v0.htotal = head->arm.htotal; + args->v0.hblanks = head->arm.hblanks; + args->v0.hblanke = head->arm.hblanke; + + /* We don't support reading htotal/vtotal on pre-NV50 VGA, + * so we have to give up and trigger the timestamping + * fallback in the drm core. + */ + if (!args->v0.vtotal || !args->v0.htotal) + return -ENOTSUPP; + + args->v0.time[0] = ktime_to_ns(ktime_get()); + head->func->rgpos(head, &args->v0.hline, &args->v0.vline); + args->v0.time[1] = ktime_to_ns(ktime_get()); + return 0; +} + +static int +nvkm_uhead_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_head *head = nvkm_uhead(object); + + switch (mthd) { + case NVIF_HEAD_V0_SCANOUTPOS: return nvkm_uhead_mthd_scanoutpos(head, argv, argc); + default: + return -EINVAL; + } +} + static void * nvkm_uhead_dtor(struct nvkm_object *object) { @@ -39,6 +80,7 @@ nvkm_uhead_dtor(struct nvkm_object *object) static const struct nvkm_object_func nvkm_uhead = { .dtor = nvkm_uhead_dtor, + .mthd = nvkm_uhead_mthd, }; int -- cgit v1.2.3 From f43e47c090dc7fe32d5410d8740c3a004eb2676f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:36 +1000 Subject: drm/nouveau/nvkm: add a replacement for nvkm_notify This replaces the twisty, confusing, relationship between nvkm_event and nvkm_notify with something much simpler, and less racey. It also places events in the object tree hierarchy, which will allow a heap of the code tracking events across allocation/teardown/suspend to be removed. This commit just adds the new interfaces, and passes the owning subdev to the event constructor to enable debug-tracing in the new code. v2: - use ?: (lyude) Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/class.h | 2 + drivers/gpu/drm/nouveau/include/nvif/event.h | 32 +++++ drivers/gpu/drm/nouveau/include/nvif/if000e.h | 26 ++++ drivers/gpu/drm/nouveau/include/nvkm/core/client.h | 2 + drivers/gpu/drm/nouveau/include/nvkm/core/event.h | 38 ++++- drivers/gpu/drm/nouveau/include/nvkm/core/object.h | 2 + drivers/gpu/drm/nouveau/nouveau_nvif.c | 15 +- drivers/gpu/drm/nouveau/nvif/Kbuild | 1 + drivers/gpu/drm/nouveau/nvif/event.c | 81 +++++++++++ drivers/gpu/drm/nouveau/nvkm/core/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/core/client.c | 5 +- drivers/gpu/drm/nouveau/nvkm/core/event.c | 149 ++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/core/ioctl.c | 27 +++- drivers/gpu/drm/nouveau/nvkm/core/oproxy.c | 13 ++ drivers/gpu/drm/nouveau/nvkm/core/uevent.c | 157 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c | 11 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c | 3 +- drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c | 3 +- drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c | 2 +- 21 files changed, 547 insertions(+), 29 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvif/if000e.h create mode 100644 drivers/gpu/drm/nouveau/nvif/event.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/core/uevent.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index 03f0f7c299f2..29448f77069b 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -32,6 +32,8 @@ #define NVIF_CLASS_VMM_GM200 /* ifb00d.h */ 0x8000b00d #define NVIF_CLASS_VMM_GP100 /* ifc00d.h */ 0x8000c00d +#define NVIF_CLASS_EVENT /* if000e.h */ 0x8000000e + #define NVIF_CLASS_DISP /* if0010.h */ 0x80000010 #define NVIF_CLASS_CONN /* if0011.h */ 0x80000011 #define NVIF_CLASS_OUTP /* if0012.h */ 0x80000012 diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h index a6b1ee4f10ca..a510ba4ad487 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/event.h +++ b/drivers/gpu/drm/nouveau/include/nvif/event.h @@ -1,6 +1,38 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVIF_EVENT_H__ #define __NVIF_EVENT_H__ +#include +#include +struct nvif_event; + +#define NVIF_EVENT_KEEP 0 +#define NVIF_EVENT_DROP 1 +typedef int (*nvif_event_func)(struct nvif_event *, void *repv, u32 repc); + +struct nvif_event { + struct nvif_object object; + nvif_event_func func; +}; + +static inline bool +nvif_event_constructed(struct nvif_event *event) +{ + return nvif_object_constructed(&event->object); +} + +int nvif_event_ctor_(struct nvif_object *, const char *, u32, nvif_event_func, bool, + struct nvif_event_v0 *, u32, bool, struct nvif_event *); + +static inline int +nvif_event_ctor(struct nvif_object *parent, const char *name, u32 handle, nvif_event_func func, + bool wait, struct nvif_event_v0 *args, u32 argc, struct nvif_event *event) +{ + return nvif_event_ctor_(parent, name, handle, func, wait, args, argc, true, event); +} + +void nvif_event_dtor(struct nvif_event *); +int nvif_event_allow(struct nvif_event *); +int nvif_event_block(struct nvif_event *); struct nvif_notify_req_v0 { __u8 version; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000e.h b/drivers/gpu/drm/nouveau/include/nvif/if000e.h new file mode 100644 index 000000000000..90a936cb1766 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if000e.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF000E_H__ +#define __NVIF_IF000E_H__ + +union nvif_event_args { + struct nvif_event_v0 { + __u8 version; + __u8 wait; + __u8 pad02[6]; + __u8 data[]; + } v0; +}; + +#define NVIF_EVENT_V0_ALLOW 0x00 +#define NVIF_EVENT_V0_BLOCK 0x01 + +union nvif_event_allow_args { + struct nvif_event_allow_vn { + } vn; +}; + +union nvif_event_block_args { + struct nvif_event_block_vn { + } vn; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index 2f86606e708c..2eb22aaed700 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -15,6 +15,7 @@ struct nvkm_client { void *data; int (*ntfy)(const void *, u32, const void *, u32); + int (*event)(u64 token, void *argv, u32 argc); struct list_head umem; spinlock_t lock; @@ -23,6 +24,7 @@ struct nvkm_client { int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg, int (*)(const void *, u32, const void *, u32), + int (*)(u64, void *, u32), struct nvkm_client **); struct nvkm_client *nvkm_client_search(struct nvkm_client *, u64 handle); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h index a7a413f07a78..d6755a89f587 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h @@ -4,9 +4,12 @@ #include struct nvkm_notify; struct nvkm_object; +struct nvkm_oclass; +struct nvkm_uevent; struct nvkm_event { const struct nvkm_event_func *func; + struct nvkm_subdev *subdev; int types_nr; int index_nr; @@ -15,6 +18,8 @@ struct nvkm_event { spinlock_t list_lock; struct list_head list; int *refs; + + struct list_head ntfy; }; struct nvkm_event_func { @@ -25,11 +30,42 @@ struct nvkm_event_func { void (*fini)(struct nvkm_event *, int type, int index); }; -int nvkm_event_init(const struct nvkm_event_func *func, int types_nr, +int nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr, int index_nr, struct nvkm_event *); void nvkm_event_fini(struct nvkm_event *); void nvkm_event_get(struct nvkm_event *, u32 types, int index); void nvkm_event_put(struct nvkm_event *, u32 types, int index); void nvkm_event_send(struct nvkm_event *, u32 types, int index, void *data, u32 size); + +#define NVKM_EVENT_KEEP 0 +#define NVKM_EVENT_DROP 1 +struct nvkm_event_ntfy; +typedef int (*nvkm_event_func)(struct nvkm_event_ntfy *, u32 bits); + +struct nvkm_event_ntfy { + struct nvkm_event *event; + int id; + u32 bits; + bool wait; + nvkm_event_func func; + + atomic_t allowed; + bool running; + + struct list_head head; +}; + +void nvkm_event_ntfy(struct nvkm_event *, int id, u32 bits); +bool nvkm_event_ntfy_valid(struct nvkm_event *, int id, u32 bits); +void nvkm_event_ntfy_add(struct nvkm_event *, int id, u32 bits, bool wait, nvkm_event_func, + struct nvkm_event_ntfy *); +void nvkm_event_ntfy_del(struct nvkm_event_ntfy *); +void nvkm_event_ntfy_allow(struct nvkm_event_ntfy *); +void nvkm_event_ntfy_block(struct nvkm_event_ntfy *); + +typedef int (*nvkm_uevent_func)(struct nvkm_object *, u64 token, u32 bits); + +int nvkm_uevent_new(const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **); +int nvkm_uevent_add(struct nvkm_uevent *, struct nvkm_event *, int id, u32 bits, nvkm_uevent_func); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h index 7efcd5d2f2ff..ed1f66360782 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h @@ -4,6 +4,7 @@ #include struct nvkm_event; struct nvkm_gpuobj; +struct nvkm_uevent; struct nvkm_object { const struct nvkm_object_func *func; @@ -43,6 +44,7 @@ struct nvkm_object_func { int (*bind)(struct nvkm_object *, struct nvkm_gpuobj *, int align, struct nvkm_gpuobj **); int (*sclass)(struct nvkm_object *, int index, struct nvkm_oclass *); + int (*uevent)(struct nvkm_object *, void *argv, u32 argc, struct nvkm_uevent *); }; void nvkm_object_ctor(const struct nvkm_object_func *, diff --git a/drivers/gpu/drm/nouveau/nouveau_nvif.c b/drivers/gpu/drm/nouveau/nouveau_nvif.c index df0fe58ca3ab..be6d404a3459 100644 --- a/drivers/gpu/drm/nouveau/nouveau_nvif.c +++ b/drivers/gpu/drm/nouveau/nouveau_nvif.c @@ -71,11 +71,24 @@ nvkm_client_suspend(void *priv) return nvkm_object_fini(&client->object, true); } +static int +nvkm_client_event(u64 token, void *repv, u32 repc) +{ + struct nvif_object *object = (void *)(unsigned long)token; + struct nvif_event *event = container_of(object, typeof(*event), object); + + if (event->func(event, repv, repc) == NVIF_EVENT_KEEP) + return NVKM_EVENT_KEEP; + + return NVKM_EVENT_DROP; +} + static int nvkm_client_driver_init(const char *name, u64 device, const char *cfg, const char *dbg, void **ppriv) { - return nvkm_client_new(name, device, cfg, dbg, nvif_notify, (struct nvkm_client **)ppriv); + return nvkm_client_new(name, device, cfg, dbg, nvif_notify, nvkm_client_event, + (struct nvkm_client **)ppriv); } const struct nvif_driver diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild index 6281291c70dc..7ce040ca2394 100644 --- a/drivers/gpu/drm/nouveau/nvif/Kbuild +++ b/drivers/gpu/drm/nouveau/nvif/Kbuild @@ -5,6 +5,7 @@ nvif-y += nvif/conn.o nvif-y += nvif/device.o nvif-y += nvif/disp.o nvif-y += nvif/driver.o +nvif-y += nvif/event.o nvif-y += nvif/fifo.o nvif-y += nvif/head.o nvif-y += nvif/mem.o diff --git a/drivers/gpu/drm/nouveau/nvif/event.c b/drivers/gpu/drm/nouveau/nvif/event.c new file mode 100644 index 000000000000..61ff4d6eba9f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvif/event.c @@ -0,0 +1,81 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include + +#include +#include + +int +nvif_event_block(struct nvif_event *event) +{ + if (nvif_event_constructed(event)) { + int ret = nvif_mthd(&event->object, NVIF_EVENT_V0_BLOCK, NULL, 0); + NVIF_ERRON(ret, &event->object, "[BLOCK]"); + return ret; + } + return 0; +} + +int +nvif_event_allow(struct nvif_event *event) +{ + if (nvif_event_constructed(event)) { + int ret = nvif_mthd(&event->object, NVIF_EVENT_V0_ALLOW, NULL, 0); + NVIF_ERRON(ret, &event->object, "[ALLOW]"); + return ret; + } + return 0; +} + +void +nvif_event_dtor(struct nvif_event *event) +{ + nvif_object_dtor(&event->object); +} + +int +nvif_event_ctor_(struct nvif_object *parent, const char *name, u32 handle, nvif_event_func func, + bool wait, struct nvif_event_v0 *args, u32 argc, bool warn, + struct nvif_event *event) +{ + struct nvif_event_v0 _args; + int ret; + + if (!args) { + args = &_args; + argc = sizeof(_args); + } + + args->version = 0; + args->wait = wait; + + ret = nvif_object_ctor(parent, name ?: "nvifEvent", handle, + NVIF_CLASS_EVENT, args, argc, &event->object); + NVIF_ERRON(ret && warn, parent, "[NEW EVENT wait:%d size:%zd]", + args->wait, argc - sizeof(*args)); + if (ret) + return ret; + + event->func = func; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild index 2b471ab585b4..216a3db821ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild @@ -14,3 +14,4 @@ nvkm-y += nvkm/core/oproxy.o nvkm-y += nvkm/core/option.o nvkm-y += nvkm/core/ramht.o nvkm-y += nvkm/core/subdev.o +nvkm-y += nvkm/core/uevent.o diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index 0c8c55c73b12..e1d978fbfe72 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -44,7 +44,7 @@ nvkm_uclient_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))){ args->v0.name[sizeof(args->v0.name) - 1] = 0; ret = nvkm_client_new(args->v0.name, args->v0.device, NULL, - NULL, oclass->client->ntfy, &client); + NULL, oclass->client->ntfy, oclass->client->event, &client); if (ret) return ret; } else @@ -286,7 +286,7 @@ int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg, int (*ntfy)(const void *, u32, const void *, u32), - struct nvkm_client **pclient) + int (*event)(u64, void *, u32), struct nvkm_client **pclient) { struct nvkm_oclass oclass = { .base = nvkm_uclient_sclass }; struct nvkm_client *client; @@ -301,6 +301,7 @@ nvkm_client_new(const char *name, u64 device, const char *cfg, client->debug = nvkm_dbgopt(dbg, "CLIENT"); client->objroot = RB_ROOT; client->ntfy = ntfy; + client->event = event; INIT_LIST_HEAD(&client->umem); spin_lock_init(&client->lock); return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/event.c b/drivers/gpu/drm/nouveau/nvkm/core/event.c index 006618d77aa4..ec508d1bbe1d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/event.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/event.c @@ -21,14 +21,19 @@ */ #include #include +#include void nvkm_event_put(struct nvkm_event *event, u32 types, int index) { assert_spin_locked(&event->refs_lock); + + nvkm_trace(event->subdev, "event: decr %08x on %d\n", types, index); + while (types) { int type = __ffs(types); types &= ~(1 << type); if (--event->refs[index * event->types_nr + type] == 0) { + nvkm_trace(event->subdev, "event: blocking %d on %d\n", type, index); if (event->func->fini) event->func->fini(event, 1 << type, index); } @@ -39,18 +44,146 @@ void nvkm_event_get(struct nvkm_event *event, u32 types, int index) { assert_spin_locked(&event->refs_lock); + + nvkm_trace(event->subdev, "event: incr %08x on %d\n", types, index); + while (types) { int type = __ffs(types); types &= ~(1 << type); if (++event->refs[index * event->types_nr + type] == 1) { + nvkm_trace(event->subdev, "event: allowing %d on %d\n", type, index); if (event->func->init) event->func->init(event, 1 << type, index); } } } +static void +nvkm_event_ntfy_state(struct nvkm_event_ntfy *ntfy) +{ + struct nvkm_event *event = ntfy->event; + unsigned long flags; + + nvkm_trace(event->subdev, "event: ntfy state changed\n"); + spin_lock_irqsave(&event->refs_lock, flags); + + if (atomic_read(&ntfy->allowed) != ntfy->running) { + if (ntfy->running) { + nvkm_event_put(ntfy->event, ntfy->bits, ntfy->id); + ntfy->running = false; + } else { + nvkm_event_get(ntfy->event, ntfy->bits, ntfy->id); + ntfy->running = true; + } + } + + spin_unlock_irqrestore(&event->refs_lock, flags); +} + +static void +nvkm_event_ntfy_remove(struct nvkm_event_ntfy *ntfy) +{ + spin_lock_irq(&ntfy->event->list_lock); + list_del_init(&ntfy->head); + spin_unlock_irq(&ntfy->event->list_lock); +} + +static void +nvkm_event_ntfy_insert(struct nvkm_event_ntfy *ntfy) +{ + spin_lock_irq(&ntfy->event->list_lock); + list_add_tail(&ntfy->head, &ntfy->event->ntfy); + spin_unlock_irq(&ntfy->event->list_lock); +} + +static void +nvkm_event_ntfy_block_(struct nvkm_event_ntfy *ntfy, bool wait) +{ + struct nvkm_subdev *subdev = ntfy->event->subdev; + + nvkm_trace(subdev, "event: ntfy block %08x on %d wait:%d\n", ntfy->bits, ntfy->id, wait); + + if (atomic_xchg(&ntfy->allowed, 0) == 1) { + nvkm_event_ntfy_state(ntfy); + if (wait) + nvkm_event_ntfy_remove(ntfy); + } +} + +void +nvkm_event_ntfy_block(struct nvkm_event_ntfy *ntfy) +{ + if (ntfy->event) + nvkm_event_ntfy_block_(ntfy, ntfy->wait); +} + +void +nvkm_event_ntfy_allow(struct nvkm_event_ntfy *ntfy) +{ + nvkm_trace(ntfy->event->subdev, "event: ntfy allow %08x on %d\n", ntfy->bits, ntfy->id); + + if (atomic_xchg(&ntfy->allowed, 1) == 0) { + nvkm_event_ntfy_state(ntfy); + if (ntfy->wait) + nvkm_event_ntfy_insert(ntfy); + } +} + +void +nvkm_event_ntfy_del(struct nvkm_event_ntfy *ntfy) +{ + struct nvkm_event *event = ntfy->event; + + if (!event) + return; + + nvkm_trace(event->subdev, "event: ntfy del %08x on %d\n", ntfy->bits, ntfy->id); + + nvkm_event_ntfy_block_(ntfy, false); + nvkm_event_ntfy_remove(ntfy); + ntfy->event = NULL; +} + +void +nvkm_event_ntfy_add(struct nvkm_event *event, int id, u32 bits, bool wait, nvkm_event_func func, + struct nvkm_event_ntfy *ntfy) +{ + nvkm_trace(event->subdev, "event: ntfy add %08x on %d wait:%d\n", id, bits, wait); + + ntfy->event = event; + ntfy->id = id; + ntfy->bits = bits; + ntfy->wait = wait; + ntfy->func = func; + atomic_set(&ntfy->allowed, 0); + ntfy->running = false; + INIT_LIST_HEAD(&ntfy->head); + if (!ntfy->wait) + nvkm_event_ntfy_insert(ntfy); +} + +bool +nvkm_event_ntfy_valid(struct nvkm_event *event, int id, u32 bits) +{ + return true; +} + +void +nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits) +{ + struct nvkm_event_ntfy *ntfy, *ntmp; + + nvkm_trace(event->subdev, "event: ntfy %08x on %d\n", bits, id); + + list_for_each_entry_safe(ntfy, ntmp, &event->ntfy, head) { + if (ntfy->id == id && ntfy->bits & bits) { + if (atomic_read(&ntfy->allowed)) + ntfy->func(ntfy, ntfy->bits & bits); + } + } +} + void -nvkm_event_send(struct nvkm_event *event, u32 types, int index, - void *data, u32 size) +nvkm_event_send(struct nvkm_event *event, u32 types, int index, void *data, u32 size) { struct nvkm_notify *notify; unsigned long flags; @@ -59,6 +192,8 @@ nvkm_event_send(struct nvkm_event *event, u32 types, int index, return; spin_lock_irqsave(&event->list_lock, flags); + nvkm_event_ntfy(event, index, types); + list_for_each_entry(notify, &event->list, head) { if (notify->index == index && (notify->types & types)) { if (event->func->send) { @@ -81,20 +216,20 @@ nvkm_event_fini(struct nvkm_event *event) } int -nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr, - struct nvkm_event *event) +nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev, + int types_nr, int index_nr, struct nvkm_event *event) { - event->refs = kzalloc(array3_size(index_nr, types_nr, - sizeof(*event->refs)), - GFP_KERNEL); + event->refs = kzalloc(array3_size(index_nr, types_nr, sizeof(*event->refs)), GFP_KERNEL); if (!event->refs) return -ENOMEM; event->func = func; + event->subdev = subdev; event->types_nr = types_nr; event->index_nr = index_nr; spin_lock_init(&event->refs_lock); spin_lock_init(&event->list_lock); INIT_LIST_HEAD(&event->list); + INIT_LIST_HEAD(&event->ntfy); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c index 45f920da89af..b42d0bf2c492 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c @@ -47,6 +47,26 @@ nvkm_ioctl_nop(struct nvkm_client *client, return ret; } +#include + +static int +nvkm_ioctl_sclass_(struct nvkm_object *object, int index, struct nvkm_oclass *oclass) +{ + if ( object->func->uevent && + !object->func->uevent(object, NULL, 0, NULL) && index-- == 0) { + oclass->ctor = nvkm_uevent_new; + oclass->base.minver = 0; + oclass->base.maxver = 0; + oclass->base.oclass = NVIF_CLASS_EVENT; + return 0; + } + + if (object->func->sclass) + return object->func->sclass(object, index, oclass); + + return -ENOSYS; +} + static int nvkm_ioctl_sclass(struct nvkm_client *client, struct nvkm_object *object, void *data, u32 size) @@ -64,8 +84,7 @@ nvkm_ioctl_sclass(struct nvkm_client *client, if (size != args->v0.count * sizeof(args->v0.oclass[0])) return -EINVAL; - while (object->func->sclass && - object->func->sclass(object, i, &oclass) >= 0) { + while (nvkm_ioctl_sclass_(object, i, &oclass) >= 0) { if (i < args->v0.count) { args->v0.oclass[i].oclass = oclass.base.oclass; args->v0.oclass[i].minver = oclass.base.minver; @@ -100,7 +119,7 @@ nvkm_ioctl_new(struct nvkm_client *client, } else return ret; - if (!parent->func->sclass) { + if (!parent->func->sclass && !parent->func->uevent) { nvif_ioctl(parent, "cannot have children\n"); return -EINVAL; } @@ -113,7 +132,7 @@ nvkm_ioctl_new(struct nvkm_client *client, oclass.object = args->v0.object; oclass.client = client; oclass.parent = parent; - ret = parent->func->sclass(parent, i++, &oclass); + ret = nvkm_ioctl_sclass_(parent, i++, &oclass); if (ret) return ret; } while (oclass.base.oclass != args->v0.oclass); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c index 16299837a296..3ffd4845d9e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c @@ -105,6 +105,18 @@ nvkm_oproxy_sclass(struct nvkm_object *object, int index, return oproxy->object->func->sclass(oproxy->object, index, oclass); } +static int +nvkm_oproxy_uevent(struct nvkm_object *object, void *argv, u32 argc, + struct nvkm_uevent *uevent) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + + if (!oproxy->object->func->uevent) + return -ENOSYS; + + return oproxy->object->func->uevent(oproxy->object, argv, argc, uevent); +} + static int nvkm_oproxy_fini(struct nvkm_object *object, bool suspend) { @@ -188,6 +200,7 @@ nvkm_oproxy_func = { .wr32 = nvkm_oproxy_wr32, .bind = nvkm_oproxy_bind, .sclass = nvkm_oproxy_sclass, + .uevent = nvkm_oproxy_uevent, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/core/uevent.c b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c new file mode 100644 index 000000000000..ba9d9edaec75 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c @@ -0,0 +1,157 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#define nvkm_uevent(p) container_of((p), struct nvkm_uevent, object) +#include +#include + +#include + +struct nvkm_uevent { + struct nvkm_object object; + struct nvkm_object *parent; + nvkm_uevent_func func; + bool wait; + + struct nvkm_event_ntfy ntfy; + atomic_t allowed; +}; + +static int +nvkm_uevent_mthd_block(struct nvkm_uevent *uevent, union nvif_event_block_args *args, u32 argc) +{ + if (argc != sizeof(args->vn)) + return -ENOSYS; + + nvkm_event_ntfy_block(&uevent->ntfy); + atomic_set(&uevent->allowed, 0); + return 0; +} + +static int +nvkm_uevent_mthd_allow(struct nvkm_uevent *uevent, union nvif_event_allow_args *args, u32 argc) +{ + if (argc != sizeof(args->vn)) + return -ENOSYS; + + nvkm_event_ntfy_allow(&uevent->ntfy); + atomic_set(&uevent->allowed, 1); + return 0; +} + +static int +nvkm_uevent_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_uevent *uevent = nvkm_uevent(object); + + switch (mthd) { + case NVIF_EVENT_V0_ALLOW: return nvkm_uevent_mthd_allow(uevent, argv, argc); + case NVIF_EVENT_V0_BLOCK: return nvkm_uevent_mthd_block(uevent, argv, argc); + default: + break; + } + + return -EINVAL; +} + +static int +nvkm_uevent_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_uevent *uevent = nvkm_uevent(object); + + nvkm_event_ntfy_block(&uevent->ntfy); + return 0; +} + +static int +nvkm_uevent_init(struct nvkm_object *object) +{ + struct nvkm_uevent *uevent = nvkm_uevent(object); + + if (atomic_read(&uevent->allowed)) + nvkm_event_ntfy_allow(&uevent->ntfy); + + return 0; +} + +static void * +nvkm_uevent_dtor(struct nvkm_object *object) +{ + struct nvkm_uevent *uevent = nvkm_uevent(object); + + nvkm_event_ntfy_del(&uevent->ntfy); + return uevent; +} + +static const struct nvkm_object_func +nvkm_uevent = { + .dtor = nvkm_uevent_dtor, + .init = nvkm_uevent_init, + .fini = nvkm_uevent_fini, + .mthd = nvkm_uevent_mthd, +}; + +static int +nvkm_uevent_ntfy(struct nvkm_event_ntfy *ntfy, u32 bits) +{ + struct nvkm_uevent *uevent = container_of(ntfy, typeof(*uevent), ntfy); + struct nvkm_client *client = uevent->object.client; + + if (uevent->func) + return uevent->func(uevent->parent, uevent->object.token, bits); + + return client->event(uevent->object.token, NULL, 0); +} + +int +nvkm_uevent_add(struct nvkm_uevent *uevent, struct nvkm_event *event, int id, u32 bits, + nvkm_uevent_func func) +{ + if (WARN_ON(uevent->func)) + return -EBUSY; + + nvkm_event_ntfy_add(event, id, bits, uevent->wait, nvkm_uevent_ntfy, &uevent->ntfy); + uevent->func = func; + return 0; +} + +int +nvkm_uevent_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + struct nvkm_uevent *uevent; + union nvif_event_args *args = argv; + + if (argc < sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + if (!(uevent = kzalloc(sizeof(*uevent), GFP_KERNEL))) + return -ENOMEM; + *pobject = &uevent->object; + + nvkm_object_ctor(&nvkm_uevent, oclass, &uevent->object); + uevent->parent = parent; + uevent->func = NULL; + uevent->wait = args->v0.wait; + uevent->ntfy.event = NULL; + return parent->func->uevent(parent, &args->v0.data, argc - sizeof(args->v0), uevent); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 65c99d948b68..55c97dc314e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -343,9 +343,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) /* Apparently we need to create a new one! */ ret = nvkm_conn_new(disp, i, &connE, &outp->conn); if (ret) { - nvkm_error(&disp->engine.subdev, - "failed to create outp %d conn: %d\n", - outp->index, ret); + nvkm_error(subdev, "failed to create outp %d conn: %d\n", outp->index, ret); nvkm_conn_del(&outp->conn); list_del(&outp->head); nvkm_outp_del(&outp); @@ -355,7 +353,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) list_add_tail(&outp->conn->head, &disp->conns); } - ret = nvkm_event_init(&nvkm_disp_hpd_func, 3, hpd, &disp->hpd); + ret = nvkm_event_init(&nvkm_disp_hpd_func, subdev, 3, hpd, &disp->hpd); if (ret) return ret; @@ -382,7 +380,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) list_for_each_entry(head, &disp->heads, head) i = max(i, head->id + 1); - return nvkm_event_init(&nvkm_disp_vblank_func, 1, i, &disp->vblank); + return nvkm_event_init(&nvkm_disp_vblank_func, subdev, 1, i, &disp->vblank); } static void * @@ -473,5 +471,6 @@ nvkm_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device, mutex_init(&disp->super.mutex); } - return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), &disp->uevent); + return nvkm_event_init(func->uevent, &disp->engine.subdev, 1, ARRAY_SIZE(disp->chan), + &disp->uevent); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 58b8df75fc40..c94b2b9b9329 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -347,11 +347,11 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, return ret; if (func->uevent_init) { - ret = nvkm_event_init(&nvkm_fifo_uevent_func, 1, 1, + ret = nvkm_event_init(&nvkm_fifo_uevent_func, &fifo->engine.subdev, 1, 1, &fifo->uevent); if (ret) return ret; } - return nvkm_event_init(&nvkm_fifo_kevent_func, 1, nr, &fifo->kevent); + return nvkm_event_init(&nvkm_fifo_kevent_func, &fifo->engine.subdev, 1, nr, &fifo->kevent); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c index f28967065639..d156f8676896 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c @@ -107,5 +107,5 @@ nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *func, struct nvkm_sw *sw, list_add(&chan->head, &sw->chan); spin_unlock_irqrestore(&sw->engine.lock, flags); - return nvkm_event_init(&nvkm_sw_chan_event, 1, 1, &chan->event); + return nvkm_event_init(&nvkm_sw_chan_event, &sw->engine.subdev, 1, 1, &chan->event); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c index fd54fa504efa..cc6fa1bb5034 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c @@ -130,8 +130,7 @@ nvkm_fault_oneinit(struct nvkm_subdev *subdev) } } - ret = nvkm_event_init(&nvkm_fault_ntfy, 1, fault->buffer_nr, - &fault->event); + ret = nvkm_event_init(&nvkm_fault_ntfy, subdev, 1, fault->buffer_nr, &fault->event); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c index 048bcc70c3f4..f2ccbcf219ca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c @@ -251,6 +251,5 @@ nvkm_gpio_new_(const struct nvkm_gpio_func *func, struct nvkm_device *device, nvkm_subdev_ctor(&nvkm_gpio, device, type, inst, &gpio->subdev); gpio->func = func; - return nvkm_event_init(&nvkm_gpio_intr_func, 2, func->lines, - &gpio->event); + return nvkm_event_init(&nvkm_gpio_intr_func, &gpio->subdev, 2, func->lines, &gpio->event); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index cb5cb533d91c..49a84ef146e9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -427,5 +427,5 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, } } - return nvkm_event_init(&nvkm_i2c_intr_func, 4, i, &i2c->event); + return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event); } -- cgit v1.2.3 From 55520832d6e40c1e2099ce2c6c1e5ab9ecf57ff7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:37 +1000 Subject: drm/nouveau/fault: switch non-replayable faults to nvkm_event_ntfy v2: fix flush_work() being called uninitialised during init Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/include/nvkm/subdev/fault.h | 5 +-- drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c | 41 ++++++++++++++-------- drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c | 17 ++++++--- 6 files changed, 44 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h index 9c78f072d62b..e781c5e4dcae 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h @@ -2,7 +2,6 @@ #define __NVKM_FAULT_H__ #include #include -#include struct nvkm_fault { const struct nvkm_fault_func *func; @@ -11,9 +10,11 @@ struct nvkm_fault { struct nvkm_fault_buffer *buffer[2]; int buffer_nr; +#define NVKM_FAULT_BUFFER_EVENT_PENDING BIT(0) struct nvkm_event event; - struct nvkm_notify nrpfb; + struct nvkm_event_ntfy nrpfb; + struct work_struct nrpfb_work; struct nvkm_device_oclass user; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c index cc6fa1bb5034..7dd722c9b660 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c @@ -145,7 +145,7 @@ nvkm_fault_dtor(struct nvkm_subdev *subdev) struct nvkm_fault *fault = nvkm_fault(subdev); int i; - nvkm_notify_fini(&fault->nrpfb); + nvkm_event_ntfy_del(&fault->nrpfb); nvkm_event_fini(&fault->event); for (i = 0; i < fault->buffer_nr; i++) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c index 6af7959e02ea..a96a1d633cb3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c @@ -65,7 +65,7 @@ gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer) void gp100_fault_intr(struct nvkm_fault *fault) { - nvkm_event_send(&fault->event, 1, 0, NULL, 0); + nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0); } static const struct nvkm_fault_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c index cd9d2ade5ac7..21756d65663b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c @@ -27,10 +27,12 @@ #include -static void -gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer) +void +gv100_fault_buffer_process(struct work_struct *work) { - struct nvkm_device *device = buffer->fault->subdev.device; + struct nvkm_fault *fault = container_of(work, typeof(*fault), nrpfb_work); + struct nvkm_fault_buffer *buffer = fault->buffer[0]; + struct nvkm_device *device = fault->subdev.device; struct nvkm_memory *mem = buffer->mem; u32 get = nvkm_rd32(device, buffer->get); u32 put = nvkm_rd32(device, buffer->put); @@ -115,11 +117,12 @@ gv100_fault_buffer_info(struct nvkm_fault_buffer *buffer) } static int -gv100_fault_ntfy_nrpfb(struct nvkm_notify *notify) +gv100_fault_ntfy_nrpfb(struct nvkm_event_ntfy *ntfy, u32 bits) { - struct nvkm_fault *fault = container_of(notify, typeof(*fault), nrpfb); - gv100_fault_buffer_process(fault->buffer[0]); - return NVKM_NOTIFY_KEEP; + struct nvkm_fault *fault = container_of(ntfy, typeof(*fault), nrpfb); + + schedule_work(&fault->nrpfb_work); + return NVKM_EVENT_KEEP; } static void @@ -163,14 +166,14 @@ gv100_fault_intr(struct nvkm_fault *fault) if (stat & 0x20000000) { if (fault->buffer[0]) { - nvkm_event_send(&fault->event, 1, 0, NULL, 0); + nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0); stat &= ~0x20000000; } } if (stat & 0x08000000) { if (fault->buffer[1]) { - nvkm_event_send(&fault->event, 1, 1, NULL, 0); + nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 1, NULL, 0); stat &= ~0x08000000; } } @@ -183,9 +186,12 @@ gv100_fault_intr(struct nvkm_fault *fault) static void gv100_fault_fini(struct nvkm_fault *fault) { - nvkm_notify_put(&fault->nrpfb); + nvkm_event_ntfy_block(&fault->nrpfb); + flush_work(&fault->nrpfb_work); + if (fault->buffer[0]) fault->func->buffer.fini(fault->buffer[0]); + nvkm_mask(fault->subdev.device, 0x100a34, 0x80000000, 0x80000000); } @@ -194,15 +200,15 @@ gv100_fault_init(struct nvkm_fault *fault) { nvkm_mask(fault->subdev.device, 0x100a2c, 0x80000000, 0x80000000); fault->func->buffer.init(fault->buffer[0]); - nvkm_notify_get(&fault->nrpfb); + nvkm_event_ntfy_allow(&fault->nrpfb); } int gv100_fault_oneinit(struct nvkm_fault *fault) { - return nvkm_notify_init(&fault->buffer[0]->object, &fault->event, - gv100_fault_ntfy_nrpfb, true, NULL, 0, 0, - &fault->nrpfb); + nvkm_event_ntfy_add(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING, true, + gv100_fault_ntfy_nrpfb, &fault->nrpfb); + return 0; } static const struct nvkm_fault_func @@ -231,5 +237,10 @@ int gv100_fault_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fault **pfault) { - return nvkm_fault_new_(&gv100_fault, device, type, inst, pfault); + int ret = nvkm_fault_new_(&gv100_fault, device, type, inst, pfault); + if (ret) + return ret; + + INIT_WORK(&(*pfault)->nrpfb_work, gv100_fault_buffer_process); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h index 36681c347fb5..30cc0d088897 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h @@ -46,6 +46,7 @@ void gp100_fault_buffer_fini(struct nvkm_fault_buffer *); void gp100_fault_buffer_init(struct nvkm_fault_buffer *); u64 gp100_fault_buffer_pin(struct nvkm_fault_buffer *); void gp100_fault_buffer_info(struct nvkm_fault_buffer *); +void gv100_fault_buffer_process(struct work_struct *); void gp100_fault_intr(struct nvkm_fault *); u64 gp10b_fault_buffer_pin(struct nvkm_fault_buffer *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c index 91eb6729c84d..2d3660d21b9a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c @@ -126,7 +126,7 @@ tu102_fault_intr(struct nvkm_fault *fault) nvkm_wr32(device, 0xb81010, 0x10); if (fault->buffer[0]) { - nvkm_event_send(&fault->event, 1, 0, NULL, 0); + nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0); stat &= ~0x00000200; } } @@ -137,7 +137,7 @@ tu102_fault_intr(struct nvkm_fault *fault) nvkm_wr32(device, 0xb81008, 0x1); if (fault->buffer[1]) { - nvkm_event_send(&fault->event, 1, 1, NULL, 0); + nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 1, NULL, 0); stat &= ~0x00000100; } } @@ -150,7 +150,9 @@ tu102_fault_intr(struct nvkm_fault *fault) static void tu102_fault_fini(struct nvkm_fault *fault) { - nvkm_notify_put(&fault->nrpfb); + nvkm_event_ntfy_block(&fault->nrpfb); + flush_work(&fault->nrpfb_work); + if (fault->buffer[0]) fault->func->buffer.fini(fault->buffer[0]); /*XXX: disable priv faults */ @@ -161,7 +163,7 @@ tu102_fault_init(struct nvkm_fault *fault) { /*XXX: enable priv faults */ fault->func->buffer.init(fault->buffer[0]); - nvkm_notify_get(&fault->nrpfb); + nvkm_event_ntfy_allow(&fault->nrpfb); } static const struct nvkm_fault_func @@ -184,5 +186,10 @@ int tu102_fault_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fault **pfault) { - return nvkm_fault_new_(&tu102_fault, device, type, inst, pfault); + int ret = nvkm_fault_new_(&tu102_fault, device, type, inst, pfault); + if (ret) + return ret; + + INIT_WORK(&(*pfault)->nrpfb_work, gv100_fault_buffer_process); + return 0; } -- cgit v1.2.3 From b418ff8863eec01b39f32eee0417a216f4cdb24c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:37 +1000 Subject: drm/nouveau/fault: expose replayable fault buffer event class Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/clb069.h | 5 ++- drivers/gpu/drm/nouveau/nouveau_svm.c | 50 +++++++++++++++--------- drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c | 16 -------- drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c | 30 ++++++++------ 4 files changed, 53 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/clb069.h b/drivers/gpu/drm/nouveau/include/nvif/clb069.h index eef5d0227bab..d7689de35ab2 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/clb069.h +++ b/drivers/gpu/drm/nouveau/include/nvif/clb069.h @@ -8,5 +8,8 @@ struct nvif_clb069_v0 { __u32 put; }; -#define NVB069_V0_NTFY_FAULT 0x00 +union nvif_clb069_event_args { + struct nvif_clb069_event_vn { + } vn; +}; #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c index 31a5b81ee9fc..a74ba8d84ba7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_svm.c +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c @@ -24,7 +24,7 @@ #include "nouveau_chan.h" #include "nouveau_dmem.h" -#include +#include #include #include @@ -51,7 +51,8 @@ struct nouveau_svm { u32 putaddr; u32 get; u32 put; - struct nvif_notify notify; + struct nvif_event notify; + struct work_struct work; struct nouveau_svm_fault { u64 inst; @@ -711,13 +712,11 @@ out: return ret; } -static int -nouveau_svm_fault(struct nvif_notify *notify) +static void +nouveau_svm_fault(struct work_struct *work) { - struct nouveau_svm_fault_buffer *buffer = - container_of(notify, typeof(*buffer), notify); - struct nouveau_svm *svm = - container_of(buffer, typeof(*svm), buffer[buffer->id]); + struct nouveau_svm_fault_buffer *buffer = container_of(work, typeof(*buffer), work); + struct nouveau_svm *svm = container_of(buffer, typeof(*svm), buffer[buffer->id]); struct nvif_object *device = &svm->drm->client.device.object; struct nouveau_svmm *svmm; struct { @@ -737,7 +736,7 @@ nouveau_svm_fault(struct nvif_notify *notify) buffer->put = nvif_rd32(device, buffer->putaddr); buffer->get = nvif_rd32(device, buffer->getaddr); if (buffer->get == buffer->put) - return NVIF_NOTIFY_KEEP; + return; } buffer->fault_nr = 0; @@ -881,7 +880,15 @@ nouveau_svm_fault(struct nvif_notify *notify) /* Issue fault replay to the GPU. */ if (replay) nouveau_svm_fault_replay(svm); - return NVIF_NOTIFY_KEEP; +} + +static int +nouveau_svm_event(struct nvif_event *event, void *argv, u32 argc) +{ + struct nouveau_svm_fault_buffer *buffer = container_of(event, typeof(*buffer), notify); + + schedule_work(&buffer->work); + return NVIF_EVENT_KEEP; } static struct nouveau_pfnmap_args * @@ -936,7 +943,9 @@ static void nouveau_svm_fault_buffer_fini(struct nouveau_svm *svm, int id) { struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id]; - nvif_notify_put(&buffer->notify); + + nvif_event_block(&buffer->notify); + flush_work(&buffer->work); } static int @@ -944,10 +953,12 @@ nouveau_svm_fault_buffer_init(struct nouveau_svm *svm, int id) { struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id]; struct nvif_object *device = &svm->drm->client.device.object; + buffer->get = nvif_rd32(device, buffer->getaddr); buffer->put = nvif_rd32(device, buffer->putaddr); SVM_DBG(svm, "get %08x put %08x (init)", buffer->get, buffer->put); - return nvif_notify_get(&buffer->notify); + + return nvif_event_allow(&buffer->notify); } static void @@ -956,15 +967,18 @@ nouveau_svm_fault_buffer_dtor(struct nouveau_svm *svm, int id) struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id]; int i; + if (!nvif_object_constructed(&buffer->object)) + return; + + nouveau_svm_fault_buffer_fini(svm, id); + if (buffer->fault) { for (i = 0; buffer->fault[i] && i < buffer->entries; i++) kfree(buffer->fault[i]); kvfree(buffer->fault); } - nouveau_svm_fault_buffer_fini(svm, id); - - nvif_notify_dtor(&buffer->notify); + nvif_event_dtor(&buffer->notify); nvif_object_dtor(&buffer->object); } @@ -990,10 +1004,10 @@ nouveau_svm_fault_buffer_ctor(struct nouveau_svm *svm, s32 oclass, int id) buffer->entries = args.entries; buffer->getaddr = args.get; buffer->putaddr = args.put; + INIT_WORK(&buffer->work, nouveau_svm_fault); - ret = nvif_notify_ctor(&buffer->object, "svmFault", nouveau_svm_fault, - true, NVB069_V0_NTFY_FAULT, NULL, 0, 0, - &buffer->notify); + ret = nvif_event_ctor(&buffer->object, "svmFault", id, nouveau_svm_event, true, NULL, 0, + &buffer->notify); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c index 7dd722c9b660..b53ac9a2552f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c @@ -22,7 +22,6 @@ #include "priv.h" #include -#include static void nvkm_fault_ntfy_fini(struct nvkm_event *event, int type, int index) @@ -38,23 +37,8 @@ nvkm_fault_ntfy_init(struct nvkm_event *event, int type, int index) fault->func->buffer.intr(fault->buffer[index], true); } -static int -nvkm_fault_ntfy_ctor(struct nvkm_object *object, void *argv, u32 argc, - struct nvkm_notify *notify) -{ - struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object); - if (argc == 0) { - notify->size = 0; - notify->types = 1; - notify->index = buffer->id; - return 0; - } - return -ENOSYS; -} - static const struct nvkm_event_func nvkm_fault_ntfy = { - .ctor = nvkm_fault_ntfy_ctor, .init = nvkm_fault_ntfy_init, .fini = nvkm_fault_ntfy_fini, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c index ac835c9582fd..c123e5893d76 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c @@ -22,11 +22,27 @@ #include "priv.h" #include +#include #include #include #include +static int +nvkm_ufault_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) +{ + struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object); + union nvif_clb069_event_args *args = argv; + + if (!uevent) + return 0; + if (argc != sizeof(args->vn)) + return -ENOSYS; + + return nvkm_uevent_add(uevent, &buffer->fault->event, buffer->id, + NVKM_FAULT_BUFFER_EVENT_PENDING, NULL); +} + static int nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc, enum nvkm_object_map *type, u64 *addr, u64 *size) @@ -39,18 +55,6 @@ nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc, return 0; } -static int -nvkm_ufault_ntfy(struct nvkm_object *object, u32 type, - struct nvkm_event **pevent) -{ - struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object); - if (type == NVB069_V0_NTFY_FAULT) { - *pevent = &buffer->fault->event; - return 0; - } - return -EINVAL; -} - static int nvkm_ufault_fini(struct nvkm_object *object, bool suspend) { @@ -78,8 +82,8 @@ nvkm_ufault = { .dtor = nvkm_ufault_dtor, .init = nvkm_ufault_init, .fini = nvkm_ufault_fini, - .ntfy = nvkm_ufault_ntfy, .map = nvkm_ufault_map, + .uevent = nvkm_ufault_uevent, }; int -- cgit v1.2.3 From 1d4dce284164de21cfbab05d0b763711c428df45 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:37 +1000 Subject: drm/nouveau/disp: switch vblank semaphore release to nvkm_event_ntfy Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/event.h | 2 -- drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c | 3 +-- drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c | 20 ++++++------------ drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c | 24 ++++++++-------------- drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h | 4 ++-- 6 files changed, 19 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h index a510ba4ad487..75211961c27b 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/event.h +++ b/drivers/gpu/drm/nouveau/include/nvif/event.h @@ -61,8 +61,6 @@ struct nvif_notify_head_req_v0 { struct nvif_notify_head_rep_v0 { /* nvif_notify_rep ... */ - __u8 version; - __u8 pad01[7]; }; struct nvif_notify_conn_req_v0 { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index eaf10f5d505e..ad9aef2df48f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -16,6 +16,7 @@ struct nvkm_disp { struct list_head conns; struct nvkm_event hpd; +#define NVKM_DISP_HEAD_EVENT_VBLANK BIT(0) struct nvkm_event vblank; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 55c97dc314e1..7d286138e5cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -90,8 +90,7 @@ nvkm_disp_vblank_func = { void nvkm_disp_vblank(struct nvkm_disp *disp, int head) { - struct nvif_notify_head_rep_v0 rep = {}; - nvkm_event_send(&disp->vblank, 1, head, &rep, sizeof(rep)); + nvkm_event_send(&disp->vblank, NVKM_DISP_HEAD_EVENT_VBLANK, head, NULL, 0); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c index 55abf839f29d..c3cf6f2ff86c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c @@ -36,10 +36,10 @@ ******************************************************************************/ static int -gf100_sw_chan_vblsem_release(struct nvkm_notify *notify) +gf100_sw_chan_vblsem_release(struct nvkm_event_ntfy *notify, u32 bits) { struct nv50_sw_chan *chan = - container_of(notify, typeof(*chan), vblank.notify[notify->index]); + container_of(notify, typeof(*chan), vblank.notify[notify->id]); struct nvkm_sw *sw = chan->base.sw; struct nvkm_device *device = sw->engine.subdev.device; u32 inst = chan->base.fifo->inst->addr >> 12; @@ -50,7 +50,7 @@ gf100_sw_chan_vblsem_release(struct nvkm_notify *notify) nvkm_wr32(device, 0x060010, lower_32_bits(chan->vblank.offset)); nvkm_wr32(device, 0x060014, chan->vblank.value); - return NVKM_NOTIFY_DROP; + return NVKM_EVENT_DROP; } static bool @@ -73,7 +73,7 @@ gf100_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data) return true; case 0x040c: if (data < device->disp->vblank.index_nr) { - nvkm_notify_get(&chan->vblank.notify[data]); + nvkm_event_ntfy_allow(&chan->vblank.notify[data]); return true; } break; @@ -120,16 +120,8 @@ gf100_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch, return ret; for (i = 0; disp && i < disp->vblank.index_nr; i++) { - ret = nvkm_notify_init(NULL, &disp->vblank, - gf100_sw_chan_vblsem_release, false, - &(struct nvif_notify_head_req_v0) { - .head = i, - }, - sizeof(struct nvif_notify_head_req_v0), - sizeof(struct nvif_notify_head_rep_v0), - &chan->vblank.notify[i]); - if (ret) - return ret; + nvkm_event_ntfy_add(&disp->vblank, i, NVKM_DISP_HEAD_EVENT_VBLANK, true, + gf100_sw_chan_vblsem_release, &chan->vblank.notify[i]); } return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c index 1fdd094c8b7e..9d7a9b7d5be3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c @@ -36,10 +36,10 @@ ******************************************************************************/ static int -nv50_sw_chan_vblsem_release(struct nvkm_notify *notify) +nv50_sw_chan_vblsem_release(struct nvkm_event_ntfy *notify, u32 bits) { struct nv50_sw_chan *chan = - container_of(notify, typeof(*chan), vblank.notify[notify->index]); + container_of(notify, typeof(*chan), vblank.notify[notify->id]); struct nvkm_sw *sw = chan->base.sw; struct nvkm_device *device = sw->engine.subdev.device; @@ -55,7 +55,7 @@ nv50_sw_chan_vblsem_release(struct nvkm_notify *notify) nvkm_wr32(device, 0x060014, chan->vblank.value); } - return NVKM_NOTIFY_DROP; + return NVKM_EVENT_DROP; } static bool @@ -70,7 +70,7 @@ nv50_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data) case 0x0404: chan->vblank.value = data; return true; case 0x0408: if (data < device->disp->vblank.index_nr) { - nvkm_notify_get(&chan->vblank.notify[data]); + nvkm_event_ntfy_allow(&chan->vblank.notify[data]); return true; } break; @@ -85,8 +85,10 @@ nv50_sw_chan_dtor(struct nvkm_sw_chan *base) { struct nv50_sw_chan *chan = nv50_sw_chan(base); int i; + for (i = 0; i < ARRAY_SIZE(chan->vblank.notify); i++) - nvkm_notify_fini(&chan->vblank.notify[i]); + nvkm_event_ntfy_del(&chan->vblank.notify[i]); + return chan; } @@ -113,16 +115,8 @@ nv50_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch, return ret; for (i = 0; disp && i < disp->vblank.index_nr; i++) { - ret = nvkm_notify_init(NULL, &disp->vblank, - nv50_sw_chan_vblsem_release, false, - &(struct nvif_notify_head_req_v0) { - .head = i, - }, - sizeof(struct nvif_notify_head_req_v0), - sizeof(struct nvif_notify_head_rep_v0), - &chan->vblank.notify[i]); - if (ret) - return ret; + nvkm_event_ntfy_add(&disp->vblank, i, NVKM_DISP_HEAD_EVENT_VBLANK, true, + nv50_sw_chan_vblsem_release, &chan->vblank.notify[i]); } return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h index 6d364d7b406a..b42289ce8826 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h @@ -5,12 +5,12 @@ #include "priv.h" #include "chan.h" #include "nvsw.h" -#include +#include struct nv50_sw_chan { struct nvkm_sw_chan base; struct { - struct nvkm_notify notify[4]; + struct nvkm_event_ntfy notify[4]; u32 ctxdma; u64 offset; u32 value; -- cgit v1.2.3 From ffd2664114c8fb9f12c4d4fd09c6d57cc3f4d951 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:38 +1000 Subject: drm/nouveau/disp: expose head event class Also fixes vblank interrupts being left enabled when they're not meant to be as a result of races/bugs in previous event handling code. v2: - use ?: (lyude) Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 22 ++++++------------- drivers/gpu/drm/nouveau/dispnv50/head.c | 20 ++++++------------ drivers/gpu/drm/nouveau/include/nvif/cl0046.h | 1 - drivers/gpu/drm/nouveau/include/nvif/event.h | 11 ---------- drivers/gpu/drm/nouveau/include/nvif/head.h | 10 +++++++++ drivers/gpu/drm/nouveau/include/nvif/if0013.h | 5 +++++ drivers/gpu/drm/nouveau/nouveau_crtc.h | 4 ++-- drivers/gpu/drm/nouveau/nouveau_display.c | 4 ++-- drivers/gpu/drm/nouveau/nvif/head.c | 10 +++++++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c | 27 ------------------------ drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c | 19 +++++++++++++++++ 11 files changed, 62 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index f35c25607508..80b0b5cf4079 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -761,7 +761,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) nouveau_bo_unmap(nv_crtc->cursor.nvbo); nouveau_bo_unpin(nv_crtc->cursor.nvbo); nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); - nvif_notify_dtor(&nv_crtc->vblank); + nvif_event_dtor(&nv_crtc->vblank); nvif_head_dtor(&nv_crtc->head); kfree(nv_crtc); } @@ -1280,13 +1280,13 @@ static const struct drm_plane_funcs nv04_primary_plane_funcs = { DRM_PLANE_NON_ATOMIC_FUNCS, }; -static int nv04_crtc_vblank_handler(struct nvif_notify *notify) +static int +nv04_crtc_vblank_handler(struct nvif_event *event, void *repv, u32 repc) { - struct nouveau_crtc *nv_crtc = - container_of(notify, struct nouveau_crtc, vblank); + struct nouveau_crtc *nv_crtc = container_of(event, struct nouveau_crtc, vblank); drm_crtc_handle_vblank(&nv_crtc->base); - return NVIF_NOTIFY_KEEP; + return NVIF_EVENT_KEEP; } int @@ -1346,14 +1346,6 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) if (ret) return ret; - ret = nvif_notify_ctor(&disp->disp.object, "kmsVbl", nv04_crtc_vblank_handler, - false, NV04_DISP_NTFY_VBLANK, - &(struct nvif_notify_head_req_v0) { - .head = nv_crtc->index, - }, - sizeof(struct nvif_notify_head_req_v0), - sizeof(struct nvif_notify_head_rep_v0), - &nv_crtc->vblank); - - return ret; + return nvif_head_vblank_event_ctor(&nv_crtc->head, "kmsVbl", nv04_crtc_vblank_handler, + false, &nv_crtc->vblank); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index 8ac3474111c5..f006e56e1e08 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -517,7 +517,7 @@ nv50_head_destroy(struct drm_crtc *crtc) { struct nv50_head *head = nv50_head(crtc); - nvif_notify_dtor(&head->base.vblank); + nvif_event_dtor(&head->base.vblank); nvif_head_dtor(&head->base.head); nv50_lut_fini(&head->olut); drm_crtc_cleanup(crtc); @@ -555,15 +555,15 @@ nvd9_head_func = { .late_register = nv50_head_late_register, }; -static int nv50_head_vblank_handler(struct nvif_notify *notify) +static int +nv50_head_vblank_handler(struct nvif_event *event, void *repv, u32 repc) { - struct nouveau_crtc *nv_crtc = - container_of(notify, struct nouveau_crtc, vblank); + struct nouveau_crtc *nv_crtc = container_of(event, struct nouveau_crtc, vblank); if (drm_crtc_handle_vblank(&nv_crtc->base)) nv50_crc_handle_vblank(nv50_head(&nv_crtc->base)); - return NVIF_NOTIFY_KEEP; + return NVIF_EVENT_KEEP; } struct nv50_head * @@ -629,14 +629,8 @@ nv50_head_create(struct drm_device *dev, int index) if (ret) return ERR_PTR(ret); - ret = nvif_notify_ctor(&disp->disp->object, "kmsVbl", nv50_head_vblank_handler, - false, NV04_DISP_NTFY_VBLANK, - &(struct nvif_notify_head_req_v0) { - .head = nv_crtc->index, - }, - sizeof(struct nvif_notify_head_req_v0), - sizeof(struct nvif_notify_head_rep_v0), - &nv_crtc->vblank); + ret = nvif_head_vblank_event_ctor(&head->base.head, "kmsVbl", nv50_head_vblank_handler, + false, &nv_crtc->vblank); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h index b3ac930b01fa..eca7c3950654 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h @@ -2,6 +2,5 @@ #ifndef __NVIF_CL0046_H__ #define __NVIF_CL0046_H__ -#define NV04_DISP_NTFY_VBLANK 0x00 #define NV04_DISP_NTFY_CONN 0x01 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h index 75211961c27b..679950400f53 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/event.h +++ b/drivers/gpu/drm/nouveau/include/nvif/event.h @@ -52,17 +52,6 @@ struct nvif_notify_rep_v0 { __u8 data[]; /* reply data (below) */ }; -struct nvif_notify_head_req_v0 { - /* nvif_notify_req ... */ - __u8 version; - __u8 head; - __u8 pad02[6]; -}; - -struct nvif_notify_head_rep_v0 { - /* nvif_notify_rep ... */ -}; - struct nvif_notify_conn_req_v0 { /* nvif_notify_req ... */ __u8 version; diff --git a/drivers/gpu/drm/nouveau/include/nvif/head.h b/drivers/gpu/drm/nouveau/include/nvif/head.h index 09170c7bc0af..3ec36999e956 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/head.h +++ b/drivers/gpu/drm/nouveau/include/nvif/head.h @@ -2,6 +2,7 @@ #ifndef __NVIF_HEAD_H__ #define __NVIF_HEAD_H__ #include +#include struct nvif_disp; struct nvif_head { @@ -10,4 +11,13 @@ struct nvif_head { int nvif_head_ctor(struct nvif_disp *, const char *name, int id, struct nvif_head *); void nvif_head_dtor(struct nvif_head *); + +static inline int +nvif_head_id(struct nvif_head *head) +{ + return head->object.handle; +} + +int nvif_head_vblank_event_ctor(struct nvif_head *, const char *name, nvif_event_func, bool wait, + struct nvif_event *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0013.h b/drivers/gpu/drm/nouveau/include/nvif/if0013.h index 4bd9507a200b..6756c7467ae4 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0013.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0013.h @@ -10,6 +10,11 @@ union nvif_head_args { } v0; }; +union nvif_head_event_args { + struct nvif_head_event_vn { + } vn; +}; + #define NVIF_HEAD_V0_SCANOUTPOS 0x00 union nvif_head_scanoutpos_args { diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h index e85e74f9a28d..c717f664a7b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_crtc.h +++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -29,14 +29,14 @@ #include #include -#include +#include struct nouveau_crtc { struct drm_crtc base; struct nvif_head head; int index; - struct nvif_notify vblank; + struct nvif_event vblank; uint32_t dpms_saved_fp_control; uint32_t fp_users; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 2034346f3934..e88845ae7520 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -52,7 +52,7 @@ nouveau_display_vblank_enable(struct drm_crtc *crtc) struct nouveau_crtc *nv_crtc; nv_crtc = nouveau_crtc(crtc); - nvif_notify_get(&nv_crtc->vblank); + nvif_event_allow(&nv_crtc->vblank); return 0; } @@ -63,7 +63,7 @@ nouveau_display_vblank_disable(struct drm_crtc *crtc) struct nouveau_crtc *nv_crtc; nv_crtc = nouveau_crtc(crtc); - nvif_notify_put(&nv_crtc->vblank); + nvif_event_block(&nv_crtc->vblank); } static inline int diff --git a/drivers/gpu/drm/nouveau/nvif/head.c b/drivers/gpu/drm/nouveau/nvif/head.c index 01deba462600..f00e01d232db 100644 --- a/drivers/gpu/drm/nouveau/nvif/head.c +++ b/drivers/gpu/drm/nouveau/nvif/head.c @@ -26,6 +26,16 @@ #include #include +int +nvif_head_vblank_event_ctor(struct nvif_head *head, const char *name, nvif_event_func func, + bool wait, struct nvif_event *event) +{ + int ret = nvif_event_ctor(&head->object, name ?: "nvifHeadVBlank", nvif_head_id(head), + func, wait, NULL, 0, event); + NVIF_ERRON(ret, &head->object, "[NEW EVENT:VBLANK]"); + return ret; +} + void nvif_head_dtor(struct nvif_head *head) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 7d286138e5cd..399195946823 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -57,32 +57,8 @@ nvkm_disp_vblank_init(struct nvkm_event *event, int type, int id) head->func->vblank_get(head); } -static int -nvkm_disp_vblank_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nvkm_disp *disp = - container_of(notify->event, typeof(*disp), vblank); - union { - struct nvif_notify_head_req_v0 v0; - } *req = data; - int ret = -ENOSYS; - - if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) { - notify->size = sizeof(struct nvif_notify_head_rep_v0); - if (ret = -ENXIO, req->v0.head <= disp->vblank.index_nr) { - notify->types = 1; - notify->index = req->v0.head; - return 0; - } - } - - return ret; -} - static const struct nvkm_event_func nvkm_disp_vblank_func = { - .ctor = nvkm_disp_vblank_ctor, .init = nvkm_disp_vblank_init, .fini = nvkm_disp_vblank_fini, }; @@ -132,9 +108,6 @@ nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event) { struct nvkm_disp *disp = nvkm_disp(object->engine); switch (type) { - case NV04_DISP_NTFY_VBLANK: - *event = &disp->vblank; - return 0; case NV04_DISP_NTFY_CONN: *event = &disp->hpd; return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c index 5f3c4b7dbb75..f072cec16040 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c @@ -21,9 +21,27 @@ */ #define nvkm_uhead(p) container_of((p), struct nvkm_head, object) #include "head.h" +#include #include +#include + +static int +nvkm_uhead_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) +{ + struct nvkm_head *head = nvkm_uhead(object); + union nvif_head_event_args *args = argv; + + if (!uevent) + return 0; + if (argc != sizeof(args->vn)) + return -ENOSYS; + + return nvkm_uevent_add(uevent, &head->disp->vblank, head->id, + NVKM_DISP_HEAD_EVENT_VBLANK, NULL); +} + static int nvkm_uhead_mthd_scanoutpos(struct nvkm_head *head, void *argv, u32 argc) { @@ -81,6 +99,7 @@ static const struct nvkm_object_func nvkm_uhead = { .dtor = nvkm_uhead_dtor, .mthd = nvkm_uhead_mthd, + .uevent = nvkm_uhead_uevent, }; int -- cgit v1.2.3 From 773eb04d14a11552b2c3953097ed09cde2ab4831 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:38 +1000 Subject: drm/nouveau/disp: expose conn event class This removes some now-unnecessary nesting of workqueues. v2: - use ?: (lyude) Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/conn.h | 10 +++ drivers/gpu/drm/nouveau/include/nvif/event.h | 19 ------ drivers/gpu/drm/nouveau/include/nvif/if0011.h | 11 ++++ drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h | 6 +- drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h | 19 ++---- drivers/gpu/drm/nouveau/nouveau_connector.c | 67 ++++++++++--------- drivers/gpu/drm/nouveau/nouveau_connector.h | 6 +- drivers/gpu/drm/nouveau/nouveau_display.c | 16 +++-- drivers/gpu/drm/nouveau/nouveau_dp.c | 15 +++-- drivers/gpu/drm/nouveau/nouveau_encoder.h | 3 +- drivers/gpu/drm/nouveau/nvif/conn.c | 19 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c | 54 ---------------- drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c | 39 ----------- drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h | 3 - drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 40 ------------ drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c | 75 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c | 1 - drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c | 24 +------ drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c | 25 +------- 21 files changed, 187 insertions(+), 269 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/conn.h b/drivers/gpu/drm/nouveau/include/nvif/conn.h index f72a8f138f47..dc355e1dfafa 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/conn.h +++ b/drivers/gpu/drm/nouveau/include/nvif/conn.h @@ -2,6 +2,7 @@ #ifndef __NVIF_CONN_H__ #define __NVIF_CONN_H__ #include +#include struct nvif_disp; struct nvif_conn { @@ -11,8 +12,17 @@ struct nvif_conn { int nvif_conn_ctor(struct nvif_disp *, const char *name, int id, struct nvif_conn *); void nvif_conn_dtor(struct nvif_conn *); +static inline int +nvif_conn_id(struct nvif_conn *conn) +{ + return conn->object.handle; +} + #define NVIF_CONN_HPD_STATUS_UNSUPPORTED 0 /* negative if query fails */ #define NVIF_CONN_HPD_STATUS_NOT_PRESENT 1 #define NVIF_CONN_HPD_STATUS_PRESENT 2 int nvif_conn_hpd_status(struct nvif_conn *); + +int nvif_conn_event_ctor(struct nvif_conn *, const char *name, nvif_event_func, u8 types, + struct nvif_event *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h index 679950400f53..3afcda2034d6 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/event.h +++ b/drivers/gpu/drm/nouveau/include/nvif/event.h @@ -52,25 +52,6 @@ struct nvif_notify_rep_v0 { __u8 data[]; /* reply data (below) */ }; -struct nvif_notify_conn_req_v0 { - /* nvif_notify_req ... */ - __u8 version; -#define NVIF_NOTIFY_CONN_V0_PLUG 0x01 -#define NVIF_NOTIFY_CONN_V0_UNPLUG 0x02 -#define NVIF_NOTIFY_CONN_V0_IRQ 0x04 -#define NVIF_NOTIFY_CONN_V0_ANY 0x07 - __u8 mask; - __u8 conn; - __u8 pad03[5]; -}; - -struct nvif_notify_conn_rep_v0 { - /* nvif_notify_rep ... */ - __u8 version; - __u8 mask; - __u8 pad02[6]; -}; - struct nvif_notify_uevent_req { /* nvif_notify_req ... */ }; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0011.h b/drivers/gpu/drm/nouveau/include/nvif/if0011.h index 04ba6581f840..69b0b779f942 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0011.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0011.h @@ -10,6 +10,17 @@ union nvif_conn_args { } v0; }; +union nvif_conn_event_args { + struct nvif_conn_event_v0 { + __u8 version; +#define NVIF_CONN_EVENT_V0_PLUG 0x01 +#define NVIF_CONN_EVENT_V0_UNPLUG 0x02 +#define NVIF_CONN_EVENT_V0_IRQ 0x04 + __u8 types; + __u8 pad02[6]; + } v0; +}; + #define NVIF_CONN_V0_HPD_STATUS 0x00000000 union nvif_conn_hpd_status_args { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h index 0e46ea1fe972..537c4fc58b4f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h @@ -8,9 +8,6 @@ #include struct nvkm_gpio_ntfy_req { -#define NVKM_GPIO_HI 0x01 -#define NVKM_GPIO_LO 0x02 -#define NVKM_GPIO_TOGGLED 0x03 u8 mask; u8 line; }; @@ -23,6 +20,9 @@ struct nvkm_gpio { const struct nvkm_gpio_func *func; struct nvkm_subdev subdev; +#define NVKM_GPIO_HI BIT(0) +#define NVKM_GPIO_LO BIT(1) +#define NVKM_GPIO_TOGGLED (NVKM_GPIO_HI | NVKM_GPIO_LO) struct nvkm_event event; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h index 146e13292203..40a1065ae626 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h @@ -7,20 +7,6 @@ #include #include -struct nvkm_i2c_ntfy_req { -#define NVKM_I2C_PLUG 0x01 -#define NVKM_I2C_UNPLUG 0x02 -#define NVKM_I2C_IRQ 0x04 -#define NVKM_I2C_DONE 0x08 -#define NVKM_I2C_ANY 0x0f - u8 mask; - u8 port; -}; - -struct nvkm_i2c_ntfy_rep { - u8 mask; -}; - struct nvkm_i2c_bus_probe { struct i2c_board_info dev; u8 udelay; /* set to 0 to use the standard delay */ @@ -79,6 +65,11 @@ struct nvkm_i2c { struct list_head bus; struct list_head aux; +#define NVKM_I2C_PLUG BIT(0) +#define NVKM_I2C_UNPLUG BIT(1) +#define NVKM_I2C_IRQ BIT(2) +#define NVKM_I2C_DONE BIT(3) +#define NVKM_I2C_ANY (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG | NVKM_I2C_IRQ | NVKM_I2C_DONE) struct nvkm_event event; }; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index bbd17ee60853..086b66b60d91 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -47,8 +47,7 @@ #include "nouveau_crtc.h" #include -#include -#include +#include struct drm_display_mode * nouveau_conn_native_mode(struct drm_connector *connector) @@ -396,7 +395,8 @@ static void nouveau_connector_destroy(struct drm_connector *connector) { struct nouveau_connector *nv_connector = nouveau_connector(connector); - nvif_notify_dtor(&nv_connector->hpd); + nvif_event_dtor(&nv_connector->irq); + nvif_event_dtor(&nv_connector->hpd); kfree(nv_connector->edid); drm_connector_unregister(connector); drm_connector_cleanup(connector); @@ -1178,23 +1178,22 @@ nouveau_connector_hpd(struct nouveau_connector *nv_connector, u64 bits) } static int -nouveau_connector_hotplug(struct nvif_notify *notify) +nouveau_connector_irq(struct nvif_event *event, void *repv, u32 repc) { - struct nouveau_connector *nv_connector = - container_of(notify, typeof(*nv_connector), hpd); - struct drm_connector *connector = &nv_connector->base; - struct drm_device *dev = connector->dev; - struct nouveau_drm *drm = nouveau_drm(dev); - const struct nvif_notify_conn_rep_v0 *rep = notify->data; + struct nouveau_connector *nv_connector = container_of(event, typeof(*nv_connector), irq); - if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { - nouveau_dp_irq(drm, nv_connector); - return NVIF_NOTIFY_KEEP; - } + schedule_work(&nv_connector->irq_work); + return NVIF_EVENT_KEEP; +} - nouveau_connector_hpd(nv_connector, rep->mask); +static int +nouveau_connector_hotplug(struct nvif_event *event, void *repv, u32 repc) +{ + struct nouveau_connector *nv_connector = container_of(event, typeof(*nv_connector), hpd); + struct nvif_conn_event_v0 *rep = repv; - return NVIF_NOTIFY_KEEP; + nouveau_connector_hpd(nv_connector, rep->types); + return NVIF_EVENT_KEEP; } static ssize_t @@ -1290,6 +1289,7 @@ nouveau_connector_create(struct drm_device *dev, connector = &nv_connector->base; nv_connector->index = index; + INIT_WORK(&nv_connector->irq_work, nouveau_dp_irq); /* attempt to parse vbios connector type and hotplug gpio */ nv_connector->dcb = olddcb_conn(dev, index); @@ -1401,6 +1401,7 @@ nouveau_connector_create(struct drm_device *dev, drm_connector_init(dev, connector, funcs, type); drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); + connector->polled = DRM_CONNECTOR_POLL_CONNECT; if (nv_connector->dcb && (disp->disp.conn_mask & BIT(nv_connector->index))) { ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index, @@ -1409,6 +1410,25 @@ nouveau_connector_create(struct drm_device *dev, kfree(nv_connector); return ERR_PTR(ret); } + + ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsHotplug", + nouveau_connector_hotplug, + NVIF_CONN_EVENT_V0_PLUG | NVIF_CONN_EVENT_V0_UNPLUG, + &nv_connector->hpd); + if (ret == 0) + connector->polled = DRM_CONNECTOR_POLL_HPD; + + if (nv_connector->aux.transfer) { + ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsDpIrq", + nouveau_connector_irq, NVIF_CONN_EVENT_V0_IRQ, + &nv_connector->irq); + if (ret) { + nvif_event_dtor(&nv_connector->hpd); + nvif_conn_dtor(&nv_connector->conn); + kfree(nv_connector); + return ERR_PTR(ret); + } + } } connector->funcs->reset(connector); @@ -1452,21 +1472,6 @@ nouveau_connector_create(struct drm_device *dev, break; } - ret = nvif_notify_ctor(&disp->disp.object, "kmsHotplug", - nouveau_connector_hotplug, - true, NV04_DISP_NTFY_CONN, - &(struct nvif_notify_conn_req_v0) { - .mask = NVIF_NOTIFY_CONN_V0_ANY, - .conn = index, - }, - sizeof(struct nvif_notify_conn_req_v0), - sizeof(struct nvif_notify_conn_rep_v0), - &nv_connector->hpd); - if (ret) - connector->polled = DRM_CONNECTOR_POLL_CONNECT; - else - connector->polled = DRM_CONNECTOR_POLL_HPD; - drm_connector_register(connector); return connector; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index 1bbf8bf6ba44..35bcb541722b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -27,7 +27,7 @@ #ifndef __NOUVEAU_CONNECTOR_H__ #define __NOUVEAU_CONNECTOR_H__ #include -#include +#include #include #include @@ -125,7 +125,9 @@ struct nouveau_connector { struct nvif_conn conn; u64 hpd_pending; - struct nvif_notify hpd; + struct nvif_event hpd; + struct nvif_event irq; + struct work_struct irq_work; struct drm_dp_aux aux; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e88845ae7520..55099d9ce1c8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -42,8 +42,8 @@ #include "nv50_display.h" #include +#include #include -#include #include int @@ -497,11 +497,11 @@ nouveau_display_hpd_work(struct work_struct *work) drm_dbg_kms(dev, "[CONNECTOR:%d:%s] plug:%d unplug:%d irq:%d\n", connector->base.id, connector->name, - !!(bits & NVIF_NOTIFY_CONN_V0_PLUG), - !!(bits & NVIF_NOTIFY_CONN_V0_UNPLUG), - !!(bits & NVIF_NOTIFY_CONN_V0_IRQ)); + !!(bits & NVIF_CONN_EVENT_V0_PLUG), + !!(bits & NVIF_CONN_EVENT_V0_UNPLUG), + !!(bits & NVIF_CONN_EVENT_V0_IRQ)); - if (bits & NVIF_NOTIFY_CONN_V0_IRQ) { + if (bits & NVIF_CONN_EVENT_V0_IRQ) { if (nouveau_dp_link_check(nv_connector)) continue; } @@ -584,7 +584,8 @@ nouveau_display_init(struct drm_device *dev, bool resume, bool runtime) drm_connector_list_iter_begin(dev, &conn_iter); nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { struct nouveau_connector *conn = nouveau_connector(connector); - nvif_notify_get(&conn->hpd); + nvif_event_allow(&conn->hpd); + nvif_event_allow(&conn->irq); } drm_connector_list_iter_end(&conn_iter); @@ -619,7 +620,8 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime) drm_connector_list_iter_begin(dev, &conn_iter); nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { struct nouveau_connector *conn = nouveau_connector(connector); - nvif_notify_put(&conn->hpd); + nvif_event_block(&conn->irq); + nvif_event_block(&conn->hpd); } drm_connector_list_iter_end(&conn_iter); diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index bde58d00fbf5..e00876f92aee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -29,7 +29,7 @@ #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include +#include MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)"); static int nouveau_mst = 1; @@ -222,11 +222,14 @@ nouveau_dp_link_check(struct nouveau_connector *nv_connector) return nvif_outp_dp_retrain(&nv_encoder->outp) == 0; } -void nouveau_dp_irq(struct nouveau_drm *drm, - struct nouveau_connector *nv_connector) +void +nouveau_dp_irq(struct work_struct *work) { + struct nouveau_connector *nv_connector = + container_of(work, typeof(*nv_connector), irq_work); struct drm_connector *connector = &nv_connector->base; struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP); + struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev); struct nv50_mstm *mstm; u64 hpd = 0; int ret; @@ -241,14 +244,14 @@ void nouveau_dp_irq(struct nouveau_drm *drm, if (mstm && mstm->is_mst) { if (!nv50_mstm_service(drm, nv_connector, mstm)) - hpd |= NVIF_NOTIFY_CONN_V0_UNPLUG; + hpd |= NVIF_CONN_EVENT_V0_UNPLUG; } else { drm_dp_cec_irq(&nv_connector->aux); if (nouveau_dp_has_sink_count(connector, outp)) { ret = drm_dp_read_sink_count(&nv_connector->aux); if (ret != outp->dp.sink_count) - hpd |= NVIF_NOTIFY_CONN_V0_PLUG; + hpd |= NVIF_CONN_EVENT_V0_PLUG; if (ret >= 0) outp->dp.sink_count = ret; } @@ -256,7 +259,7 @@ void nouveau_dp_irq(struct nouveau_drm *drm, mutex_unlock(&outp->dp.hpd_irq_lock); - nouveau_connector_hpd(nv_connector, NVIF_NOTIFY_CONN_V0_IRQ | hpd); + nouveau_connector_hpd(nv_connector, NVIF_CONN_EVENT_V0_IRQ | hpd); } /* TODO: diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 8524d211f4e1..70c1ad6c4d9d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -142,8 +142,7 @@ enum nouveau_dp_status { int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *); bool nouveau_dp_link_check(struct nouveau_connector *); -void nouveau_dp_irq(struct nouveau_drm *drm, - struct nouveau_connector *nv_connector); +void nouveau_dp_irq(struct work_struct *); enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, struct nouveau_encoder *, const struct drm_display_mode *, diff --git a/drivers/gpu/drm/nouveau/nvif/conn.c b/drivers/gpu/drm/nouveau/nvif/conn.c index 4ce935d58c90..a3cf91aeae2d 100644 --- a/drivers/gpu/drm/nouveau/nvif/conn.c +++ b/drivers/gpu/drm/nouveau/nvif/conn.c @@ -26,6 +26,25 @@ #include #include +int +nvif_conn_event_ctor(struct nvif_conn *conn, const char *name, nvif_event_func func, u8 types, + struct nvif_event *event) +{ + struct { + struct nvif_event_v0 base; + struct nvif_conn_event_v0 conn; + } args; + int ret; + + args.conn.version = 0; + args.conn.types = types; + + ret = nvif_event_ctor_(&conn->object, name ?: "nvifConnHpd", nvif_conn_id(conn), + func, true, &args.base, sizeof(args), false, event); + NVIF_DEBUG(&conn->object, "[NEW EVENT:HPD types:%02x]", types); + return ret; +} + int nvif_conn_hpd_status(struct nvif_conn *conn) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 399195946823..c1d81cf74c57 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -29,7 +29,6 @@ #include "outp.h" #include -#include #include #include #include @@ -69,54 +68,6 @@ nvkm_disp_vblank(struct nvkm_disp *disp, int head) nvkm_event_send(&disp->vblank, NVKM_DISP_HEAD_EVENT_VBLANK, head, NULL, 0); } -static int -nvkm_disp_hpd_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nvkm_disp *disp = - container_of(notify->event, typeof(*disp), hpd); - union { - struct nvif_notify_conn_req_v0 v0; - } *req = data; - struct nvkm_outp *outp; - int ret = -ENOSYS; - - if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) { - notify->size = sizeof(struct nvif_notify_conn_rep_v0); - list_for_each_entry(outp, &disp->outps, head) { - if (ret = -ENXIO, outp->conn->index == req->v0.conn) { - if (ret = -ENODEV, outp->conn->hpd.event) { - notify->types = req->v0.mask; - notify->index = req->v0.conn; - ret = 0; - } - break; - } - } - } - - return ret; -} - -static const struct nvkm_event_func -nvkm_disp_hpd_func = { - .ctor = nvkm_disp_hpd_ctor -}; - -int -nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event) -{ - struct nvkm_disp *disp = nvkm_disp(object->engine); - switch (type) { - case NV04_DISP_NTFY_CONN: - *event = &disp->hpd; - return 0; - default: - break; - } - return -EINVAL; -} - static int nvkm_disp_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, void *data, u32 size, @@ -325,10 +276,6 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) list_add_tail(&outp->conn->head, &disp->conns); } - ret = nvkm_event_init(&nvkm_disp_hpd_func, subdev, 3, hpd, &disp->hpd); - if (ret) - return ret; - if (disp->func->oneinit) { ret = disp->func->oneinit(disp); if (ret) @@ -376,7 +323,6 @@ nvkm_disp_dtor(struct nvkm_engine *engine) } nvkm_event_fini(&disp->vblank); - nvkm_event_fini(&disp->hpd); while (!list_empty(&disp->conns)) { conn = list_first_entry(&disp->conns, typeof(*conn), head); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c index 7ed11801a3ae..fbdae1137864 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c @@ -29,38 +29,14 @@ #include -static int -nvkm_conn_hpd(struct nvkm_notify *notify) -{ - struct nvkm_conn *conn = container_of(notify, typeof(*conn), hpd); - struct nvkm_disp *disp = conn->disp; - struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio; - const struct nvkm_gpio_ntfy_rep *line = notify->data; - struct nvif_notify_conn_rep_v0 rep; - int index = conn->index; - - CONN_DBG(conn, "HPD: %d", line->mask); - - if (!nvkm_gpio_get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index)) - rep.mask = NVIF_NOTIFY_CONN_V0_UNPLUG; - else - rep.mask = NVIF_NOTIFY_CONN_V0_PLUG; - rep.version = 0; - - nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep)); - return NVKM_NOTIFY_KEEP; -} - void nvkm_conn_fini(struct nvkm_conn *conn) { - nvkm_notify_put(&conn->hpd); } void nvkm_conn_init(struct nvkm_conn *conn) { - nvkm_notify_get(&conn->hpd); } void @@ -68,7 +44,6 @@ nvkm_conn_del(struct nvkm_conn **pconn) { struct nvkm_conn *conn = *pconn; if (conn) { - nvkm_notify_fini(&conn->hpd); kfree(*pconn); *pconn = NULL; } @@ -106,20 +81,6 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info, } conn->info.hpd = func.line; - - ret = nvkm_notify_init(NULL, &gpio->event, nvkm_conn_hpd, - true, &(struct nvkm_gpio_ntfy_req) { - .mask = NVKM_GPIO_TOGGLED, - .line = func.line, - }, - sizeof(struct nvkm_gpio_ntfy_req), - sizeof(struct nvkm_gpio_ntfy_rep), - &conn->hpd); - if (ret) { - CONN_ERR(conn, "func %02x failed, %d", info->hpd, ret); - } else { - CONN_DBG(conn, "func %02x (HPD)", info->hpd); - } } } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h index f109634ce5ca..a0600e72b0ec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h @@ -3,7 +3,6 @@ #define __NVKM_DISP_CONN_H__ #include "priv.h" -#include #include #include @@ -12,8 +11,6 @@ struct nvkm_conn { int index; struct nvbios_connE info; - struct nvkm_notify hpd; - struct list_head head; struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 730c3a6f3362..40c8ea43c42f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -738,31 +738,9 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) } } -static int -nvkm_dp_hpd(struct nvkm_notify *notify) -{ - const struct nvkm_i2c_ntfy_rep *line = notify->data; - struct nvkm_outp *outp = container_of(notify, typeof(*outp), dp.hpd); - struct nvkm_conn *conn = outp->conn; - struct nvkm_disp *disp = outp->disp; - struct nvif_notify_conn_rep_v0 rep = {}; - - OUTP_DBG(outp, "HPD: %d", line->mask); - if (line->mask & NVKM_I2C_IRQ) - rep.mask |= NVIF_NOTIFY_CONN_V0_IRQ; - if (line->mask & NVKM_I2C_UNPLUG) - rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG; - if (line->mask & NVKM_I2C_PLUG) - rep.mask |= NVIF_NOTIFY_CONN_V0_PLUG; - - nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep)); - return NVKM_NOTIFY_KEEP; -} - static void nvkm_dp_fini(struct nvkm_outp *outp) { - nvkm_notify_put(&outp->dp.hpd); nvkm_dp_enable(outp, false); } @@ -770,14 +748,11 @@ static void nvkm_dp_init(struct nvkm_outp *outp) { nvkm_dp_enable(outp, outp->dp.enabled); - nvkm_notify_put(&outp->conn->hpd); - nvkm_notify_get(&outp->dp.hpd); } static void * nvkm_dp_dtor(struct nvkm_outp *outp) { - nvkm_notify_fini(&outp->dp.hpd); return outp; } @@ -826,21 +801,6 @@ nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, struct n OUTP_DBG(outp, "bios dp %02x %02x %02x %02x", outp->dp.version, hdr, cnt, len); - /* hotplug detect, replaces gpio-based mechanism with aux events */ - ret = nvkm_notify_init(NULL, &i2c->event, nvkm_dp_hpd, true, - &(struct nvkm_i2c_ntfy_req) { - .mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG | - NVKM_I2C_IRQ, - .port = outp->dp.aux->id, - }, - sizeof(struct nvkm_i2c_ntfy_req), - sizeof(struct nvkm_i2c_ntfy_rep), - &outp->dp.hpd); - if (ret) { - OUTP_ERR(outp, "error monitoring aux hpd: %d", ret); - return ret; - } - mutex_init(&outp->dp.mutex); atomic_set(&outp->dp.lt.done, 0); return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index 66def8ae3165..b7631c1ab242 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -2,7 +2,6 @@ #ifndef __NVKM_DISP_OUTP_H__ #define __NVKM_DISP_OUTP_H__ #include "priv.h" -#include #include #include @@ -38,7 +37,6 @@ struct nvkm_outp { struct nvkm_i2c_aux *aux; - struct nvkm_notify hpd; bool enabled; bool aux_pwr; bool aux_pwr_pu; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index a98b57f82fe7..ec5292a8f3c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -42,8 +42,6 @@ struct nvkm_disp_func { } user[]; }; -int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **); - int nv50_disp_oneinit(struct nvkm_disp *); int nv50_disp_init(struct nvkm_disp *); void nv50_disp_fini(struct nvkm_disp *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c index fd9f18144c26..dad942be6679 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -21,11 +21,85 @@ */ #define nvkm_uconn(p) container_of((p), struct nvkm_conn, object) #include "conn.h" +#include "outp.h" +#include +#include #include +#include #include +static int +nvkm_uconn_uevent_aux(struct nvkm_object *object, u64 token, u32 bits) +{ + union nvif_conn_event_args args; + + args.v0.version = 0; + args.v0.types = 0; + if (bits & NVKM_I2C_PLUG) + args.v0.types |= NVIF_CONN_EVENT_V0_PLUG; + if (bits & NVKM_I2C_UNPLUG) + args.v0.types |= NVIF_CONN_EVENT_V0_UNPLUG; + if (bits & NVKM_I2C_IRQ) + args.v0.types |= NVIF_CONN_EVENT_V0_IRQ; + + return object->client->event(token, &args, sizeof(args.v0)); +} + +static int +nvkm_uconn_uevent_gpio(struct nvkm_object *object, u64 token, u32 bits) +{ + union nvif_conn_event_args args; + + args.v0.version = 0; + args.v0.types = 0; + if (bits & NVKM_GPIO_HI) + args.v0.types |= NVIF_CONN_EVENT_V0_PLUG; + if (bits & NVKM_GPIO_LO) + args.v0.types |= NVIF_CONN_EVENT_V0_UNPLUG; + + return object->client->event(token, &args, sizeof(args.v0)); +} + +static int +nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) +{ + struct nvkm_conn *conn = nvkm_uconn(object); + struct nvkm_device *device = conn->disp->engine.subdev.device; + struct nvkm_outp *outp; + union nvif_conn_event_args *args = argv; + u64 bits = 0; + + if (!uevent) { + if (conn->info.hpd == DCB_GPIO_UNUSED) + return -ENOSYS; + return 0; + } + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + list_for_each_entry(outp, &conn->disp->outps, head) { + if (outp->info.connector == conn->index && outp->dp.aux) { + if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG; + if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG; + if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ; + + return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits, + nvkm_uconn_uevent_aux); + } + } + + if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_GPIO_HI; + if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO; + if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) + return -EINVAL; + + return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits, + nvkm_uconn_uevent_gpio); +} + static int nvkm_uconn_mthd_hpd_status(struct nvkm_conn *conn, void *argv, u32 argc) { @@ -82,6 +156,7 @@ static const struct nvkm_object_func nvkm_uconn = { .dtor = nvkm_uconn_dtor, .mthd = nvkm_uconn_mthd, + .uevent = nvkm_uconn_uevent, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c index c9bd32220fe1..0268d1d75805 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c @@ -74,7 +74,6 @@ nvkm_udisp_dtor(struct nvkm_object *object) static const struct nvkm_object_func nvkm_udisp = { .dtor = nvkm_udisp_dtor, - .ntfy = nvkm_disp_ntfy, .sclass = nvkm_udisp_sclass, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c index f2ccbcf219ca..2c2c23b8663b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c @@ -24,7 +24,6 @@ #include "priv.h" #include -#include static int nvkm_gpio_drive(struct nvkm_gpio *gpio, int idx, int line, int dir, int out) @@ -123,23 +122,8 @@ nvkm_gpio_intr_init(struct nvkm_event *event, int type, int index) gpio->func->intr_mask(gpio, type, 1 << index, 1 << index); } -static int -nvkm_gpio_intr_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nvkm_gpio_ntfy_req *req = data; - if (!WARN_ON(size != sizeof(*req))) { - notify->size = sizeof(struct nvkm_gpio_ntfy_rep); - notify->types = req->mask; - notify->index = req->line; - return 0; - } - return -EINVAL; -} - static const struct nvkm_event_func nvkm_gpio_intr_func = { - .ctor = nvkm_gpio_intr_ctor, .init = nvkm_gpio_intr_init, .fini = nvkm_gpio_intr_fini, }; @@ -153,11 +137,9 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev) gpio->func->intr_stat(gpio, &hi, &lo); for (i = 0; (hi | lo) && i < gpio->func->lines; i++) { - struct nvkm_gpio_ntfy_rep rep = { - .mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) | - (NVKM_GPIO_LO * !!(lo & (1 << i))), - }; - nvkm_event_send(&gpio->event, rep.mask, i, &rep, sizeof(rep)); + u32 mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) | + (NVKM_GPIO_LO * !!(lo & (1 << i))); + nvkm_event_send(&gpio->event, mask, i, NULL, 0); } } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index 49a84ef146e9..feb7de985d2d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -26,7 +26,6 @@ #include "bus.h" #include "pad.h" -#include #include #include #include @@ -104,23 +103,8 @@ nvkm_i2c_intr_init(struct nvkm_event *event, int type, int id) i2c->func->aux_mask(i2c, type, aux->intr, aux->intr); } -static int -nvkm_i2c_intr_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nvkm_i2c_ntfy_req *req = data; - if (!WARN_ON(size != sizeof(*req))) { - notify->size = sizeof(struct nvkm_i2c_ntfy_rep); - notify->types = req->mask; - notify->index = req->port; - return 0; - } - return -EINVAL; -} - static const struct nvkm_event_func nvkm_i2c_intr_func = { - .ctor = nvkm_i2c_intr_ctor, .init = nvkm_i2c_intr_init, .fini = nvkm_i2c_intr_fini, }; @@ -145,13 +129,8 @@ nvkm_i2c_intr(struct nvkm_subdev *subdev) if (lo & aux->intr) mask |= NVKM_I2C_UNPLUG; if (rq & aux->intr) mask |= NVKM_I2C_IRQ; if (tx & aux->intr) mask |= NVKM_I2C_DONE; - if (mask) { - struct nvkm_i2c_ntfy_rep rep = { - .mask = mask, - }; - nvkm_event_send(&i2c->event, rep.mask, aux->id, - &rep, sizeof(rep)); - } + if (mask) + nvkm_event_send(&i2c->event, mask, aux->id, NULL, 0); } } -- cgit v1.2.3 From 801bc8584e58f718491ca25827647129d9b6ef1f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:39 +1000 Subject: drm/nouveau/disp: expose page flip event class Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 8 +++--- drivers/gpu/drm/nouveau/dispnv04/disp.c | 15 +++++++----- drivers/gpu/drm/nouveau/dispnv04/disp.h | 7 ++++-- drivers/gpu/drm/nouveau/include/nvif/if0004.h | 5 +++- drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c | 22 +---------------- drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c | 35 ++++++++++++++------------- 7 files changed, 42 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 80b0b5cf4079..4e8b84f59280 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1081,10 +1081,10 @@ nv04_finish_page_flip(struct nouveau_channel *chan, } int -nv04_flip_complete(struct nvif_notify *notify) +nv04_flip_complete(struct nvif_event *event, void *argv, u32 argc) { - struct nouveau_cli *cli = (void *)notify->object->client; - struct nouveau_drm *drm = cli->drm; + struct nv04_display *disp = container_of(event, typeof(*disp), flip); + struct nouveau_drm *drm = disp->drm; struct nouveau_channel *chan = drm->channel; struct nv04_page_flip_state state; @@ -1095,7 +1095,7 @@ nv04_flip_complete(struct nvif_notify *notify) state.bpp / 8); } - return NVIF_NOTIFY_KEEP; + return NVIF_EVENT_KEEP; } static int diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 99fee4d8cd31..e9ac3fb27ff7 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -61,7 +61,7 @@ nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend) struct drm_crtc *crtc; /* Disable flip completion events. */ - nvif_notify_put(&disp->flip); + nvif_event_block(&disp->flip); /* Disable vblank interrupts. */ NVWriteCRTC(dev, 0, NV_PCRTC_INTR_EN_0, 0); @@ -121,7 +121,7 @@ nv04_display_init(struct drm_device *dev, bool resume, bool runtime) encoder->enc_save(&encoder->base.base); /* Enable flip completion events. */ - nvif_notify_get(&disp->flip); + nvif_event_allow(&disp->flip); if (!resume) return 0; @@ -202,7 +202,7 @@ nv04_display_destroy(struct drm_device *dev) nouveau_hw_save_vga_fonts(dev, 0); - nvif_notify_dtor(&disp->flip); + nvif_event_dtor(&disp->flip); nouveau_display(dev)->priv = NULL; vfree(disp); @@ -227,6 +227,8 @@ nv04_display_create(struct drm_device *dev) if (!disp) return -ENOMEM; + disp->drm = drm; + nvif_object_map(&drm->client.device.object, NULL, 0); nouveau_display(dev)->priv = disp; @@ -239,9 +241,10 @@ nv04_display_create(struct drm_device *dev) /* Request page flip completion event. */ if (drm->channel) { - nvif_notify_ctor(&drm->channel->nvsw, "kmsFlip", nv04_flip_complete, - false, NV04_NVSW_NTFY_UEVENT, - NULL, 0, 0, &disp->flip); + ret = nvif_event_ctor(&drm->channel->nvsw, "kmsFlip", 0, nv04_flip_complete, + true, NULL, 0, &disp->flip); + if (ret) + return ret; } nouveau_hw_save_vga_fonts(dev, 1); diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index f0a24126641a..11a6663758ec 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h @@ -6,6 +6,8 @@ #include "nouveau_display.h" +#include + struct nouveau_encoder; enum nv04_fp_display_regs { @@ -84,7 +86,8 @@ struct nv04_display { uint32_t saved_vga_font[4][16384]; uint32_t dac_users[4]; struct nouveau_bo *image[2]; - struct nvif_notify flip; + struct nvif_event flip; + struct nouveau_drm *drm; }; static inline struct nv04_display * @@ -179,5 +182,5 @@ nouveau_bios_run_init_table(struct drm_device *dev, u16 table, ); } -int nv04_flip_complete(struct nvif_notify *); +int nv04_flip_complete(struct nvif_event *, void *, u32); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0004.h b/drivers/gpu/drm/nouveau/include/nvif/if0004.h index d324c73c27fb..1d916a137941 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0004.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0004.h @@ -2,7 +2,10 @@ #ifndef __NVIF_IF0004_H__ #define __NVIF_IF0004_H__ -#define NV04_NVSW_NTFY_UEVENT 0x00 +union nv04_nvsw_event_args { + struct nv04_nvsw_event_vn { + } vn; +}; #define NV04_NVSW_GET_REF 0x00 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c index d156f8676896..5e65e13b0053 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c @@ -23,7 +23,6 @@ */ #include "chan.h" -#include #include #include @@ -36,7 +35,7 @@ nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data) case 0x0000: return true; case 0x0500: - nvkm_event_send(&chan->event, 1, 0, NULL, 0); + nvkm_event_send(&chan->event, NVKM_SW_CHAN_EVENT_PAGE_FLIP, 0, NULL, 0); return true; default: if (chan->func->mthd) @@ -46,27 +45,8 @@ nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data) return false; } -static int -nvkm_sw_chan_event_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - union { - struct nvif_notify_uevent_req none; - } *req = data; - int ret = -ENOSYS; - - if (!(ret = nvif_unvers(ret, &data, &size, req->none))) { - notify->size = sizeof(struct nvif_notify_uevent_rep); - notify->types = 1; - notify->index = 0; - } - - return ret; -} - static const struct nvkm_event_func nvkm_sw_chan_event = { - .ctor = nvkm_sw_chan_event_ctor, }; static void * diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h index 32de53427aa4..67b2e5ea93d9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h @@ -14,6 +14,7 @@ struct nvkm_sw_chan { struct nvkm_fifo_chan *fifo; struct list_head head; +#define NVKM_SW_CHAN_EVENT_PAGE_FLIP BIT(0) struct nvkm_event event; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c index 33dd03fff3c4..f5affa1c8f34 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c @@ -27,33 +27,34 @@ #include static int -nvkm_nvsw_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) +nvkm_nvsw_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) { - struct nvkm_nvsw *nvsw = nvkm_nvsw(object); - if (nvsw->func->mthd) - return nvsw->func->mthd(nvsw, mthd, data, size); - return -ENODEV; + union nv04_nvsw_event_args *args = argv; + + if (!uevent) + return 0; + if (argc != sizeof(args->vn)) + return -ENOSYS; + + return nvkm_uevent_add(uevent, &nvkm_nvsw(object)->chan->event, 0, + NVKM_SW_CHAN_EVENT_PAGE_FLIP, NULL); } static int -nvkm_nvsw_ntfy_(struct nvkm_object *object, u32 mthd, - struct nvkm_event **pevent) +nvkm_nvsw_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { struct nvkm_nvsw *nvsw = nvkm_nvsw(object); - switch (mthd) { - case NV04_NVSW_NTFY_UEVENT: - *pevent = &nvsw->chan->event; - return 0; - default: - break; - } - return -EINVAL; + + if (nvsw->func->mthd) + return nvsw->func->mthd(nvsw, mthd, data, size); + + return -ENODEV; } static const struct nvkm_object_func nvkm_nvsw_ = { - .mthd = nvkm_nvsw_mthd_, - .ntfy = nvkm_nvsw_ntfy_, + .mthd = nvkm_nvsw_mthd, + .uevent = nvkm_nvsw_uevent, }; int -- cgit v1.2.3 From 8c880fd4c155d9b1b3e294169d7dc3f3a1e04bd3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:39 +1000 Subject: drm/nouveau/fifo: expose non-stall intr in host channel event class Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/cl826e.h | 2 -- drivers/gpu/drm/nouveau/include/nvif/cl826f.h | 2 -- drivers/gpu/drm/nouveau/include/nvif/cl906f.h | 1 - drivers/gpu/drm/nouveau/include/nvif/cla06f.h | 1 - drivers/gpu/drm/nouveau/include/nvif/class.h | 2 ++ drivers/gpu/drm/nouveau/include/nvif/clc36f.h | 1 - drivers/gpu/drm/nouveau/include/nvif/if0020.h | 12 +++++++ drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 1 + drivers/gpu/drm/nouveau/nouveau_fence.c | 42 +++++++++++----------- drivers/gpu/drm/nouveau/nouveau_fence.h | 4 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 23 +----------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 25 +++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 15 -------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 3 -- 14 files changed, 64 insertions(+), 70 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvif/if0020.h (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h index 1b6496d31580..ef3033b836f0 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h @@ -10,6 +10,4 @@ struct g82_channel_dma_v0 { __u64 pushbuf; __u64 offset; }; - -#define NV826E_V0_NTFY_NON_STALL_INTERRUPT 0x00 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h index 148602264a76..c5d5e56b04cc 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h @@ -11,6 +11,4 @@ struct g82_channel_gpfifo_v0 { __u64 pushbuf; __u64 vmm; }; - -#define NV826F_V0_NTFY_NON_STALL_INTERRUPT 0x00 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h index 3823d6891b55..0e17b21e8c6e 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h @@ -11,6 +11,5 @@ struct fermi_channel_gpfifo_v0 { __u64 vmm; }; -#define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00 #define NV906F_V0_NTFY_KILLED 0x01 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h index cfa18f1fbf83..00057ddfa41f 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h @@ -13,6 +13,5 @@ struct kepler_channel_gpfifo_a_v0 { __u64 inst; }; -#define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00 #define NVA06F_V0_NTFY_KILLED 0x01 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index 29448f77069b..3e9d181b5dda 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -40,6 +40,8 @@ #define NVIF_CLASS_HEAD /* if0013.h */ 0x80000013 #define NVIF_CLASS_DISP_CHAN /* if0014.h */ 0x80000014 +#define NVIF_CLASS_CHAN /* if0020.h */ 0x80000020 + /* the below match nvidia-assigned (either in hw, or sw) class numbers */ #define NV_NULL_CLASS 0x00000030 diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h index f66885891238..b36624760dea 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h @@ -14,6 +14,5 @@ struct volta_channel_gpfifo_a_v0 { __u32 token; }; -#define NVC36F_V0_NTFY_NON_STALL_INTERRUPT 0x00 #define NVC36F_V0_NTFY_KILLED 0x01 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0020.h b/drivers/gpu/drm/nouveau/include/nvif/if0020.h new file mode 100644 index 000000000000..29a9fe2a8d87 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0020.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0020_H__ +#define __NVIF_IF0020_H__ + +union nvif_chan_event_args { + struct nvif_chan_event_v0 { + __u8 version; +#define NVIF_CHAN_EVENT_V0_NON_STALL_INTR 0x00 + __u8 type; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 15099913504d..ebfca3ffe9ae 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -42,6 +42,7 @@ struct nvkm_fifo { spinlock_t lock; struct mutex mutex; +#define NVKM_FIFO_EVENT_NON_STALL_INTR BIT(0) struct nvkm_event uevent; /* async user trigger */ struct nvkm_event kevent; /* channel killed */ }; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index abcac7db4347..62560e30febb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -29,9 +29,7 @@ #include #include -#include -#include -#include +#include #include "nouveau_drv.h" #include "nouveau_dma.h" @@ -99,7 +97,7 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) dma_fence_set_error(&fence->base, error); if (nouveau_fence_signal(fence)) - nvif_notify_put(&fctx->notify); + nvif_event_block(&fctx->event); } spin_unlock_irq(&fctx->lock); } @@ -108,7 +106,7 @@ void nouveau_fence_context_del(struct nouveau_fence_chan *fctx) { nouveau_fence_context_kill(fctx, 0); - nvif_notify_dtor(&fctx->notify); + nvif_event_dtor(&fctx->event); fctx->dead = 1; /* @@ -150,12 +148,11 @@ nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fc } static int -nouveau_fence_wait_uevent_handler(struct nvif_notify *notify) +nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc) { - struct nouveau_fence_chan *fctx = - container_of(notify, typeof(*fctx), notify); + struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event); unsigned long flags; - int ret = NVIF_NOTIFY_KEEP; + int ret = NVIF_EVENT_KEEP; spin_lock_irqsave(&fctx->lock, flags); if (!list_empty(&fctx->pending)) { @@ -165,7 +162,7 @@ nouveau_fence_wait_uevent_handler(struct nvif_notify *notify) fence = list_entry(fctx->pending.next, typeof(*fence), head); chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); if (nouveau_fence_update(chan, fctx)) - ret = NVIF_NOTIFY_DROP; + ret = NVIF_EVENT_DROP; } spin_unlock_irqrestore(&fctx->lock, flags); @@ -177,6 +174,10 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha { struct nouveau_fence_priv *priv = (void*)chan->drm->fence; struct nouveau_cli *cli = (void *)chan->user.client; + struct { + struct nvif_event_v0 base; + struct nvif_chan_event_v0 host; + } args; int ret; INIT_LIST_HEAD(&fctx->flip); @@ -195,13 +196,12 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha if (!priv->uevent) return; - ret = nvif_notify_ctor(&chan->user, "fenceNonStallIntr", - nouveau_fence_wait_uevent_handler, - false, NV826E_V0_NTFY_NON_STALL_INTERRUPT, - &(struct nvif_notify_uevent_req) { }, - sizeof(struct nvif_notify_uevent_req), - sizeof(struct nvif_notify_uevent_rep), - &fctx->notify); + args.host.version = 0; + args.host.type = NVIF_CHAN_EVENT_V0_NON_STALL_INTR; + + ret = nvif_event_ctor(&chan->user, "fenceNonStallIntr", chan->chid, + nouveau_fence_wait_uevent_handler, false, + &args.base, sizeof(args), &fctx->event); WARN_ON(ret); } @@ -230,7 +230,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) spin_lock_irq(&fctx->lock); if (nouveau_fence_update(chan, fctx)) - nvif_notify_put(&fctx->notify); + nvif_event_block(&fctx->event); list_add_tail(&fence->head, &fctx->pending); spin_unlock_irq(&fctx->lock); @@ -254,7 +254,7 @@ nouveau_fence_done(struct nouveau_fence *fence) spin_lock_irqsave(&fctx->lock, flags); chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); if (chan && nouveau_fence_update(chan, fctx)) - nvif_notify_put(&fctx->notify); + nvif_event_block(&fctx->event); spin_unlock_irqrestore(&fctx->lock, flags); } return dma_fence_is_signaled(&fence->base); @@ -505,13 +505,13 @@ static bool nouveau_fence_enable_signaling(struct dma_fence *f) bool ret; if (!fctx->notify_ref++) - nvif_notify_get(&fctx->notify); + nvif_event_allow(&fctx->event); ret = nouveau_fence_no_signaling(f); if (ret) set_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags); else if (!--fctx->notify_ref) - nvif_notify_put(&fctx->notify); + nvif_event_block(&fctx->event); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 4887caa69c65..0ca2bc85adf6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -3,7 +3,7 @@ #define __NOUVEAU_FENCE_H__ #include -#include +#include struct nouveau_drm; struct nouveau_bo; @@ -44,7 +44,7 @@ struct nouveau_fence_chan { u32 context; char name[32]; - struct nvif_notify notify; + struct nvif_event event; int notify_ref, dead; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index c94b2b9b9329..ec790af9b24f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -158,27 +158,8 @@ nvkm_fifo_uevent_init(struct nvkm_event *event, int type, int index) fifo->func->uevent_init(fifo); } -static int -nvkm_fifo_uevent_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - union { - struct nvif_notify_uevent_req none; - } *req = data; - int ret = -ENOSYS; - - if (!(ret = nvif_unvers(ret, &data, &size, req->none))) { - notify->size = sizeof(struct nvif_notify_uevent_rep); - notify->types = 1; - notify->index = 0; - } - - return ret; -} - static const struct nvkm_event_func nvkm_fifo_uevent_func = { - .ctor = nvkm_fifo_uevent_ctor, .init = nvkm_fifo_uevent_init, .fini = nvkm_fifo_uevent_fini, }; @@ -186,9 +167,7 @@ nvkm_fifo_uevent_func = { void nvkm_fifo_uevent(struct nvkm_fifo *fifo) { - struct nvif_notify_uevent_rep rep = { - }; - nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep)); + nvkm_event_send(&fifo->uevent, NVKM_FIFO_EVENT_NON_STALL_INTR, 0, NULL, 0); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 2e7f32cebf2a..08f09f40defb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -29,6 +29,8 @@ #include #include +#include + struct nvkm_fifo_chan_object { struct nvkm_oproxy oproxy; struct nvkm_fifo_chan *chan; @@ -250,6 +252,28 @@ nvkm_fifo_chan_child_get(struct nvkm_object *object, int index, return -EINVAL; } +static int +nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + union nvif_chan_event_args *args = argv; + + if (!uevent) + return 0; + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + switch (args->v0.type) { + case NVIF_CHAN_EVENT_V0_NON_STALL_INTR: + return nvkm_uevent_add(uevent, &chan->fifo->uevent, 0, + NVKM_FIFO_EVENT_NON_STALL_INTR, NULL); + default: + break; + } + + return -ENOSYS; +} + static int nvkm_fifo_chan_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **pevent) @@ -320,6 +344,7 @@ nvkm_fifo_chan_func = { .ntfy = nvkm_fifo_chan_ntfy, .map = nvkm_fifo_chan_map, .sclass = nvkm_fifo_chan_child_get, + .uevent = nvkm_fifo_chan_uevent, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 3492c561f2cf..903b54c07750 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -30,20 +30,6 @@ #include -static int -g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, - struct nvkm_event **pevent) -{ - switch (type) { - case NV826E_V0_NTFY_NON_STALL_INTERRUPT: - *pevent = &chan->fifo->uevent; - return 0; - default: - break; - } - return -EINVAL; -} - static int g84_fifo_chan_engine_addr(struct nvkm_engine *engine) { @@ -198,7 +184,6 @@ g84_fifo_chan_func = { .dtor = nv50_fifo_chan_dtor, .init = g84_fifo_chan_init, .fini = nv50_fifo_chan_fini, - .ntfy = g84_fifo_chan_ntfy, .engine_ctor = g84_fifo_chan_engine_ctor, .engine_dtor = nv50_fifo_chan_engine_dtor, .engine_init = g84_fifo_chan_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 4e78bbe3b94b..569b5eedb84d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -37,9 +37,6 @@ gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, struct nvkm_event **pevent) { switch (type) { - case NV906F_V0_NTFY_NON_STALL_INTERRUPT: - *pevent = &chan->fifo->uevent; - return 0; case NV906F_V0_NTFY_KILLED: *pevent = &chan->fifo->kevent; return 0; -- cgit v1.2.3 From 6c9705f68465661eede90ce435eda7fd49f70d79 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:39 +1000 Subject: drm/nouveau/fifo: expose channel killed in host channel event class Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/cl906f.h | 2 -- drivers/gpu/drm/nouveau/include/nvif/cla06f.h | 2 -- drivers/gpu/drm/nouveau/include/nvif/clc36f.h | 2 -- drivers/gpu/drm/nouveau/include/nvif/if0020.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 1 + drivers/gpu/drm/nouveau/nouveau_chan.c | 28 +++++++++++++++------- drivers/gpu/drm/nouveau/nouveau_chan.h | 4 ++-- drivers/gpu/drm/nouveau/nouveau_fence.c | 5 ++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 18 +------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 14 +++-------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 15 ------------ .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c | 1 - 15 files changed, 30 insertions(+), 66 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h index 0e17b21e8c6e..5ccc8fd8c458 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h @@ -10,6 +10,4 @@ struct fermi_channel_gpfifo_v0 { __u64 ioffset; __u64 vmm; }; - -#define NV906F_V0_NTFY_KILLED 0x01 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h index 00057ddfa41f..10449accd3e8 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h @@ -12,6 +12,4 @@ struct kepler_channel_gpfifo_a_v0 { __u64 vmm; __u64 inst; }; - -#define NVA06F_V0_NTFY_KILLED 0x01 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h index b36624760dea..cdf6708e1d9a 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h @@ -13,6 +13,4 @@ struct volta_channel_gpfifo_a_v0 { __u64 inst; __u32 token; }; - -#define NVC36F_V0_NTFY_KILLED 0x01 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0020.h b/drivers/gpu/drm/nouveau/include/nvif/if0020.h index 29a9fe2a8d87..1893b8aa0abb 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0020.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0020.h @@ -6,6 +6,7 @@ union nvif_chan_event_args { struct nvif_chan_event_v0 { __u8 version; #define NVIF_CHAN_EVENT_V0_NON_STALL_INTR 0x00 +#define NVIF_CHAN_EVENT_V0_KILLED 0x01 __u8 type; } v0; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index ebfca3ffe9ae..5a19c71f7ccb 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -44,6 +44,7 @@ struct nvkm_fifo { #define NVKM_FIFO_EVENT_NON_STALL_INTR BIT(0) struct nvkm_event uevent; /* async user trigger */ +#define NVKM_FIFO_EVENT_KILLED BIT(0) struct nvkm_event kevent; /* channel killed */ }; diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 48dea5d0c580..497d889c20b6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "nouveau_drv.h" @@ -46,15 +47,17 @@ int nouveau_vram_pushbuf; module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); static int -nouveau_channel_killed(struct nvif_notify *ntfy) +nouveau_channel_killed(struct nvif_event *event, void *repv, u32 repc) { - struct nouveau_channel *chan = container_of(ntfy, typeof(*chan), kill); + struct nouveau_channel *chan = container_of(event, typeof(*chan), kill); struct nouveau_cli *cli = (void *)chan->user.client; + NV_PRINTK(warn, cli, "channel %d killed!\n", chan->chid); atomic_set(&chan->killed, 1); if (chan->fence) nouveau_fence_context_kill(chan->fence, -ENODEV); - return NVIF_NOTIFY_DROP; + + return NVIF_EVENT_DROP; } int @@ -96,7 +99,7 @@ nouveau_channel_del(struct nouveau_channel **pchan) nvif_object_dtor(&chan->nvsw); nvif_object_dtor(&chan->gart); nvif_object_dtor(&chan->vram); - nvif_notify_dtor(&chan->kill); + nvif_event_dtor(&chan->kill); nvif_object_dtor(&chan->user); nvif_object_dtor(&chan->push.ctxdma); nouveau_vma_del(&chan->push.vma); @@ -391,12 +394,19 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO && chan->user.oclass < AMPERE_CHANNEL_GPFIFO_B) { - ret = nvif_notify_ctor(&chan->user, "abi16ChanKilled", - nouveau_channel_killed, - true, NV906F_V0_NTFY_KILLED, - NULL, 0, 0, &chan->kill); + struct { + struct nvif_event_v0 base; + struct nvif_chan_event_v0 host; + } args; + + args.host.version = 0; + args.host.type = NVIF_CHAN_EVENT_V0_KILLED; + + ret = nvif_event_ctor(&chan->user, "abi16ChanKilled", chan->chid, + nouveau_channel_killed, false, + &args.base, sizeof(args), &chan->kill); if (ret == 0) - ret = nvif_notify_get(&chan->kill); + ret = nvif_event_allow(&chan->kill); if (ret) { NV_ERROR(drm, "Failed to request channel kill " "notification: %d\n", ret); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 98ba9d27e6b4..195b38c84771 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -2,7 +2,7 @@ #ifndef __NOUVEAU_CHAN_H__ #define __NOUVEAU_CHAN_H__ #include -#include +#include #include struct nvif_device; @@ -50,7 +50,7 @@ struct nouveau_channel { struct nvif_object user; - struct nvif_notify kill; + struct nvif_event kill; atomic_t killed; }; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 62560e30febb..c4c8af16af02 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -88,8 +88,9 @@ void nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) { struct nouveau_fence *fence; + unsigned long flags; - spin_lock_irq(&fctx->lock); + spin_lock_irqsave(&fctx->lock, flags); while (!list_empty(&fctx->pending)) { fence = list_entry(fctx->pending.next, typeof(*fence), head); @@ -99,7 +100,7 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) if (nouveau_fence_signal(fence)) nvif_event_block(&fctx->event); } - spin_unlock_irq(&fctx->lock); + spin_unlock_irqrestore(&fctx->lock, flags); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index ec790af9b24f..a5d7c7d0ff7f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -122,26 +121,11 @@ nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags) void nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid) { - nvkm_event_send(&fifo->kevent, 1, chid, NULL, 0); -} - -static int -nvkm_fifo_kevent_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - if (size == 0) { - notify->size = 0; - notify->types = 1; - notify->index = chan->chid; - return 0; - } - return -ENOSYS; + nvkm_event_send(&fifo->kevent, NVKM_FIFO_EVENT_KILLED, chid, NULL, 0); } static const struct nvkm_event_func nvkm_fifo_kevent_func = { - .ctor = nvkm_fifo_kevent_ctor, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 08f09f40defb..39d6b9217f8d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -267,6 +267,9 @@ nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct n case NVIF_CHAN_EVENT_V0_NON_STALL_INTR: return nvkm_uevent_add(uevent, &chan->fifo->uevent, 0, NVKM_FIFO_EVENT_NON_STALL_INTR, NULL); + case NVIF_CHAN_EVENT_V0_KILLED: + return nvkm_uevent_add(uevent, &chan->fifo->kevent, chan->chid, + NVKM_FIFO_EVENT_KILLED, NULL); default: break; } @@ -274,16 +277,6 @@ nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct n return -ENOSYS; } -static int -nvkm_fifo_chan_ntfy(struct nvkm_object *object, u32 type, - struct nvkm_event **pevent) -{ - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - if (chan->func->ntfy) - return chan->func->ntfy(chan, type, pevent); - return -ENODEV; -} - static int nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc, enum nvkm_object_map *type, u64 *addr, u64 *size) @@ -341,7 +334,6 @@ nvkm_fifo_chan_func = { .dtor = nvkm_fifo_chan_dtor, .init = nvkm_fifo_chan_init, .fini = nvkm_fifo_chan_fini, - .ntfy = nvkm_fifo_chan_ntfy, .map = nvkm_fifo_chan_map, .sclass = nvkm_fifo_chan_child_get, .uevent = nvkm_fifo_chan_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index e53504354841..8ef972134f9b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -8,7 +8,6 @@ struct nvkm_fifo_chan_func { void *(*dtor)(struct nvkm_fifo_chan *); void (*init)(struct nvkm_fifo_chan *); void (*fini)(struct nvkm_fifo_chan *); - int (*ntfy)(struct nvkm_fifo_chan *, u32 type, struct nvkm_event **); int (*engine_ctor)(struct nvkm_fifo_chan *, struct nvkm_engine *, struct nvkm_object *); void (*engine_dtor)(struct nvkm_fifo_chan *, struct nvkm_engine *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 569b5eedb84d..4b1f6702680a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -32,20 +32,6 @@ #include #include -int -gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, - struct nvkm_event **pevent) -{ - switch (type) { - case NV906F_V0_NTFY_KILLED: - *pevent = &chan->fifo->kevent; - return 0; - default: - break; - } - return -EINVAL; -} - static u32 gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) { @@ -207,7 +193,6 @@ gf100_fifo_gpfifo_func = { .dtor = gf100_fifo_gpfifo_dtor, .init = gf100_fifo_gpfifo_init, .fini = gf100_fifo_gpfifo_fini, - .ntfy = gf100_fifo_chan_ntfy, .engine_ctor = gf100_fifo_gpfifo_engine_ctor, .engine_dtor = gf100_fifo_gpfifo_engine_dtor, .engine_init = gf100_fifo_gpfifo_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index 80456ec70e8a..ea9852a5fdd8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -246,7 +246,6 @@ gk104_fifo_gpfifo_func = { .dtor = gk104_fifo_gpfifo_dtor, .init = gk104_fifo_gpfifo_init, .fini = gk104_fifo_gpfifo_fini, - .ntfy = gf100_fifo_chan_ntfy, .engine_ctor = gk104_fifo_gpfifo_engine_ctor, .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gk104_fifo_gpfifo_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 428f9b41165c..e8546fed4024 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -125,7 +125,6 @@ gv100_fifo_gpfifo = { .dtor = gk104_fifo_gpfifo_dtor, .init = gk104_fifo_gpfifo_init, .fini = gk104_fifo_gpfifo_fini, - .ntfy = gf100_fifo_chan_ntfy, .engine_ctor = gk104_fifo_gpfifo_engine_ctor, .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gv100_fifo_gpfifo_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c index 99aafa103a31..4d35bee0ab54 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c @@ -40,7 +40,6 @@ tu102_fifo_gpfifo = { .dtor = gk104_fifo_gpfifo_dtor, .init = gk104_fifo_gpfifo_init, .fini = gk104_fifo_gpfifo_fini, - .ntfy = gf100_fifo_chan_ntfy, .engine_ctor = gk104_fifo_gpfifo_engine_ctor, .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gv100_fifo_gpfifo_engine_init, -- cgit v1.2.3 From 99d0701afdaf09ab5eb42b6578f2cc9913e7d85c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:40 +1000 Subject: drm/nouveau/nvkm: rip out old notify Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/event.h | 27 --- drivers/gpu/drm/nouveau/include/nvif/ioctl.h | 51 +---- drivers/gpu/drm/nouveau/include/nvif/notify.h | 35 ---- drivers/gpu/drm/nouveau/include/nvkm/core/client.h | 15 +- drivers/gpu/drm/nouveau/include/nvkm/core/event.h | 9 - drivers/gpu/drm/nouveau/include/nvkm/core/notify.h | 39 ---- drivers/gpu/drm/nouveau/nouveau_drv.h | 5 - drivers/gpu/drm/nouveau/nouveau_nvif.c | 4 +- drivers/gpu/drm/nouveau/nouveau_usif.c | 6 - drivers/gpu/drm/nouveau/nvif/Kbuild | 1 - drivers/gpu/drm/nouveau/nvif/notify.c | 210 --------------------- drivers/gpu/drm/nouveau/nvkm/core/Kbuild | 1 - drivers/gpu/drm/nouveau/nvkm/core/client.c | 127 +------------ drivers/gpu/drm/nouveau/nvkm/core/event.c | 33 +--- drivers/gpu/drm/nouveau/nvkm/core/ioctl.c | 88 --------- drivers/gpu/drm/nouveau/nvkm/core/notify.c | 163 ---------------- drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c | 4 +- drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c | 4 +- drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c | 2 +- 25 files changed, 33 insertions(+), 805 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/notify.h delete mode 100644 drivers/gpu/drm/nouveau/include/nvkm/core/notify.h delete mode 100644 drivers/gpu/drm/nouveau/nvif/notify.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/core/notify.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h index 3afcda2034d6..68bf6635841f 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/event.h +++ b/drivers/gpu/drm/nouveau/include/nvif/event.h @@ -33,31 +33,4 @@ nvif_event_ctor(struct nvif_object *parent, const char *name, u32 handle, nvif_e void nvif_event_dtor(struct nvif_event *); int nvif_event_allow(struct nvif_event *); int nvif_event_block(struct nvif_event *); - -struct nvif_notify_req_v0 { - __u8 version; - __u8 reply; - __u8 pad02[5]; -#define NVIF_NOTIFY_V0_ROUTE_NVIF 0x00 - __u8 route; - __u64 token; /* must be unique */ - __u8 data[]; /* request data (below) */ -}; - -struct nvif_notify_rep_v0 { - __u8 version; - __u8 pad01[6]; - __u8 route; - __u64 token; - __u8 data[]; /* reply data (below) */ -}; - -struct nvif_notify_uevent_req { - /* nvif_notify_req ... */ -}; - -struct nvif_notify_uevent_rep { - /* nvif_notify_rep ... */ -}; - #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h index 886c63fe753f..4e047bb1fc07 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h +++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h @@ -15,10 +15,6 @@ struct nvif_ioctl_v0 { #define NVIF_IOCTL_V0_WR 0x06 #define NVIF_IOCTL_V0_MAP 0x07 #define NVIF_IOCTL_V0_UNMAP 0x08 -#define NVIF_IOCTL_V0_NTFY_NEW 0x09 -#define NVIF_IOCTL_V0_NTFY_DEL 0x0a -#define NVIF_IOCTL_V0_NTFY_GET 0x0b -#define NVIF_IOCTL_V0_NTFY_PUT 0x0c __u8 type; __u8 pad02[4]; #define NVIF_IOCTL_V0_OWNER_NVIF 0x00 @@ -63,6 +59,14 @@ struct nvif_ioctl_new_v0 { struct nvif_ioctl_del { }; +struct nvif_ioctl_mthd_v0 { + /* nvif_ioctl ... */ + __u8 version; + __u8 method; + __u8 pad02[6]; + __u8 data[]; /* method data (class.h) */ +}; + struct nvif_ioctl_rd_v0 { /* nvif_ioctl ... */ __u8 version; @@ -95,43 +99,4 @@ struct nvif_ioctl_map_v0 { struct nvif_ioctl_unmap { }; - -struct nvif_ioctl_ntfy_new_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 event; - __u8 index; - __u8 pad03[5]; - __u8 data[]; /* event request data (event.h) */ -}; - -struct nvif_ioctl_ntfy_del_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 index; - __u8 pad02[6]; -}; - -struct nvif_ioctl_ntfy_get_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 index; - __u8 pad02[6]; -}; - -struct nvif_ioctl_ntfy_put_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 index; - __u8 pad02[6]; -}; - -struct nvif_ioctl_mthd_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 method; - __u8 pad02[6]; - __u8 data[]; /* method data (class.h) */ -}; - #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/notify.h b/drivers/gpu/drm/nouveau/include/nvif/notify.h deleted file mode 100644 index 39f6b7ee1719..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/notify.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_NOTIFY_H__ -#define __NVIF_NOTIFY_H__ - -struct nvif_notify { - struct nvif_object *object; - const char *name; - int index; - -#define NVIF_NOTIFY_USER 0 -#define NVIF_NOTIFY_WORK 1 - unsigned long flags; - atomic_t putcnt; - void (*dtor)(struct nvif_notify *); -#define NVIF_NOTIFY_DROP 0 -#define NVIF_NOTIFY_KEEP 1 - int (*func)(struct nvif_notify *); - - /* this is const for a *very* good reason - the data might be on the - * stack from an irq handler. if you're not nvif/notify.c then you - * should probably think twice before casting it away... - */ - const void *data; - u32 size; - struct work_struct work; -}; - -int nvif_notify_ctor(struct nvif_object *, const char *name, - int (*func)(struct nvif_notify *), bool work, u8 type, - void *data, u32 size, u32 reply, struct nvif_notify *); -int nvif_notify_dtor(struct nvif_notify *); -int nvif_notify_get(struct nvif_notify *); -int nvif_notify_put(struct nvif_notify *); -int nvif_notify(const void *, u32, const void *, u32); -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index 2eb22aaed700..0d9fc741a719 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -10,30 +10,19 @@ struct nvkm_client { u64 device; u32 debug; - struct nvkm_client_notify *notify[32]; struct rb_root objroot; void *data; - int (*ntfy)(const void *, u32, const void *, u32); int (*event)(u64 token, void *argv, u32 argc); struct list_head umem; spinlock_t lock; }; -int nvkm_client_new(const char *name, u64 device, const char *cfg, - const char *dbg, - int (*)(const void *, u32, const void *, u32), - int (*)(u64, void *, u32), - struct nvkm_client **); +int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg, + int (*)(u64, void *, u32), struct nvkm_client **); struct nvkm_client *nvkm_client_search(struct nvkm_client *, u64 handle); -int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *, - void *data, u32 size); -int nvkm_client_notify_del(struct nvkm_client *, int index); -int nvkm_client_notify_get(struct nvkm_client *, int index); -int nvkm_client_notify_put(struct nvkm_client *, int index); - /* logging for client-facing objects */ #define nvif_printk(o,l,p,f,a...) do { \ const struct nvkm_object *_object = (o); \ diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h index d6755a89f587..8e8fb4b6bca4 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h @@ -2,7 +2,6 @@ #ifndef __NVKM_EVENT_H__ #define __NVKM_EVENT_H__ #include -struct nvkm_notify; struct nvkm_object; struct nvkm_oclass; struct nvkm_uevent; @@ -16,16 +15,12 @@ struct nvkm_event { spinlock_t refs_lock; spinlock_t list_lock; - struct list_head list; int *refs; struct list_head ntfy; }; struct nvkm_event_func { - int (*ctor)(struct nvkm_object *, void *data, u32 size, - struct nvkm_notify *); - void (*send)(void *data, u32 size, struct nvkm_notify *); void (*init)(struct nvkm_event *, int type, int index); void (*fini)(struct nvkm_event *, int type, int index); }; @@ -33,10 +28,6 @@ struct nvkm_event_func { int nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr, int index_nr, struct nvkm_event *); void nvkm_event_fini(struct nvkm_event *); -void nvkm_event_get(struct nvkm_event *, u32 types, int index); -void nvkm_event_put(struct nvkm_event *, u32 types, int index); -void nvkm_event_send(struct nvkm_event *, u32 types, int index, - void *data, u32 size); #define NVKM_EVENT_KEEP 0 #define NVKM_EVENT_DROP 1 diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h b/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h deleted file mode 100644 index 3d358a66db3a..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVKM_NOTIFY_H__ -#define __NVKM_NOTIFY_H__ -#include -struct nvkm_object; - -struct nvkm_notify { - struct nvkm_event *event; - struct list_head head; -#define NVKM_NOTIFY_USER 0 -#define NVKM_NOTIFY_WORK 1 - unsigned long flags; - int block; -#define NVKM_NOTIFY_DROP 0 -#define NVKM_NOTIFY_KEEP 1 - int (*func)(struct nvkm_notify *); - - /* set by nvkm_event ctor */ - u32 types; - int index; - u32 size; - - struct work_struct work; - /* this is const for a *very* good reason - the data might be on the - * stack from an irq handler. if you're not core/notify.c then you - * should probably think twice before casting it away... - */ - const void *data; -}; - -int nvkm_notify_init(struct nvkm_object *, struct nvkm_event *, - int (*func)(struct nvkm_notify *), bool work, - void *data, u32 size, u32 reply, - struct nvkm_notify *); -void nvkm_notify_fini(struct nvkm_notify *); -void nvkm_notify_get(struct nvkm_notify *); -void nvkm_notify_put(struct nvkm_notify *); -void nvkm_notify_send(struct nvkm_notify *, void *data, u32 size); -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 1a92c980cb73..2b9045b12ac7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -78,11 +78,6 @@ enum nouveau_drm_object_route { NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY, }; -enum nouveau_drm_notify_route { - NVDRM_NOTIFY_NVIF = 0, - NVDRM_NOTIFY_USIF -}; - enum nouveau_drm_handle { NVDRM_CHAN = 0xcccc0000, /* |= client chid */ NVDRM_NVSW = 0x55550000, diff --git a/drivers/gpu/drm/nouveau/nouveau_nvif.c b/drivers/gpu/drm/nouveau/nouveau_nvif.c index be6d404a3459..1d49ebdfd5dc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_nvif.c +++ b/drivers/gpu/drm/nouveau/nouveau_nvif.c @@ -27,12 +27,10 @@ ******************************************************************************/ #include -#include #include #include #include -#include #include #include @@ -87,7 +85,7 @@ static int nvkm_client_driver_init(const char *name, u64 device, const char *cfg, const char *dbg, void **ppriv) { - return nvkm_client_new(name, device, cfg, dbg, nvif_notify, nvkm_client_event, + return nvkm_client_new(name, device, cfg, dbg, nvkm_client_event, (struct nvkm_client **)ppriv); } diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c index 36df6840c099..002d1479ba89 100644 --- a/drivers/gpu/drm/nouveau/nouveau_usif.c +++ b/drivers/gpu/drm/nouveau/nouveau_usif.c @@ -151,12 +151,6 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) case NVIF_IOCTL_V0_NEW: ret = usif_object_new(filp, data, size, argv, argc, abi16); break; - case NVIF_IOCTL_V0_NTFY_NEW: - case NVIF_IOCTL_V0_NTFY_DEL: - case NVIF_IOCTL_V0_NTFY_GET: - case NVIF_IOCTL_V0_NTFY_PUT: - ret = -ENOSYS; - break; default: ret = nvif_client_ioctl(client, argv, argc); break; diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild index 7ce040ca2394..b7963a39dd91 100644 --- a/drivers/gpu/drm/nouveau/nvif/Kbuild +++ b/drivers/gpu/drm/nouveau/nvif/Kbuild @@ -10,7 +10,6 @@ nvif-y += nvif/fifo.o nvif-y += nvif/head.o nvif-y += nvif/mem.o nvif-y += nvif/mmu.o -nvif-y += nvif/notify.o nvif-y += nvif/outp.o nvif-y += nvif/timer.o nvif-y += nvif/vmm.o diff --git a/drivers/gpu/drm/nouveau/nvif/notify.c b/drivers/gpu/drm/nouveau/nvif/notify.c deleted file mode 100644 index 143c8dc6889e..000000000000 --- a/drivers/gpu/drm/nouveau/nvif/notify.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2014 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include -#include -#include -#include -#include -#include - -static inline int -nvif_notify_put_(struct nvif_notify *notify) -{ - struct nvif_object *object = notify->object; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_ntfy_put_v0 ntfy; - } args = { - .ioctl.type = NVIF_IOCTL_V0_NTFY_PUT, - .ntfy.index = notify->index, - }; - - if (atomic_inc_return(¬ify->putcnt) != 1) - return 0; - - return nvif_object_ioctl(object, &args, sizeof(args), NULL); -} - -int -nvif_notify_put(struct nvif_notify *notify) -{ - if (likely(notify->object) && - test_and_clear_bit(NVIF_NOTIFY_USER, ¬ify->flags)) { - int ret = nvif_notify_put_(notify); - if (test_bit(NVIF_NOTIFY_WORK, ¬ify->flags)) - flush_work(¬ify->work); - return ret; - } - return 0; -} - -static inline int -nvif_notify_get_(struct nvif_notify *notify) -{ - struct nvif_object *object = notify->object; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_ntfy_get_v0 ntfy; - } args = { - .ioctl.type = NVIF_IOCTL_V0_NTFY_GET, - .ntfy.index = notify->index, - }; - - if (atomic_dec_return(¬ify->putcnt) != 0) - return 0; - - return nvif_object_ioctl(object, &args, sizeof(args), NULL); -} - -int -nvif_notify_get(struct nvif_notify *notify) -{ - if (likely(notify->object) && - !test_and_set_bit(NVIF_NOTIFY_USER, ¬ify->flags)) - return nvif_notify_get_(notify); - return 0; -} - -static inline int -nvif_notify_func(struct nvif_notify *notify, bool keep) -{ - int ret = notify->func(notify); - if (ret == NVIF_NOTIFY_KEEP || - !test_and_clear_bit(NVIF_NOTIFY_USER, ¬ify->flags)) { - if (!keep) - atomic_dec(¬ify->putcnt); - else - nvif_notify_get_(notify); - } - return ret; -} - -static void -nvif_notify_work(struct work_struct *work) -{ - struct nvif_notify *notify = container_of(work, typeof(*notify), work); - nvif_notify_func(notify, true); -} - -int -nvif_notify(const void *header, u32 length, const void *data, u32 size) -{ - struct nvif_notify *notify = NULL; - const union { - struct nvif_notify_rep_v0 v0; - } *args = header; - int ret = NVIF_NOTIFY_DROP; - - if (length == sizeof(args->v0) && args->v0.version == 0) { - if (WARN_ON(args->v0.route)) - return NVIF_NOTIFY_DROP; - notify = (void *)(unsigned long)args->v0.token; - } - - if (!WARN_ON(notify == NULL)) { - struct nvif_client *client = notify->object->client; - if (!WARN_ON(notify->size != size)) { - atomic_inc(¬ify->putcnt); - if (test_bit(NVIF_NOTIFY_WORK, ¬ify->flags)) { - memcpy((void *)notify->data, data, size); - schedule_work(¬ify->work); - return NVIF_NOTIFY_DROP; - } - notify->data = data; - ret = nvif_notify_func(notify, client->driver->keep); - notify->data = NULL; - } - } - - return ret; -} - -int -nvif_notify_dtor(struct nvif_notify *notify) -{ - struct nvif_object *object = notify->object; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_ntfy_del_v0 ntfy; - } args = { - .ioctl.type = NVIF_IOCTL_V0_NTFY_DEL, - .ntfy.index = notify->index, - }; - int ret = nvif_notify_put(notify); - if (ret >= 0 && object) { - ret = nvif_object_ioctl(object, &args, sizeof(args), NULL); - notify->object = NULL; - kfree((void *)notify->data); - } - return ret; -} - -int -nvif_notify_ctor(struct nvif_object *object, const char *name, - int (*func)(struct nvif_notify *), bool work, u8 event, - void *data, u32 size, u32 reply, struct nvif_notify *notify) -{ - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_ntfy_new_v0 ntfy; - struct nvif_notify_req_v0 req; - } *args; - int ret = -ENOMEM; - - notify->object = object; - notify->name = name ? name : "nvifNotify"; - notify->flags = 0; - atomic_set(¬ify->putcnt, 1); - notify->func = func; - notify->data = NULL; - notify->size = reply; - if (work) { - INIT_WORK(¬ify->work, nvif_notify_work); - set_bit(NVIF_NOTIFY_WORK, ¬ify->flags); - notify->data = kmalloc(notify->size, GFP_KERNEL); - if (!notify->data) - goto done; - } - - if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL))) - goto done; - args->ioctl.version = 0; - args->ioctl.type = NVIF_IOCTL_V0_NTFY_NEW; - args->ntfy.version = 0; - args->ntfy.event = event; - args->req.version = 0; - args->req.reply = notify->size; - args->req.route = 0; - args->req.token = (unsigned long)(void *)notify; - - memcpy(args->req.data, data, size); - ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL); - notify->index = args->ntfy.index; - kfree(args); -done: - if (ret) - nvif_notify_dtor(notify); - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild index 216a3db821ee..65dad05f047c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild @@ -8,7 +8,6 @@ nvkm-y += nvkm/core/gpuobj.o nvkm-y += nvkm/core/ioctl.o nvkm-y += nvkm/core/memory.o nvkm-y += nvkm/core/mm.o -nvkm-y += nvkm/core/notify.o nvkm-y += nvkm/core/object.o nvkm-y += nvkm/core/oproxy.o nvkm-y += nvkm/core/option.o diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index e1d978fbfe72..ebdeb8eb9e77 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -23,7 +23,6 @@ */ #include #include -#include #include #include @@ -44,7 +43,7 @@ nvkm_uclient_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))){ args->v0.name[sizeof(args->v0.name) - 1] = 0; ret = nvkm_client_new(args->v0.name, args->v0.device, NULL, - NULL, oclass->client->ntfy, oclass->client->event, &client); + NULL, oclass->client->event, &client); if (ret) return ret; } else @@ -68,113 +67,6 @@ nvkm_uclient_sclass = { .ctor = nvkm_uclient_new, }; -struct nvkm_client_notify { - struct nvkm_client *client; - struct nvkm_notify n; - u8 version; - u8 size; - union { - struct nvif_notify_rep_v0 v0; - } rep; -}; - -static int -nvkm_client_notify(struct nvkm_notify *n) -{ - struct nvkm_client_notify *notify = container_of(n, typeof(*notify), n); - struct nvkm_client *client = notify->client; - return client->ntfy(¬ify->rep, notify->size, n->data, n->size); -} - -int -nvkm_client_notify_put(struct nvkm_client *client, int index) -{ - if (index < ARRAY_SIZE(client->notify)) { - if (client->notify[index]) { - nvkm_notify_put(&client->notify[index]->n); - return 0; - } - } - return -ENOENT; -} - -int -nvkm_client_notify_get(struct nvkm_client *client, int index) -{ - if (index < ARRAY_SIZE(client->notify)) { - if (client->notify[index]) { - nvkm_notify_get(&client->notify[index]->n); - return 0; - } - } - return -ENOENT; -} - -int -nvkm_client_notify_del(struct nvkm_client *client, int index) -{ - if (index < ARRAY_SIZE(client->notify)) { - if (client->notify[index]) { - nvkm_notify_fini(&client->notify[index]->n); - kfree(client->notify[index]); - client->notify[index] = NULL; - return 0; - } - } - return -ENOENT; -} - -int -nvkm_client_notify_new(struct nvkm_object *object, - struct nvkm_event *event, void *data, u32 size) -{ - struct nvkm_client *client = object->client; - struct nvkm_client_notify *notify; - union { - struct nvif_notify_req_v0 v0; - } *req = data; - u8 index, reply; - int ret = -ENOSYS; - - for (index = 0; index < ARRAY_SIZE(client->notify); index++) { - if (!client->notify[index]) - break; - } - - if (index == ARRAY_SIZE(client->notify)) - return -ENOSPC; - - notify = kzalloc(sizeof(*notify), GFP_KERNEL); - if (!notify) - return -ENOMEM; - - nvif_ioctl(object, "notify new size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, true))) { - nvif_ioctl(object, "notify new vers %d reply %d route %02x " - "token %llx\n", req->v0.version, - req->v0.reply, req->v0.route, req->v0.token); - notify->version = req->v0.version; - notify->size = sizeof(notify->rep.v0); - notify->rep.v0.version = req->v0.version; - notify->rep.v0.route = req->v0.route; - notify->rep.v0.token = req->v0.token; - reply = req->v0.reply; - } - - if (ret == 0) { - ret = nvkm_notify_init(object, event, nvkm_client_notify, - false, data, size, reply, ¬ify->n); - if (ret == 0) { - client->notify[index] = notify; - notify->client = client; - return index; - } - } - - kfree(notify); - return ret; -} - static const struct nvkm_object_func nvkm_client; struct nvkm_client * nvkm_client_search(struct nvkm_client *client, u64 handle) @@ -255,23 +147,13 @@ nvkm_client_child_get(struct nvkm_object *object, int index, static int nvkm_client_fini(struct nvkm_object *object, bool suspend) { - struct nvkm_client *client = nvkm_client(object); - const char *name[2] = { "fini", "suspend" }; - int i; - nvif_debug(object, "%s notify\n", name[suspend]); - for (i = 0; i < ARRAY_SIZE(client->notify); i++) - nvkm_client_notify_put(client, i); return 0; } static void * nvkm_client_dtor(struct nvkm_object *object) { - struct nvkm_client *client = nvkm_client(object); - int i; - for (i = 0; i < ARRAY_SIZE(client->notify); i++) - nvkm_client_notify_del(client, i); - return client; + return nvkm_client(object); } static const struct nvkm_object_func @@ -283,9 +165,7 @@ nvkm_client = { }; int -nvkm_client_new(const char *name, u64 device, const char *cfg, - const char *dbg, - int (*ntfy)(const void *, u32, const void *, u32), +nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg, int (*event)(u64, void *, u32), struct nvkm_client **pclient) { struct nvkm_oclass oclass = { .base = nvkm_uclient_sclass }; @@ -300,7 +180,6 @@ nvkm_client_new(const char *name, u64 device, const char *cfg, client->device = device; client->debug = nvkm_dbgopt(dbg, "CLIENT"); client->objroot = RB_ROOT; - client->ntfy = ntfy; client->event = event; INIT_LIST_HEAD(&client->umem); spin_lock_init(&client->lock); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/event.c b/drivers/gpu/drm/nouveau/nvkm/core/event.c index ec508d1bbe1d..622df36391be 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/event.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/event.c @@ -20,10 +20,9 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include -#include #include -void +static void nvkm_event_put(struct nvkm_event *event, u32 types, int index) { assert_spin_locked(&event->refs_lock); @@ -40,7 +39,7 @@ nvkm_event_put(struct nvkm_event *event, u32 types, int index) } } -void +static void nvkm_event_get(struct nvkm_event *event, u32 types, int index) { assert_spin_locked(&event->refs_lock); @@ -171,8 +170,13 @@ void nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits) { struct nvkm_event_ntfy *ntfy, *ntmp; + unsigned long flags; + + if (!event->refs || WARN_ON(id >= event->index_nr)) + return; nvkm_trace(event->subdev, "event: ntfy %08x on %d\n", bits, id); + spin_lock_irqsave(&event->list_lock, flags); list_for_each_entry_safe(ntfy, ntmp, &event->ntfy, head) { if (ntfy->id == id && ntfy->bits & bits) { @@ -180,29 +184,7 @@ nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits) ntfy->func(ntfy, ntfy->bits & bits); } } -} -void -nvkm_event_send(struct nvkm_event *event, u32 types, int index, void *data, u32 size) -{ - struct nvkm_notify *notify; - unsigned long flags; - - if (!event->refs || WARN_ON(index >= event->index_nr)) - return; - - spin_lock_irqsave(&event->list_lock, flags); - nvkm_event_ntfy(event, index, types); - - list_for_each_entry(notify, &event->list, head) { - if (notify->index == index && (notify->types & types)) { - if (event->func->send) { - event->func->send(data, size, notify); - continue; - } - nvkm_notify_send(notify, data, size); - } - } spin_unlock_irqrestore(&event->list_lock, flags); } @@ -229,7 +211,6 @@ nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev, event->index_nr = index_nr; spin_lock_init(&event->refs_lock); spin_lock_init(&event->list_lock); - INIT_LIST_HEAD(&event->list); INIT_LIST_HEAD(&event->ntfy); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c index b42d0bf2c492..0b33287e43a7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c @@ -313,90 +313,6 @@ nvkm_ioctl_unmap(struct nvkm_client *client, return ret; } -static int -nvkm_ioctl_ntfy_new(struct nvkm_client *client, - struct nvkm_object *object, void *data, u32 size) -{ - union { - struct nvif_ioctl_ntfy_new_v0 v0; - } *args = data; - struct nvkm_event *event; - int ret = -ENOSYS; - - nvif_ioctl(object, "ntfy new size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - nvif_ioctl(object, "ntfy new vers %d event %02x\n", - args->v0.version, args->v0.event); - ret = nvkm_object_ntfy(object, args->v0.event, &event); - if (ret == 0) { - ret = nvkm_client_notify_new(object, event, data, size); - if (ret >= 0) { - args->v0.index = ret; - ret = 0; - } - } - } - - return ret; -} - -static int -nvkm_ioctl_ntfy_del(struct nvkm_client *client, - struct nvkm_object *object, void *data, u32 size) -{ - union { - struct nvif_ioctl_ntfy_del_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(object, "ntfy del size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "ntfy del vers %d index %d\n", - args->v0.version, args->v0.index); - ret = nvkm_client_notify_del(client, args->v0.index); - } - - return ret; -} - -static int -nvkm_ioctl_ntfy_get(struct nvkm_client *client, - struct nvkm_object *object, void *data, u32 size) -{ - union { - struct nvif_ioctl_ntfy_get_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(object, "ntfy get size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "ntfy get vers %d index %d\n", - args->v0.version, args->v0.index); - ret = nvkm_client_notify_get(client, args->v0.index); - } - - return ret; -} - -static int -nvkm_ioctl_ntfy_put(struct nvkm_client *client, - struct nvkm_object *object, void *data, u32 size) -{ - union { - struct nvif_ioctl_ntfy_put_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(object, "ntfy put size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "ntfy put vers %d index %d\n", - args->v0.version, args->v0.index); - ret = nvkm_client_notify_put(client, args->v0.index); - } - - return ret; -} - static struct { int version; int (*func)(struct nvkm_client *, struct nvkm_object *, void *, u32); @@ -411,10 +327,6 @@ nvkm_ioctl_v0[] = { { 0x00, nvkm_ioctl_wr }, { 0x00, nvkm_ioctl_map }, { 0x00, nvkm_ioctl_unmap }, - { 0x00, nvkm_ioctl_ntfy_new }, - { 0x00, nvkm_ioctl_ntfy_del }, - { 0x00, nvkm_ioctl_ntfy_get }, - { 0x00, nvkm_ioctl_ntfy_put }, }; static int diff --git a/drivers/gpu/drm/nouveau/nvkm/core/notify.c b/drivers/gpu/drm/nouveau/nvkm/core/notify.c deleted file mode 100644 index 023610d01458..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/core/notify.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2014 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include -#include - -static inline void -nvkm_notify_put_locked(struct nvkm_notify *notify) -{ - if (notify->block++ == 0) - nvkm_event_put(notify->event, notify->types, notify->index); -} - -void -nvkm_notify_put(struct nvkm_notify *notify) -{ - struct nvkm_event *event = notify->event; - unsigned long flags; - if (likely(event) && - test_and_clear_bit(NVKM_NOTIFY_USER, ¬ify->flags)) { - spin_lock_irqsave(&event->refs_lock, flags); - nvkm_notify_put_locked(notify); - spin_unlock_irqrestore(&event->refs_lock, flags); - if (test_bit(NVKM_NOTIFY_WORK, ¬ify->flags)) - flush_work(¬ify->work); - } -} - -static inline void -nvkm_notify_get_locked(struct nvkm_notify *notify) -{ - if (--notify->block == 0) - nvkm_event_get(notify->event, notify->types, notify->index); -} - -void -nvkm_notify_get(struct nvkm_notify *notify) -{ - struct nvkm_event *event = notify->event; - unsigned long flags; - if (likely(event) && - !test_and_set_bit(NVKM_NOTIFY_USER, ¬ify->flags)) { - spin_lock_irqsave(&event->refs_lock, flags); - nvkm_notify_get_locked(notify); - spin_unlock_irqrestore(&event->refs_lock, flags); - } -} - -static inline void -nvkm_notify_func(struct nvkm_notify *notify) -{ - struct nvkm_event *event = notify->event; - int ret = notify->func(notify); - unsigned long flags; - if ((ret == NVKM_NOTIFY_KEEP) || - !test_and_clear_bit(NVKM_NOTIFY_USER, ¬ify->flags)) { - spin_lock_irqsave(&event->refs_lock, flags); - nvkm_notify_get_locked(notify); - spin_unlock_irqrestore(&event->refs_lock, flags); - } -} - -static void -nvkm_notify_work(struct work_struct *work) -{ - struct nvkm_notify *notify = container_of(work, typeof(*notify), work); - nvkm_notify_func(notify); -} - -void -nvkm_notify_send(struct nvkm_notify *notify, void *data, u32 size) -{ - struct nvkm_event *event = notify->event; - unsigned long flags; - - assert_spin_locked(&event->list_lock); - BUG_ON(size != notify->size); - - spin_lock_irqsave(&event->refs_lock, flags); - if (notify->block) { - spin_unlock_irqrestore(&event->refs_lock, flags); - return; - } - nvkm_notify_put_locked(notify); - spin_unlock_irqrestore(&event->refs_lock, flags); - - if (test_bit(NVKM_NOTIFY_WORK, ¬ify->flags)) { - memcpy((void *)notify->data, data, size); - schedule_work(¬ify->work); - } else { - notify->data = data; - nvkm_notify_func(notify); - notify->data = NULL; - } -} - -void -nvkm_notify_fini(struct nvkm_notify *notify) -{ - unsigned long flags; - if (notify->event) { - nvkm_notify_put(notify); - spin_lock_irqsave(¬ify->event->list_lock, flags); - list_del(¬ify->head); - spin_unlock_irqrestore(¬ify->event->list_lock, flags); - kfree((void *)notify->data); - notify->event = NULL; - } -} - -int -nvkm_notify_init(struct nvkm_object *object, struct nvkm_event *event, - int (*func)(struct nvkm_notify *), bool work, - void *data, u32 size, u32 reply, - struct nvkm_notify *notify) -{ - unsigned long flags; - int ret = -ENODEV; - if ((notify->event = event), event->refs) { - ret = event->func->ctor(object, data, size, notify); - if (ret == 0 && (ret = -EINVAL, notify->size == reply)) { - notify->flags = 0; - notify->block = 1; - notify->func = func; - notify->data = NULL; - if (ret = 0, work) { - INIT_WORK(¬ify->work, nvkm_notify_work); - set_bit(NVKM_NOTIFY_WORK, ¬ify->flags); - notify->data = kmalloc(reply, GFP_KERNEL); - if (!notify->data) - ret = -ENOMEM; - } - } - if (ret == 0) { - spin_lock_irqsave(&event->list_lock, flags); - list_add_tail(¬ify->head, &event->list); - spin_unlock_irqrestore(&event->list_lock, flags); - } - } - if (ret) - notify->event = NULL; - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index c1d81cf74c57..73104b59f97f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -65,7 +65,7 @@ nvkm_disp_vblank_func = { void nvkm_disp_vblank(struct nvkm_disp *disp, int head) { - nvkm_event_send(&disp->vblank, NVKM_DISP_HEAD_EVENT_VBLANK, head, NULL, 0); + nvkm_event_ntfy(&disp->vblank, head, NVKM_DISP_HEAD_EVENT_VBLANK); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 55ac6d70e950..be8116802960 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -503,7 +503,7 @@ nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) void nv50_disp_chan_uevent_send(struct nvkm_disp *disp, int chid) { - nvkm_event_send(&disp->uevent, NVKM_DISP_EVENT_CHAN_AWAKEN, chid, NULL, 0); + nvkm_event_ntfy(&disp->uevent, chid, NVKM_DISP_EVENT_CHAN_AWAKEN); } const struct nvkm_event_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index a5d7c7d0ff7f..518f3c492f01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -121,7 +121,7 @@ nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags) void nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid) { - nvkm_event_send(&fifo->kevent, NVKM_FIFO_EVENT_KILLED, chid, NULL, 0); + nvkm_event_ntfy(&fifo->kevent, chid, NVKM_FIFO_EVENT_KILLED); } static const struct nvkm_event_func @@ -151,7 +151,7 @@ nvkm_fifo_uevent_func = { void nvkm_fifo_uevent(struct nvkm_fifo *fifo) { - nvkm_event_send(&fifo->uevent, NVKM_FIFO_EVENT_NON_STALL_INTR, 0, NULL, 0); + nvkm_event_ntfy(&fifo->uevent, 0, NVKM_FIFO_EVENT_NON_STALL_INTR); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c index 5e65e13b0053..834b8cbed51d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c @@ -35,7 +35,7 @@ nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data) case 0x0000: return true; case 0x0500: - nvkm_event_send(&chan->event, NVKM_SW_CHAN_EVENT_PAGE_FLIP, 0, NULL, 0); + nvkm_event_ntfy(&chan->event, 0, NVKM_SW_CHAN_EVENT_PAGE_FLIP); return true; default: if (chan->func->mthd) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c index a96a1d633cb3..04c7526888bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c @@ -65,7 +65,7 @@ gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer) void gp100_fault_intr(struct nvkm_fault *fault) { - nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0); + nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING); } static const struct nvkm_fault_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c index 21756d65663b..8e34d40e7649 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c @@ -166,14 +166,14 @@ gv100_fault_intr(struct nvkm_fault *fault) if (stat & 0x20000000) { if (fault->buffer[0]) { - nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0); + nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING); stat &= ~0x20000000; } } if (stat & 0x08000000) { if (fault->buffer[1]) { - nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 1, NULL, 0); + nvkm_event_ntfy(&fault->event, 1, NVKM_FAULT_BUFFER_EVENT_PENDING); stat &= ~0x08000000; } } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c index 2d3660d21b9a..917a7343db31 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c @@ -126,7 +126,7 @@ tu102_fault_intr(struct nvkm_fault *fault) nvkm_wr32(device, 0xb81010, 0x10); if (fault->buffer[0]) { - nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0); + nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING); stat &= ~0x00000200; } } @@ -137,7 +137,7 @@ tu102_fault_intr(struct nvkm_fault *fault) nvkm_wr32(device, 0xb81008, 0x1); if (fault->buffer[1]) { - nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 1, NULL, 0); + nvkm_event_ntfy(&fault->event, 1, NVKM_FAULT_BUFFER_EVENT_PENDING); stat &= ~0x00000100; } } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c index 2c2c23b8663b..b196baa376dc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c @@ -139,7 +139,7 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev) for (i = 0; (hi | lo) && i < gpio->func->lines; i++) { u32 mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) | (NVKM_GPIO_LO * !!(lo & (1 << i))); - nvkm_event_send(&gpio->event, mask, i, NULL, 0); + nvkm_event_ntfy(&gpio->event, i, mask); } } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index feb7de985d2d..976539de4220 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -130,7 +130,7 @@ nvkm_i2c_intr(struct nvkm_subdev *subdev) if (rq & aux->intr) mask |= NVKM_I2C_IRQ; if (tx & aux->intr) mask |= NVKM_I2C_DONE; if (mask) - nvkm_event_send(&i2c->event, mask, aux->id, NULL, 0); + nvkm_event_ntfy(&i2c->event, aux->id, mask); } } -- cgit v1.2.3 From 4a16dd9d18a04742292cc7bfdbb79aedfe24e2c8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:40 +1000 Subject: drm/nouveau/kms: switch to drm fbdev helpers This removes support for accelerated fbcon rendering, and fixes a number of races/crashes/issues around suspend/resume/module unload etc. Losing HW accelerated rendering isn't ideal, but it's been significantly reduced in performance since the removal of accelerated scrolling in the kernel anyway - not to mention, can be racey (skips cpu<->gpu sync) from certain contexts. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Kbuild | 4 - drivers/gpu/drm/nouveau/dispnv04/crtc.c | 10 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 3 +- drivers/gpu/drm/nouveau/nouveau_display.c | 10 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 14 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 3 - drivers/gpu/drm/nouveau/nouveau_fbcon.c | 614 ------------------------------ drivers/gpu/drm/nouveau/nouveau_fbcon.h | 82 ---- drivers/gpu/drm/nouveau/nouveau_vga.c | 1 - drivers/gpu/drm/nouveau/nv04_fbcon.c | 259 ------------- drivers/gpu/drm/nouveau/nv50_fbcon.c | 299 --------------- drivers/gpu/drm/nouveau/nvc0_fbcon.c | 297 --------------- 12 files changed, 15 insertions(+), 1581 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/nouveau_fbcon.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_fbcon.h delete mode 100644 drivers/gpu/drm/nouveau/nv04_fbcon.c delete mode 100644 drivers/gpu/drm/nouveau/nv50_fbcon.c delete mode 100644 drivers/gpu/drm/nouveau/nvc0_fbcon.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index 60586fb8275e..5e5617006da5 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild @@ -54,10 +54,6 @@ nouveau-y += nouveau_bios.o nouveau-y += nouveau_connector.o nouveau-y += nouveau_display.o nouveau-y += nouveau_dp.o -nouveau-y += nouveau_fbcon.o -nouveau-y += nv04_fbcon.o -nouveau-y += nv50_fbcon.o -nouveau-y += nvc0_fbcon.o include $(src)/dispnv04/Kbuild include $(src)/dispnv50/Kbuild diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 4e8b84f59280..0e0f117bc70b 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -23,6 +23,7 @@ * DEALINGS IN THE SOFTWARE. */ #include +#include #include #include #include @@ -37,7 +38,6 @@ #include "nouveau_crtc.h" #include "hw.h" #include "nvreg.h" -#include "nouveau_fbcon.h" #include "disp.h" #include "nouveau_dma.h" @@ -915,14 +915,6 @@ nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, enum mode_set_atomic state) { - struct nouveau_drm *drm = nouveau_drm(crtc->dev); - struct drm_device *dev = drm->dev; - - if (state == ENTER_ATOMIC_MODE_SET) - nouveau_fbcon_accel_save_disable(dev); - else - nouveau_fbcon_accel_restore(dev); - return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index e720c01841b2..b7084c17f9c1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -64,7 +64,6 @@ #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_fence.h" -#include "nouveau_fbcon.h" #include @@ -2446,7 +2445,7 @@ nv50_disp_atomic_state_alloc(struct drm_device *dev) static const struct drm_mode_config_funcs nv50_disp_func = { .fb_create = nouveau_user_framebuffer_create, - .output_poll_changed = nouveau_fbcon_output_poll_changed, + .output_poll_changed = drm_fb_helper_output_poll_changed, .atomic_check = nv50_disp_atomic_check, .atomic_commit = nv50_disp_atomic_commit, .atomic_state_alloc = nv50_disp_atomic_state_alloc, diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 55099d9ce1c8..ec3ffff487fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -35,7 +35,6 @@ #include #include -#include "nouveau_fbcon.h" #include "nouveau_crtc.h" #include "nouveau_gem.h" #include "nouveau_connector.h" @@ -392,7 +391,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev, static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { .fb_create = nouveau_user_framebuffer_create, - .output_poll_changed = nouveau_fbcon_output_poll_changed, + .output_poll_changed = drm_fb_helper_output_poll_changed, }; @@ -788,6 +787,9 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime) { struct nouveau_display *disp = nouveau_display(dev); + /* Disable console. */ + drm_fb_helper_set_suspend_unlocked(dev->fb_helper, true); + if (drm_drv_uses_atomic_modeset(dev)) { if (!runtime) { disp->suspend = drm_atomic_helper_suspend(dev); @@ -815,8 +817,10 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) drm_atomic_helper_resume(dev, disp->suspend); disp->suspend = NULL; } - return; } + + /* Enable console. */ + drm_fb_helper_set_suspend_unlocked(dev->fb_helper, false); } int diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index fd99ec0f4257..9df276bff3c7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -62,7 +63,6 @@ #include "nouveau_bios.h" #include "nouveau_ioctl.h" #include "nouveau_abi16.h" -#include "nouveau_fbcon.h" #include "nouveau_fence.h" #include "nouveau_debugfs.h" #include "nouveau_usif.h" @@ -611,7 +611,6 @@ nouveau_drm_device_init(struct drm_device *dev) nouveau_hwmon_init(dev); nouveau_svm_init(drm); nouveau_dmem_init(drm); - nouveau_fbcon_init(dev); nouveau_led_init(dev); if (nouveau_pmops_runtime()) { @@ -655,7 +654,6 @@ nouveau_drm_device_fini(struct drm_device *dev) } nouveau_led_fini(dev); - nouveau_fbcon_fini(dev); nouveau_dmem_fini(drm); nouveau_svm_fini(drm); nouveau_hwmon_fini(dev); @@ -809,6 +807,11 @@ static int nouveau_drm_probe(struct pci_dev *pdev, if (ret) goto fail_drm_dev_init; + if (nouveau_drm(drm_dev)->client.device.info.ram_size <= 32 * 1024 * 1024) + drm_fbdev_generic_setup(drm_dev, 8); + else + drm_fbdev_generic_setup(drm_dev, 32); + quirk_broken_nv_runpm(pdev); return 0; @@ -865,8 +868,6 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) nouveau_led_suspend(dev); if (dev->mode_config.num_crtc) { - NV_DEBUG(drm, "suspending console...\n"); - nouveau_fbcon_set_suspend(dev, 1); NV_DEBUG(drm, "suspending display...\n"); ret = nouveau_display_suspend(dev, runtime); if (ret) @@ -940,8 +941,6 @@ nouveau_do_resume(struct drm_device *dev, bool runtime) if (dev->mode_config.num_crtc) { NV_DEBUG(drm, "resuming display...\n"); nouveau_display_resume(dev, runtime); - NV_DEBUG(drm, "resuming console...\n"); - nouveau_fbcon_set_suspend(dev, 0); } nouveau_led_resume(dev); @@ -1296,7 +1295,6 @@ static void nouveau_display_options(void) DRM_DEBUG_DRIVER("... tv_disable : %d\n", nouveau_tv_disable); DRM_DEBUG_DRIVER("... ignorelid : %d\n", nouveau_ignorelid); DRM_DEBUG_DRIVER("... duallink : %d\n", nouveau_duallink); - DRM_DEBUG_DRIVER("... nofbaccel : %d\n", nouveau_nofbaccel); DRM_DEBUG_DRIVER("... config : %s\n", nouveau_config); DRM_DEBUG_DRIVER("... debug : %s\n", nouveau_debug); DRM_DEBUG_DRIVER("... noaccel : %d\n", nouveau_noaccel); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 2b9045b12ac7..6fb636020f7f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -183,7 +183,6 @@ struct nouveau_drm { struct nouveau_channel *cechan; struct nouveau_channel *channel; struct nvkm_gpuobj *notify; - struct nouveau_fbdev *fbcon; struct nvif_object ntfy; /* nv10-nv40 tiling regions */ @@ -198,8 +197,6 @@ struct nouveau_drm { struct work_struct hpd_work; spinlock_t hpd_lock; u32 hpd_pending; - struct work_struct fbcon_work; - int fbcon_new_state; #ifdef CONFIG_ACPI struct notifier_block acpi_nb; #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c deleted file mode 100644 index 3c7e0c9d6baf..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright © 2007 David Airlie - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * David Airlie - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "nouveau_drv.h" -#include "nouveau_gem.h" -#include "nouveau_bo.h" -#include "nouveau_fbcon.h" -#include "nouveau_chan.h" -#include "nouveau_vmm.h" - -#include "nouveau_crtc.h" - -MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); -int nouveau_nofbaccel = 0; -module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); - -MODULE_PARM_DESC(fbcon_bpp, "fbcon bits-per-pixel (default: auto)"); -static int nouveau_fbcon_bpp; -module_param_named(fbcon_bpp, nouveau_fbcon_bpp, int, 0400); - -static void -nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - struct nvif_device *device = &drm->client.device; - int ret; - - if (info->state != FBINFO_STATE_RUNNING) - return; - - ret = -ENODEV; - if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&drm->client.mutex)) { - if (device->info.family < NV_DEVICE_INFO_V0_TESLA) - ret = nv04_fbcon_fillrect(info, rect); - else - if (device->info.family < NV_DEVICE_INFO_V0_FERMI) - ret = nv50_fbcon_fillrect(info, rect); - else - ret = nvc0_fbcon_fillrect(info, rect); - mutex_unlock(&drm->client.mutex); - } - - if (ret == 0) - return; - - if (ret != -ENODEV) - nouveau_fbcon_gpu_lockup(info); - drm_fb_helper_cfb_fillrect(info, rect); -} - -static void -nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - struct nvif_device *device = &drm->client.device; - int ret; - - if (info->state != FBINFO_STATE_RUNNING) - return; - - ret = -ENODEV; - if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&drm->client.mutex)) { - if (device->info.family < NV_DEVICE_INFO_V0_TESLA) - ret = nv04_fbcon_copyarea(info, image); - else - if (device->info.family < NV_DEVICE_INFO_V0_FERMI) - ret = nv50_fbcon_copyarea(info, image); - else - ret = nvc0_fbcon_copyarea(info, image); - mutex_unlock(&drm->client.mutex); - } - - if (ret == 0) - return; - - if (ret != -ENODEV) - nouveau_fbcon_gpu_lockup(info); - drm_fb_helper_cfb_copyarea(info, image); -} - -static void -nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - struct nvif_device *device = &drm->client.device; - int ret; - - if (info->state != FBINFO_STATE_RUNNING) - return; - - ret = -ENODEV; - if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && - mutex_trylock(&drm->client.mutex)) { - if (device->info.family < NV_DEVICE_INFO_V0_TESLA) - ret = nv04_fbcon_imageblit(info, image); - else - if (device->info.family < NV_DEVICE_INFO_V0_FERMI) - ret = nv50_fbcon_imageblit(info, image); - else - ret = nvc0_fbcon_imageblit(info, image); - mutex_unlock(&drm->client.mutex); - } - - if (ret == 0) - return; - - if (ret != -ENODEV) - nouveau_fbcon_gpu_lockup(info); - drm_fb_helper_cfb_imageblit(info, image); -} - -static int -nouveau_fbcon_sync(struct fb_info *info) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - struct nouveau_channel *chan = drm->channel; - int ret; - - if (!chan || !chan->accel_done || in_interrupt() || - info->state != FBINFO_STATE_RUNNING || - info->flags & FBINFO_HWACCEL_DISABLED) - return 0; - - if (!mutex_trylock(&drm->client.mutex)) - return 0; - - ret = nouveau_channel_idle(chan); - mutex_unlock(&drm->client.mutex); - if (ret) { - nouveau_fbcon_gpu_lockup(info); - return 0; - } - - chan->accel_done = false; - return 0; -} - -static int -nouveau_fbcon_open(struct fb_info *info, int user) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - int ret = pm_runtime_get_sync(drm->dev->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put(drm->dev->dev); - return ret; - } - return 0; -} - -static int -nouveau_fbcon_release(struct fb_info *info, int user) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - pm_runtime_put(drm->dev->dev); - return 0; -} - -static const struct fb_ops nouveau_fbcon_ops = { - .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, - .fb_open = nouveau_fbcon_open, - .fb_release = nouveau_fbcon_release, - .fb_fillrect = nouveau_fbcon_fillrect, - .fb_copyarea = nouveau_fbcon_copyarea, - .fb_imageblit = nouveau_fbcon_imageblit, - .fb_sync = nouveau_fbcon_sync, -}; - -static const struct fb_ops nouveau_fbcon_sw_ops = { - .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, - .fb_open = nouveau_fbcon_open, - .fb_release = nouveau_fbcon_release, - .fb_fillrect = drm_fb_helper_cfb_fillrect, - .fb_copyarea = drm_fb_helper_cfb_copyarea, - .fb_imageblit = drm_fb_helper_cfb_imageblit, -}; - -void -nouveau_fbcon_accel_save_disable(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - if (drm->fbcon && drm->fbcon->helper.fbdev) { - drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; - drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; - } -} - -void -nouveau_fbcon_accel_restore(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - if (drm->fbcon && drm->fbcon->helper.fbdev) { - drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; - } -} - -static void -nouveau_fbcon_accel_fini(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fbdev *fbcon = drm->fbcon; - if (fbcon && drm->channel) { - console_lock(); - if (fbcon->helper.fbdev) - fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; - console_unlock(); - nouveau_channel_idle(drm->channel); - nvif_object_dtor(&fbcon->twod); - nvif_object_dtor(&fbcon->blit); - nvif_object_dtor(&fbcon->gdi); - nvif_object_dtor(&fbcon->patt); - nvif_object_dtor(&fbcon->rop); - nvif_object_dtor(&fbcon->clip); - nvif_object_dtor(&fbcon->surf2d); - } -} - -static void -nouveau_fbcon_accel_init(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fbdev *fbcon = drm->fbcon; - struct fb_info *info = fbcon->helper.fbdev; - int ret; - - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) - ret = nv04_fbcon_accel_init(info); - else - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI) - ret = nv50_fbcon_accel_init(info); - else - ret = nvc0_fbcon_accel_init(info); - - if (ret == 0) - info->fbops = &nouveau_fbcon_ops; -} - -static void -nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon) -{ - struct fb_info *info = fbcon->helper.fbdev; - struct fb_fillrect rect; - - /* Clear the entire fbcon. The drm will program every connector - * with it's preferred mode. If the sizes differ, one display will - * quite likely have garbage around the console. - */ - rect.dx = rect.dy = 0; - rect.width = info->var.xres_virtual; - rect.height = info->var.yres_virtual; - rect.color = 0; - rect.rop = ROP_COPY; - info->fbops->fb_fillrect(info, &rect); -} - -static int -nouveau_fbcon_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct nouveau_fbdev *fbcon = - container_of(helper, struct nouveau_fbdev, helper); - struct drm_device *dev = fbcon->helper.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->client.device; - struct fb_info *info; - struct drm_framebuffer *fb; - struct nouveau_channel *chan; - struct nouveau_bo *nvbo; - struct drm_mode_fb_cmd2 mode_cmd = {}; - int ret; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - - mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3); - mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256); - - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - ret = nouveau_gem_new(&drm->client, mode_cmd.pitches[0] * - mode_cmd.height, 0, NOUVEAU_GEM_DOMAIN_VRAM, - 0, 0x0000, &nvbo); - if (ret) { - NV_ERROR(drm, "failed to allocate framebuffer\n"); - goto out; - } - - ret = nouveau_framebuffer_new(dev, &mode_cmd, &nvbo->bo.base, &fb); - if (ret) - goto out_unref; - - ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false); - if (ret) { - NV_ERROR(drm, "failed to pin fb: %d\n", ret); - goto out_unref; - } - - ret = nouveau_bo_map(nvbo); - if (ret) { - NV_ERROR(drm, "failed to map fb: %d\n", ret); - goto out_unpin; - } - - chan = nouveau_nofbaccel ? NULL : drm->channel; - if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) { - ret = nouveau_vma_new(nvbo, chan->vmm, &fbcon->vma); - if (ret) { - NV_ERROR(drm, "failed to map fb into chan: %d\n", ret); - chan = NULL; - } - } - - info = drm_fb_helper_alloc_fbi(helper); - if (IS_ERR(info)) { - ret = PTR_ERR(info); - goto out_unlock; - } - - /* setup helper */ - fbcon->helper.fb = fb; - - if (!chan) - info->flags = FBINFO_HWACCEL_DISABLED; - else - info->flags = FBINFO_HWACCEL_COPYAREA | - FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_IMAGEBLIT; - info->fbops = &nouveau_fbcon_sw_ops; - info->fix.smem_start = nvbo->bo.resource->bus.offset; - info->fix.smem_len = nvbo->bo.base.size; - - info->screen_base = nvbo_kmap_obj_iovirtual(nvbo); - info->screen_size = nvbo->bo.base.size; - - drm_fb_helper_fill_info(info, &fbcon->helper, sizes); - - /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ - - if (chan) - nouveau_fbcon_accel_init(dev); - nouveau_fbcon_zfill(dev, fbcon); - - /* To allow resizeing without swapping buffers */ - NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n", - fb->width, fb->height, nvbo->offset, nvbo); - - if (dev_is_pci(dev->dev)) - vga_switcheroo_client_fb_set(to_pci_dev(dev->dev), info); - - return 0; - -out_unlock: - if (chan) - nouveau_vma_del(&fbcon->vma); - nouveau_bo_unmap(nvbo); -out_unpin: - nouveau_bo_unpin(nvbo); -out_unref: - nouveau_bo_ref(NULL, &nvbo); -out: - return ret; -} - -static int -nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) -{ - struct drm_framebuffer *fb = fbcon->helper.fb; - struct nouveau_bo *nvbo; - - drm_fb_helper_unregister_fbi(&fbcon->helper); - drm_fb_helper_fini(&fbcon->helper); - - if (fb && fb->obj[0]) { - nvbo = nouveau_gem_object(fb->obj[0]); - nouveau_vma_del(&fbcon->vma); - nouveau_bo_unmap(nvbo); - nouveau_bo_unpin(nvbo); - drm_framebuffer_put(fb); - } - - return 0; -} - -void nouveau_fbcon_gpu_lockup(struct fb_info *info) -{ - struct nouveau_fbdev *fbcon = info->par; - struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev); - - NV_ERROR(drm, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; -} - -static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { - .fb_probe = nouveau_fbcon_create, -}; - -static void -nouveau_fbcon_set_suspend_work(struct work_struct *work) -{ - struct nouveau_drm *drm = container_of(work, typeof(*drm), fbcon_work); - int state = READ_ONCE(drm->fbcon_new_state); - - if (state == FBINFO_STATE_RUNNING) - pm_runtime_get_sync(drm->dev->dev); - - console_lock(); - if (state == FBINFO_STATE_RUNNING) - nouveau_fbcon_accel_restore(drm->dev); - drm_fb_helper_set_suspend(&drm->fbcon->helper, state); - if (state != FBINFO_STATE_RUNNING) - nouveau_fbcon_accel_save_disable(drm->dev); - console_unlock(); - - if (state == FBINFO_STATE_RUNNING) { - nouveau_fbcon_hotplug_resume(drm->fbcon); - pm_runtime_mark_last_busy(drm->dev->dev); - pm_runtime_put_autosuspend(drm->dev->dev); - } -} - -void -nouveau_fbcon_set_suspend(struct drm_device *dev, int state) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - - if (!drm->fbcon) - return; - - drm->fbcon_new_state = state; - /* Since runtime resume can happen as a result of a sysfs operation, - * it's possible we already have the console locked. So handle fbcon - * init/deinit from a seperate work thread - */ - schedule_work(&drm->fbcon_work); -} - -void -nouveau_fbcon_output_poll_changed(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fbdev *fbcon = drm->fbcon; - int ret; - - if (!fbcon) - return; - - mutex_lock(&fbcon->hotplug_lock); - - ret = pm_runtime_get(dev->dev); - if (ret == 1 || ret == -EACCES) { - drm_fb_helper_hotplug_event(&fbcon->helper); - - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); - } else if (ret == 0) { - /* If the GPU was already in the process of suspending before - * this event happened, then we can't block here as we'll - * deadlock the runtime pmops since they wait for us to - * finish. So, just defer this event for when we runtime - * resume again. It will be handled by fbcon_work. - */ - NV_DEBUG(drm, "fbcon HPD event deferred until runtime resume\n"); - fbcon->hotplug_waiting = true; - pm_runtime_put_noidle(drm->dev->dev); - } else { - DRM_WARN("fbcon HPD event lost due to RPM failure: %d\n", - ret); - } - - mutex_unlock(&fbcon->hotplug_lock); -} - -void -nouveau_fbcon_hotplug_resume(struct nouveau_fbdev *fbcon) -{ - struct nouveau_drm *drm; - - if (!fbcon) - return; - drm = nouveau_drm(fbcon->helper.dev); - - mutex_lock(&fbcon->hotplug_lock); - if (fbcon->hotplug_waiting) { - fbcon->hotplug_waiting = false; - - NV_DEBUG(drm, "Handling deferred fbcon HPD events\n"); - drm_fb_helper_hotplug_event(&fbcon->helper); - } - mutex_unlock(&fbcon->hotplug_lock); -} - -int -nouveau_fbcon_init(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fbdev *fbcon; - int preferred_bpp = nouveau_fbcon_bpp; - int ret; - - if (!dev->mode_config.num_crtc || - (to_pci_dev(dev->dev)->class >> 8) != PCI_CLASS_DISPLAY_VGA) - return 0; - - fbcon = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); - if (!fbcon) - return -ENOMEM; - - drm->fbcon = fbcon; - INIT_WORK(&drm->fbcon_work, nouveau_fbcon_set_suspend_work); - mutex_init(&fbcon->hotplug_lock); - - drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs); - - ret = drm_fb_helper_init(dev, &fbcon->helper); - if (ret) - goto free; - - if (preferred_bpp != 8 && preferred_bpp != 16 && preferred_bpp != 32) { - if (drm->client.device.info.ram_size <= 32 * 1024 * 1024) - preferred_bpp = 8; - else - if (drm->client.device.info.ram_size <= 64 * 1024 * 1024) - preferred_bpp = 16; - else - preferred_bpp = 32; - } - - /* disable all the possible outputs/crtcs before entering KMS mode */ - if (!drm_drv_uses_atomic_modeset(dev)) - drm_helper_disable_unused_functions(dev); - - ret = drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp); - if (ret) - goto fini; - - if (fbcon->helper.fbdev) - fbcon->helper.fbdev->pixmap.buf_align = 4; - return 0; - -fini: - drm_fb_helper_fini(&fbcon->helper); -free: - kfree(fbcon); - drm->fbcon = NULL; - return ret; -} - -void -nouveau_fbcon_fini(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - - if (!drm->fbcon) - return; - - drm_kms_helper_poll_fini(dev); - nouveau_fbcon_accel_fini(dev); - nouveau_fbcon_destroy(dev, drm->fbcon); - kfree(drm->fbcon); - drm->fbcon = NULL; -} diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h deleted file mode 100644 index 1796d8824580..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2008 Maarten Maathuis. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef __NOUVEAU_FBCON_H__ -#define __NOUVEAU_FBCON_H__ - -#include - -#include "nouveau_display.h" - -struct nouveau_vma; - -struct nouveau_fbdev { - struct drm_fb_helper helper; /* must be first */ - unsigned int saved_flags; - struct nvif_object surf2d; - struct nvif_object clip; - struct nvif_object rop; - struct nvif_object patt; - struct nvif_object gdi; - struct nvif_object blit; - struct nvif_object twod; - struct nouveau_vma *vma; - - struct mutex hotplug_lock; - bool hotplug_waiting; -}; - -void nouveau_fbcon_restore(void); - -int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); -int nv04_fbcon_accel_init(struct fb_info *info); - -int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); -int nv50_fbcon_accel_init(struct fb_info *info); - -int nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -int nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -int nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); -int nvc0_fbcon_accel_init(struct fb_info *info); - -void nouveau_fbcon_gpu_lockup(struct fb_info *info); - -int nouveau_fbcon_init(struct drm_device *dev); -void nouveau_fbcon_fini(struct drm_device *dev); -void nouveau_fbcon_set_suspend(struct drm_device *dev, int state); -void nouveau_fbcon_accel_save_disable(struct drm_device *dev); -void nouveau_fbcon_accel_restore(struct drm_device *dev); - -void nouveau_fbcon_output_poll_changed(struct drm_device *dev); -void nouveau_fbcon_hotplug_resume(struct nouveau_fbdev *fbcon); -extern int nouveau_nofbaccel; - -#endif /* __NV50_FBCON_H__ */ - diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 60cd8c0463df..789393b94291 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -7,7 +7,6 @@ #include "nouveau_drv.h" #include "nouveau_acpi.h" -#include "nouveau_fbcon.h" #include "nouveau_vga.h" static unsigned int diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c deleted file mode 100644 index c30b8dacd86b..000000000000 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright 2009 Ben Skeggs - * Copyright 2008 Stuart Bennett - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#define NVIF_DEBUG_PRINT_DISABLE -#include "nouveau_drv.h" -#include "nouveau_dma.h" -#include "nouveau_fbcon.h" - -#include - -int -nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - int ret; - - ret = PUSH_WAIT(push, 4); - if (ret) - return ret; - - PUSH_NVSQ(push, NV05F, 0x0300, (region->sy << 16) | region->sx, - 0x0304, (region->dy << 16) | region->dx, - 0x0308, (region->height << 16) | region->width); - PUSH_KICK(push); - return 0; -} - -int -nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - int ret; - - ret = PUSH_WAIT(push, 7); - if (ret) - return ret; - - PUSH_NVSQ(push, NV04A, 0x02fc, (rect->rop != ROP_COPY) ? 1 : 3); - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) - PUSH_NVSQ(push, NV04A, 0x03fc, ((uint32_t *)info->pseudo_palette)[rect->color]); - else - PUSH_NVSQ(push, NV04A, 0x03fc, rect->color); - PUSH_NVSQ(push, NV04A, 0x0400, (rect->dx << 16) | rect->dy, - 0x0404, (rect->width << 16) | rect->height); - PUSH_KICK(push); - return 0; -} - -int -nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - uint32_t fg; - uint32_t bg; - uint32_t dsize; - uint32_t *data = (uint32_t *)image->data; - int ret; - - if (image->depth != 1) - return -ENODEV; - - ret = PUSH_WAIT(push, 8); - if (ret) - return ret; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fg = ((uint32_t *) info->pseudo_palette)[image->fg_color]; - bg = ((uint32_t *) info->pseudo_palette)[image->bg_color]; - } else { - fg = image->fg_color; - bg = image->bg_color; - } - - PUSH_NVSQ(push, NV04A, 0x0be4, (image->dy << 16) | (image->dx & 0xffff), - 0x0be8, ((image->dy + image->height) << 16) | - ((image->dx + image->width) & 0xffff), - 0x0bec, bg, - 0x0bf0, fg, - 0x0bf4, (image->height << 16) | ALIGN(image->width, 8), - 0x0bf8, (image->height << 16) | image->width, - 0x0bfc, (image->dy << 16) | (image->dx & 0xffff)); - - dsize = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5; - while (dsize) { - int iter_len = dsize > 128 ? 128 : dsize; - - ret = PUSH_WAIT(push, iter_len + 1); - if (ret) - return ret; - - PUSH_NVSQ(push, NV04A, 0x0c00, data, iter_len); - data += iter_len; - dsize -= iter_len; - } - - PUSH_KICK(push); - return 0; -} - -int -nv04_fbcon_accel_init(struct fb_info *info) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->helper.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_device *device = &drm->client.device; - struct nvif_push *push = chan->chan.push; - struct nvkm_device *nvkm_device = nvxx_device(&drm->client.device); - resource_size_t fb_base = nvkm_device->func->resource_addr(nvkm_device, 1); - int surface_fmt, pattern_fmt, rect_fmt; - int ret; - - switch (info->var.bits_per_pixel) { - case 8: - surface_fmt = 1; - pattern_fmt = 3; - rect_fmt = 3; - break; - case 16: - surface_fmt = 4; - pattern_fmt = 1; - rect_fmt = 1; - break; - case 32: - switch (info->var.transp.length) { - case 0: /* depth 24 */ - case 8: /* depth 32 */ - break; - default: - return -EINVAL; - } - - surface_fmt = 6; - pattern_fmt = 3; - rect_fmt = 3; - break; - default: - return -EINVAL; - } - - ret = nvif_object_ctor(&chan->user, "fbconCtxSurf2d", 0x0062, - device->info.family >= NV_DEVICE_INFO_V0_CELSIUS ? - 0x0062 : 0x0042, NULL, 0, &nfbdev->surf2d); - if (ret) - return ret; - - ret = nvif_object_ctor(&chan->user, "fbconCtxClip", 0x0019, 0x0019, - NULL, 0, &nfbdev->clip); - if (ret) - return ret; - - ret = nvif_object_ctor(&chan->user, "fbconCtxRop", 0x0043, 0x0043, - NULL, 0, &nfbdev->rop); - if (ret) - return ret; - - ret = nvif_object_ctor(&chan->user, "fbconCtxPatt", 0x0044, 0x0044, - NULL, 0, &nfbdev->patt); - if (ret) - return ret; - - ret = nvif_object_ctor(&chan->user, "fbconGdiRectText", 0x004a, 0x004a, - NULL, 0, &nfbdev->gdi); - if (ret) - return ret; - - ret = nvif_object_ctor(&chan->user, "fbconImageBlit", 0x005f, - device->info.chipset >= 0x11 ? 0x009f : 0x005f, - NULL, 0, &nfbdev->blit); - if (ret) - return ret; - - if (PUSH_WAIT(push, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) { - nouveau_fbcon_gpu_lockup(info); - return 0; - } - - PUSH_NVSQ(push, NV042, 0x0000, nfbdev->surf2d.handle); - PUSH_NVSQ(push, NV042, 0x0184, chan->vram.handle, - 0x0188, chan->vram.handle); - PUSH_NVSQ(push, NV042, 0x0300, surface_fmt, - 0x0304, info->fix.line_length | (info->fix.line_length << 16), - 0x0308, info->fix.smem_start - fb_base, - 0x030c, info->fix.smem_start - fb_base); - - PUSH_NVSQ(push, NV043, 0x0000, nfbdev->rop.handle); - PUSH_NVSQ(push, NV043, 0x0300, 0x55); - - PUSH_NVSQ(push, NV044, 0x0000, nfbdev->patt.handle); - PUSH_NVSQ(push, NV044, 0x0300, pattern_fmt, -#ifdef __BIG_ENDIAN - 0x0304, 2, -#else - 0x0304, 1, -#endif - 0x0308, 0, - 0x030c, 1, - 0x0310, ~0, - 0x0314, ~0, - 0x0318, ~0, - 0x031c, ~0); - - PUSH_NVSQ(push, NV019, 0x0000, nfbdev->clip.handle); - PUSH_NVSQ(push, NV019, 0x0300, 0, - 0x0304, (info->var.yres_virtual << 16) | info->var.xres_virtual); - - PUSH_NVSQ(push, NV05F, 0x0000, nfbdev->blit.handle); - PUSH_NVSQ(push, NV05F, 0x019c, nfbdev->surf2d.handle); - PUSH_NVSQ(push, NV05F, 0x02fc, 3); - if (nfbdev->blit.oclass == 0x009f) { - PUSH_NVSQ(push, NV09F, 0x0120, 0, - 0x0124, 1, - 0x0128, 2); - } - - PUSH_NVSQ(push, NV04A, 0x0000, nfbdev->gdi.handle); - PUSH_NVSQ(push, NV04A, 0x0198, nfbdev->surf2d.handle); - PUSH_NVSQ(push, NV04A, 0x0188, nfbdev->patt.handle, - 0x018c, nfbdev->rop.handle); - PUSH_NVSQ(push, NV04A, 0x0304, 1); - PUSH_NVSQ(push, NV04A, 0x0300, rect_fmt); - PUSH_NVSQ(push, NV04A, 0x02fc, 3); - - PUSH_KICK(push); - return 0; -} - diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c deleted file mode 100644 index 71f92e4750f9..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#define NVIF_DEBUG_PRINT_DISABLE -#include "nouveau_drv.h" -#include "nouveau_dma.h" -#include "nouveau_fbcon.h" -#include "nouveau_vmm.h" - -#include - -#include - -int -nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - u32 colour; - int ret; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) - colour = ((uint32_t *)info->pseudo_palette)[rect->color]; - else - colour = rect->color; - - ret = PUSH_WAIT(push, rect->rop == ROP_COPY ? 7 : 11); - if (ret) - return ret; - - if (rect->rop != ROP_COPY) { - PUSH_MTHD(push, NV502D, SET_OPERATION, - NVDEF(NV502D, SET_OPERATION, V, ROP_AND)); - } - - PUSH_MTHD(push, NV502D, SET_RENDER_SOLID_PRIM_COLOR, colour); - - PUSH_MTHD(push, NV502D, RENDER_SOLID_PRIM_POINT_SET_X(0), rect->dx, - RENDER_SOLID_PRIM_POINT_Y(0), rect->dy, - RENDER_SOLID_PRIM_POINT_SET_X(1), rect->dx + rect->width, - RENDER_SOLID_PRIM_POINT_Y(1), rect->dy + rect->height); - - if (rect->rop != ROP_COPY) { - PUSH_MTHD(push, NV502D, SET_OPERATION, - NVDEF(NV502D, SET_OPERATION, V, SRCCOPY)); - } - - PUSH_KICK(push); - return 0; -} - -int -nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - int ret; - - ret = PUSH_WAIT(push, 12); - if (ret) - return ret; - - PUSH_MTHD(push, NV502D, WAIT_FOR_IDLE, 0); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_DST_X0, region->dx, - SET_PIXELS_FROM_MEMORY_DST_Y0, region->dy, - SET_PIXELS_FROM_MEMORY_DST_WIDTH, region->width, - SET_PIXELS_FROM_MEMORY_DST_HEIGHT, region->height); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_SRC_X0_FRAC, 0, - SET_PIXELS_FROM_MEMORY_SRC_X0_INT, region->sx, - SET_PIXELS_FROM_MEMORY_SRC_Y0_FRAC, 0, - PIXELS_FROM_MEMORY_SRC_Y0_INT, region->sy); - PUSH_KICK(push); - return 0; -} - -int -nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - uint32_t dwords, *data = (uint32_t *)image->data; - uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); - uint32_t *palette = info->pseudo_palette, bg, fg; - int ret; - - if (image->depth != 1) - return -ENODEV; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - bg = palette[image->bg_color] | mask; - fg = palette[image->fg_color] | mask; - } else { - bg = image->bg_color; - fg = image->fg_color; - } - - ret = PUSH_WAIT(push, 11); - if (ret) - return ret; - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_COLOR0, bg, - SET_PIXELS_FROM_CPU_COLOR1, fg); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_SRC_WIDTH, image->width, - SET_PIXELS_FROM_CPU_SRC_HEIGHT, image->height); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DST_X0_FRAC, 0, - SET_PIXELS_FROM_CPU_DST_X0_INT, image->dx, - SET_PIXELS_FROM_CPU_DST_Y0_FRAC, 0, - SET_PIXELS_FROM_CPU_DST_Y0_INT, image->dy); - - dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5; - while (dwords) { - int count = dwords > 2047 ? 2047 : dwords; - - ret = PUSH_WAIT(push, count + 1); - if (ret) - return ret; - - dwords -= count; - - PUSH_NINC(push, NV502D, PIXELS_FROM_CPU_DATA, data, count); - data += count; - } - - PUSH_KICK(push); - return 0; -} - -int -nv50_fbcon_accel_init(struct fb_info *info) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->helper.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - int ret, format; - - switch (info->var.bits_per_pixel) { - case 8: - format = NV502D_SET_DST_FORMAT_V_Y8; - break; - case 15: - format = NV502D_SET_DST_FORMAT_V_X1R5G5B5; - break; - case 16: - format = NV502D_SET_DST_FORMAT_V_R5G6B5; - break; - case 32: - switch (info->var.transp.length) { - case 0: /* depth 24 */ - case 8: /* depth 32, just use 24.. */ - format = NV502D_SET_DST_FORMAT_V_X8R8G8B8; - break; - case 2: /* depth 30 */ - format = NV502D_SET_DST_FORMAT_V_A2B10G10R10; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - ret = nvif_object_ctor(&chan->user, "fbconTwoD", 0x502d, 0x502d, - NULL, 0, &nfbdev->twod); - if (ret) - return ret; - - ret = PUSH_WAIT(push, 56); - if (ret) { - nouveau_fbcon_gpu_lockup(info); - return ret; - } - - PUSH_MTHD(push, NV502D, SET_OBJECT, nfbdev->twod.handle); - PUSH_MTHD(push, NV502D, SET_DST_CONTEXT_DMA, chan->vram.handle, - SET_SRC_CONTEXT_DMA, chan->vram.handle, - SET_SEMAPHORE_CONTEXT_DMA, chan->vram.handle); - - PUSH_MTHD(push, NV502D, SET_DST_FORMAT, - NVVAL(NV502D, SET_DST_FORMAT, V, format), - - SET_DST_MEMORY_LAYOUT, - NVDEF(NV502D, SET_DST_MEMORY_LAYOUT, V, PITCH)); - - PUSH_MTHD(push, NV502D, SET_DST_PITCH, info->fix.line_length, - SET_DST_WIDTH, info->var.xres_virtual, - SET_DST_HEIGHT, info->var.yres_virtual, - - SET_DST_OFFSET_UPPER, - NVVAL(NV502D, SET_DST_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)), - - SET_DST_OFFSET_LOWER, - NVVAL(NV502D, SET_DST_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr))); - - PUSH_MTHD(push, NV502D, SET_SRC_FORMAT, - NVVAL(NV502D, SET_SRC_FORMAT, V, format), - - SET_SRC_MEMORY_LAYOUT, - NVDEF(NV502D, SET_SRC_MEMORY_LAYOUT, V, PITCH)); - - PUSH_MTHD(push, NV502D, SET_SRC_PITCH, info->fix.line_length, - SET_SRC_WIDTH, info->var.xres_virtual, - SET_SRC_HEIGHT, info->var.yres_virtual, - - SET_SRC_OFFSET_UPPER, - NVVAL(NV502D, SET_SRC_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)), - - SET_SRC_OFFSET_LOWER, - NVVAL(NV502D, SET_SRC_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr))); - - PUSH_MTHD(push, NV502D, SET_CLIP_ENABLE, - NVDEF(NV502D, SET_CLIP_ENABLE, V, FALSE)); - - PUSH_MTHD(push, NV502D, SET_ROP, - NVVAL(NV502D, SET_ROP, V, 0x55)); - - PUSH_MTHD(push, NV502D, SET_OPERATION, - NVDEF(NV502D, SET_OPERATION, V, SRCCOPY)); - - PUSH_MTHD(push, NV502D, SET_MONOCHROME_PATTERN_COLOR_FORMAT, - NVDEF(NV502D, SET_MONOCHROME_PATTERN_COLOR_FORMAT, V, A8R8G8B8), - - SET_MONOCHROME_PATTERN_FORMAT, - NVDEF(NV502D, SET_MONOCHROME_PATTERN_FORMAT, V, LE_M1)); - - PUSH_MTHD(push, NV502D, RENDER_SOLID_PRIM_MODE, - NVDEF(NV502D, RENDER_SOLID_PRIM_MODE, V, RECTS), - - SET_RENDER_SOLID_PRIM_COLOR_FORMAT, - NVVAL(NV502D, SET_RENDER_SOLID_PRIM_COLOR_FORMAT, V, format)); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DATA_TYPE, - NVDEF(NV502D, SET_PIXELS_FROM_CPU_DATA_TYPE, V, INDEX), - - SET_PIXELS_FROM_CPU_COLOR_FORMAT, - NVVAL(NV502D, SET_PIXELS_FROM_CPU_COLOR_FORMAT, V, format), - - SET_PIXELS_FROM_CPU_INDEX_FORMAT, - NVDEF(NV502D, SET_PIXELS_FROM_CPU_INDEX_FORMAT, V, I1), - - SET_PIXELS_FROM_CPU_MONO_FORMAT, - NVDEF(NV502D, SET_PIXELS_FROM_CPU_MONO_FORMAT, V, CGA6_M1), - - SET_PIXELS_FROM_CPU_WRAP, - NVDEF(NV502D, SET_PIXELS_FROM_CPU_WRAP, V, WRAP_BYTE)); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_MONO_OPACITY, - NVDEF(NV502D, SET_PIXELS_FROM_CPU_MONO_OPACITY, V, OPAQUE)); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DX_DU_FRAC, 0, - SET_PIXELS_FROM_CPU_DX_DU_INT, 1, - SET_PIXELS_FROM_CPU_DY_DV_FRAC, 0, - SET_PIXELS_FROM_CPU_DY_DV_INT, 1); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP, - NVDEF(NV502D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP, V, TRUE)); - - PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_DU_DX_FRAC, 0, - SET_PIXELS_FROM_MEMORY_DU_DX_INT, 1, - SET_PIXELS_FROM_MEMORY_DV_DY_FRAC, 0, - SET_PIXELS_FROM_MEMORY_DV_DY_INT, 1); - PUSH_KICK(push); - return 0; -} - diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c deleted file mode 100644 index 7908a1a3e00f..000000000000 --- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#define NVIF_DEBUG_PRINT_DISABLE -#include "nouveau_drv.h" -#include "nouveau_dma.h" -#include "nouveau_fbcon.h" -#include "nouveau_vmm.h" - -#include - -#include - -int -nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - u32 colour; - int ret; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) - colour = ((uint32_t *)info->pseudo_palette)[rect->color]; - else - colour = rect->color; - - ret = PUSH_WAIT(push, rect->rop == ROP_COPY ? 7 : 9); - if (ret) - return ret; - - if (rect->rop != ROP_COPY) { - PUSH_IMMD(push, NV902D, SET_OPERATION, - NVDEF(NV902D, SET_OPERATION, V, ROP_AND)); - } - - PUSH_MTHD(push, NV902D, SET_RENDER_SOLID_PRIM_COLOR, colour); - - PUSH_MTHD(push, NV902D, RENDER_SOLID_PRIM_POINT_SET_X(0), rect->dx, - RENDER_SOLID_PRIM_POINT_Y(0), rect->dy, - RENDER_SOLID_PRIM_POINT_SET_X(1), rect->dx + rect->width, - RENDER_SOLID_PRIM_POINT_Y(1), rect->dy + rect->height); - - if (rect->rop != ROP_COPY) { - PUSH_IMMD(push, NV902D, SET_OPERATION, - NVDEF(NV902D, SET_OPERATION, V, SRCCOPY)); - } - - PUSH_KICK(push); - return 0; -} - -int -nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - int ret; - - ret = PUSH_WAIT(push, 11); - if (ret) - return ret; - - PUSH_IMMD(push, NV902D, WAIT_FOR_IDLE, 0); - - PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_MEMORY_DST_X0, region->dx, - SET_PIXELS_FROM_MEMORY_DST_Y0, region->dy, - SET_PIXELS_FROM_MEMORY_DST_WIDTH, region->width, - SET_PIXELS_FROM_MEMORY_DST_HEIGHT, region->height); - - PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_MEMORY_SRC_X0_FRAC, 0, - SET_PIXELS_FROM_MEMORY_SRC_X0_INT, region->sx, - SET_PIXELS_FROM_MEMORY_SRC_Y0_FRAC, 0, - PIXELS_FROM_MEMORY_SRC_Y0_INT, region->sy); - PUSH_KICK(push); - return 0; -} - -int -nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - uint32_t dwords, *data = (uint32_t *)image->data; - uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); - uint32_t *palette = info->pseudo_palette, bg, fg; - int ret; - - if (image->depth != 1) - return -ENODEV; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - bg = palette[image->bg_color] | mask; - fg = palette[image->fg_color] | mask; - } else { - bg = image->bg_color; - fg = image->fg_color; - } - - ret = PUSH_WAIT(push, 11); - if (ret) - return ret; - - PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_COLOR0, bg, - SET_PIXELS_FROM_CPU_COLOR1, fg); - - PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_SRC_WIDTH, image->width, - SET_PIXELS_FROM_CPU_SRC_HEIGHT, image->height); - - PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_DST_X0_FRAC, 0, - SET_PIXELS_FROM_CPU_DST_X0_INT, image->dx, - SET_PIXELS_FROM_CPU_DST_Y0_FRAC, 0, - SET_PIXELS_FROM_CPU_DST_Y0_INT, image->dy); - - dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5; - while (dwords) { - int count = dwords > 2047 ? 2047 : dwords; - - ret = PUSH_WAIT(push, count + 1); - if (ret) - return ret; - - dwords -= count; - - PUSH_NINC(push, NV902D, PIXELS_FROM_CPU_DATA, data, count); - data += count; - } - - PUSH_KICK(push); - return 0; -} - -int -nvc0_fbcon_accel_init(struct fb_info *info) -{ - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->helper.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *chan = drm->channel; - struct nvif_push *push = chan->chan.push; - int ret, format; - - ret = nvif_object_ctor(&chan->user, "fbconTwoD", 0x902d, 0x902d, - NULL, 0, &nfbdev->twod); - if (ret) - return ret; - - switch (info->var.bits_per_pixel) { - case 8: - format = NV902D_SET_DST_FORMAT_V_Y8; - break; - case 15: - format = NV902D_SET_DST_FORMAT_V_X1R5G5B5; - break; - case 16: - format = NV902D_SET_DST_FORMAT_V_R5G6B5; - break; - case 32: - switch (info->var.transp.length) { - case 0: /* depth 24 */ - case 8: /* depth 32, just use 24.. */ - format = NV902D_SET_DST_FORMAT_V_X8R8G8B8; - break; - case 2: /* depth 30 */ - format = NV902D_SET_DST_FORMAT_V_A2B10G10R10; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - ret = PUSH_WAIT(push, 52); - if (ret) { - WARN_ON(1); - nouveau_fbcon_gpu_lockup(info); - return ret; - } - - PUSH_MTHD(push, NV902D, SET_OBJECT, nfbdev->twod.handle); - - PUSH_MTHD(push, NV902D, SET_DST_FORMAT, - NVVAL(NV902D, SET_DST_FORMAT, V, format), - - SET_DST_MEMORY_LAYOUT, - NVDEF(NV902D, SET_DST_MEMORY_LAYOUT, V, PITCH)); - - PUSH_MTHD(push, NV902D, SET_DST_PITCH, info->fix.line_length, - SET_DST_WIDTH, info->var.xres_virtual, - SET_DST_HEIGHT, info->var.yres_virtual, - - SET_DST_OFFSET_UPPER, - NVVAL(NV902D, SET_DST_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)), - - SET_DST_OFFSET_LOWER, - NVVAL(NV902D, SET_DST_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr))); - - PUSH_MTHD(push, NV902D, SET_SRC_FORMAT, - NVVAL(NV902D, SET_SRC_FORMAT, V, format), - - SET_SRC_MEMORY_LAYOUT, - NVDEF(NV902D, SET_SRC_MEMORY_LAYOUT, V, PITCH)); - - PUSH_MTHD(push, NV902D, SET_SRC_PITCH, info->fix.line_length, - SET_SRC_WIDTH, info->var.xres_virtual, - SET_SRC_HEIGHT, info->var.yres_virtual, - - SET_SRC_OFFSET_UPPER, - NVVAL(NV902D, SET_SRC_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)), - - SET_SRC_OFFSET_LOWER, - NVVAL(NV902D, SET_SRC_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr))); - - PUSH_IMMD(push, NV902D, SET_CLIP_ENABLE, - NVDEF(NV902D, SET_CLIP_ENABLE, V, FALSE)); - - PUSH_IMMD(push, NV902D, SET_ROP, - NVVAL(NV902D, SET_ROP, V, 0x55)); - - PUSH_IMMD(push, NV902D, SET_OPERATION, - NVDEF(NV902D, SET_OPERATION, V, SRCCOPY)); - - PUSH_MTHD(push, NV902D, SET_MONOCHROME_PATTERN_COLOR_FORMAT, - NVDEF(NV902D, SET_MONOCHROME_PATTERN_COLOR_FORMAT, V, A8R8G8B8), - - SET_MONOCHROME_PATTERN_FORMAT, - NVDEF(NV902D, SET_MONOCHROME_PATTERN_FORMAT, V, LE_M1)); - - PUSH_MTHD(push, NV902D, RENDER_SOLID_PRIM_MODE, - NVDEF(NV902D, RENDER_SOLID_PRIM_MODE, V, RECTS), - - SET_RENDER_SOLID_PRIM_COLOR_FORMAT, - NVVAL(NV902D, SET_RENDER_SOLID_PRIM_COLOR_FORMAT, V, format)); - - PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_DATA_TYPE, - NVDEF(NV902D, SET_PIXELS_FROM_CPU_DATA_TYPE, V, INDEX), - - SET_PIXELS_FROM_CPU_COLOR_FORMAT, - NVVAL(NV902D, SET_PIXELS_FROM_CPU_COLOR_FORMAT, V, format), - - SET_PIXELS_FROM_CPU_INDEX_FORMAT, - NVDEF(NV902D, SET_PIXELS_FROM_CPU_INDEX_FORMAT, V, I1), - - SET_PIXELS_FROM_CPU_MONO_FORMAT, - NVDEF(NV902D, SET_PIXELS_FROM_CPU_MONO_FORMAT, V, CGA6_M1), - - SET_PIXELS_FROM_CPU_WRAP, - NVDEF(NV902D, SET_PIXELS_FROM_CPU_WRAP, V, WRAP_BYTE)); - - PUSH_IMMD(push, NV902D, SET_PIXELS_FROM_CPU_MONO_OPACITY, - NVDEF(NV902D, SET_PIXELS_FROM_CPU_MONO_OPACITY, V, OPAQUE)); - - PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_DX_DU_FRAC, 0, - SET_PIXELS_FROM_CPU_DX_DU_INT, 1, - SET_PIXELS_FROM_CPU_DY_DV_FRAC, 0, - SET_PIXELS_FROM_CPU_DY_DV_INT, 1); - - PUSH_IMMD(push, NV902D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP, - NVDEF(NV902D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP, V, TRUE)); - - PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_MEMORY_DU_DX_FRAC, 0, - SET_PIXELS_FROM_MEMORY_DU_DX_INT, 1, - SET_PIXELS_FROM_MEMORY_DV_DY_FRAC, 0, - SET_PIXELS_FROM_MEMORY_DV_DY_INT, 1); - PUSH_KICK(push); - return 0; -} - -- cgit v1.2.3 From ab4f75eb1cc261263ac51814fed14fde08b6716f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:51 +1000 Subject: drm/nouveau/nvkm: give each nvkm_event its own lockdep class The vblank and nonstall events have some annoying interactions with DRM locking, and aren't able to do certain things as a result. However, other uses of event notifications don't have such requirements, and upcoming patches take advantage of this for various improvements. Having separate classes for each nvkm_event's spinlocks allows lockdep to distinguish between them and avoid false-positives. v2: __always_inline + comment Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/event.h | 19 +++++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/core/event.c | 6 ++---- 2 files changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h index 8e8fb4b6bca4..82b267c11147 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h @@ -25,8 +25,23 @@ struct nvkm_event_func { void (*fini)(struct nvkm_event *, int type, int index); }; -int nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr, - int index_nr, struct nvkm_event *); +int __nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr, + int index_nr, struct nvkm_event *); + +/* Each nvkm_event needs its own lockdep class due to inter-dependencies, to + * prevent lockdep false-positives. + * + * Inlining the spinlock initialisation ensures each is unique. + */ +static __always_inline int +nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev, + int types_nr, int index_nr, struct nvkm_event *event) +{ + spin_lock_init(&event->refs_lock); + spin_lock_init(&event->list_lock); + return __nvkm_event_init(func, subdev, types_nr, index_nr, event); +} + void nvkm_event_fini(struct nvkm_event *); #define NVKM_EVENT_KEEP 0 diff --git a/drivers/gpu/drm/nouveau/nvkm/core/event.c b/drivers/gpu/drm/nouveau/nvkm/core/event.c index 622df36391be..a6c877135598 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/event.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/event.c @@ -198,8 +198,8 @@ nvkm_event_fini(struct nvkm_event *event) } int -nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev, - int types_nr, int index_nr, struct nvkm_event *event) +__nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev, + int types_nr, int index_nr, struct nvkm_event *event) { event->refs = kzalloc(array3_size(index_nr, types_nr, sizeof(*event->refs)), GFP_KERNEL); if (!event->refs) @@ -209,8 +209,6 @@ nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev, event->subdev = subdev; event->types_nr = types_nr; event->index_nr = index_nr; - spin_lock_init(&event->refs_lock); - spin_lock_init(&event->list_lock); INIT_LIST_HEAD(&event->ntfy); return 0; } -- cgit v1.2.3 From eec3f6dfedc0b8c5aef7619667dee61a77a37e35 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:51 +1000 Subject: drm/nouveau/top: parse device topology right after devinit We're going to want this information available earlier than it is now. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 4 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c | 13 ++++++++----- drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h | 2 +- 6 files changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h index ee75c5524c43..73e717b980b8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h @@ -21,6 +21,7 @@ struct nvkm_top_device { struct list_head head; }; +int nvkm_top_parse(struct nvkm_device *); u32 nvkm_top_addr(struct nvkm_device *, enum nvkm_subdev_type, int); u32 nvkm_top_reset(struct nvkm_device *, enum nvkm_subdev_type, int); u32 nvkm_top_intr_mask(struct nvkm_device *, enum nvkm_subdev_type, int); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index d8cf71fb0512..c45ff9df0727 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2775,6 +2775,10 @@ nvkm_device_preinit(struct nvkm_device *device) if (ret) goto fail; + ret = nvkm_top_parse(device); + if (ret) + goto fail; + time = ktime_to_us(ktime_get()) - time; nvdev_trace(device, "preinit completed in %lldus\n", time); return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c index 28d0789f50fe..eb348dfc1d7a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c @@ -117,11 +117,15 @@ nvkm_top_fault(struct nvkm_device *device, int fault) return NULL; } -static int -nvkm_top_oneinit(struct nvkm_subdev *subdev) +int +nvkm_top_parse(struct nvkm_device *device) { - struct nvkm_top *top = nvkm_top(subdev); - return top->func->oneinit(top); + struct nvkm_top *top = device->top; + + if (!top || !list_empty(&top->device)) + return 0; + + return top->func->parse(top); } static void * @@ -141,7 +145,6 @@ nvkm_top_dtor(struct nvkm_subdev *subdev) static const struct nvkm_subdev_func nvkm_top = { .dtor = nvkm_top_dtor, - .oneinit = nvkm_top_oneinit, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c index c982d834c8d9..84790cf52b90 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c @@ -22,7 +22,7 @@ #include "priv.h" static int -ga100_top_oneinit(struct nvkm_top *top) +ga100_top_parse(struct nvkm_top *top) { struct nvkm_subdev *subdev = &top->subdev; struct nvkm_device *device = subdev->device; @@ -97,7 +97,7 @@ ga100_top_oneinit(struct nvkm_top *top) static const struct nvkm_top_func ga100_top = { - .oneinit = ga100_top_oneinit, + .parse = ga100_top_parse, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c index 4dcad97bd505..2bbba8244cbf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c @@ -24,7 +24,7 @@ #include "priv.h" static int -gk104_top_oneinit(struct nvkm_top *top) +gk104_top_parse(struct nvkm_top *top) { struct nvkm_subdev *subdev = &top->subdev; struct nvkm_device *device = subdev->device; @@ -108,7 +108,7 @@ gk104_top_oneinit(struct nvkm_top *top) static const struct nvkm_top_func gk104_top = { - .oneinit = gk104_top_oneinit, + .parse = gk104_top_parse, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h index 8e103a836705..532be91d8fd9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h @@ -5,7 +5,7 @@ #include struct nvkm_top_func { - int (*oneinit)(struct nvkm_top *); + int (*parse)(struct nvkm_top *); }; int nvkm_top_new_(const struct nvkm_top_func *, struct nvkm_device *, enum nvkm_subdev_type, int, -- cgit v1.2.3 From 727fd72f2402afe7cc320844b0aef165f7eb544e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:52 +1000 Subject: drm/nouveau/intr: add shared interrupt plumbing between pci/tegra Unifies the handling between PCI-based and Tegra GPUs, and makes more explicit/obvious where device interrupts can be expected. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/device.h | 9 ++ drivers/gpu/drm/nouveau/include/nvkm/core/intr.h | 12 +++ drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h | 1 - drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h | 2 +- drivers/gpu/drm/nouveau/nvkm/core/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/core/intr.c | 109 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 11 ++- drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c | 7 ++ drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 40 +------- drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c | 44 ++------- 10 files changed, 161 insertions(+), 75 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvkm/core/intr.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/core/intr.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index efede1f11e1d..6752a4c317e2 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -2,6 +2,7 @@ #ifndef __NVKM_DEVICE_H__ #define __NVKM_DEVICE_H__ #include +#include enum nvkm_subdev_type; enum nvkm_device_type { @@ -60,6 +61,13 @@ struct nvkm_device { #undef NVKM_LAYOUT_INST #undef NVKM_LAYOUT_ONCE struct list_head subdev; + + struct { + spinlock_t lock; + int irq; + bool alloc; + bool armed; + } intr; }; struct nvkm_subdev *nvkm_device_subdev(struct nvkm_device *, int type, int inst); @@ -72,6 +80,7 @@ struct nvkm_device_func { int (*preinit)(struct nvkm_device *); int (*init)(struct nvkm_device *); void (*fini)(struct nvkm_device *, bool suspend); + int (*irq)(struct nvkm_device *); resource_size_t (*resource_addr)(struct nvkm_device *, unsigned bar); resource_size_t (*resource_size)(struct nvkm_device *, unsigned bar); bool cpu_coherent; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h b/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h new file mode 100644 index 000000000000..b4d49ff40c6a --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_INTR_H__ +#define __NVKM_INTR_H__ +#include +struct nvkm_device; + +void nvkm_intr_ctor(struct nvkm_device *); +void nvkm_intr_dtor(struct nvkm_device *); +int nvkm_intr_install(struct nvkm_device *); +void nvkm_intr_unarm(struct nvkm_device *); +void nvkm_intr_rearm(struct nvkm_device *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h index 924009dd2bb0..ccee53d4e4ec 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h @@ -8,7 +8,6 @@ struct nvkm_device_tegra { const struct nvkm_device_tegra_func *func; struct nvkm_device device; struct platform_device *pdev; - int irq; struct reset_control *rst; struct clk *clk; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h index 74c19bdfb757..3c103101d5fc 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h @@ -13,7 +13,6 @@ struct nvkm_pci { const struct nvkm_pci_func *func; struct nvkm_subdev subdev; struct pci_dev *pdev; - int irq; struct { struct agp_bridge_data *bridge; @@ -38,6 +37,7 @@ void nvkm_pci_wr08(struct nvkm_pci *, u16 addr, u8 data); void nvkm_pci_wr32(struct nvkm_pci *, u16 addr, u32 data); u32 nvkm_pci_mask(struct nvkm_pci *, u16 addr, u32 mask, u32 value); void nvkm_pci_rom_shadow(struct nvkm_pci *, bool shadow); +void nvkm_pci_msi_rearm(struct nvkm_device *); int nv04_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pci **); int nv40_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pci **); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild index 65dad05f047c..e40712023c73 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild @@ -5,6 +5,7 @@ nvkm-y += nvkm/core/enum.o nvkm-y += nvkm/core/event.o nvkm-y += nvkm/core/firmware.o nvkm-y += nvkm/core/gpuobj.o +nvkm-y += nvkm/core/intr.o nvkm-y += nvkm/core/ioctl.o nvkm-y += nvkm/core/memory.o nvkm-y += nvkm/core/mm.o diff --git a/drivers/gpu/drm/nouveau/nvkm/core/intr.c b/drivers/gpu/drm/nouveau/nvkm/core/intr.c new file mode 100644 index 000000000000..89f601567749 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/core/intr.c @@ -0,0 +1,109 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include + +#include +#include + +static void +nvkm_intr_rearm_locked(struct nvkm_device *device) +{ + nvkm_mc_intr_rearm(device); +} + +static void +nvkm_intr_unarm_locked(struct nvkm_device *device) +{ + nvkm_mc_intr_unarm(device); +} + +static irqreturn_t +nvkm_intr(int irq, void *arg) +{ + struct nvkm_device *device = arg; + irqreturn_t ret = IRQ_NONE; + bool handled; + + spin_lock(&device->intr.lock); + if (!device->intr.armed) + goto done_unlock; + + nvkm_intr_unarm_locked(device); + nvkm_pci_msi_rearm(device); + + nvkm_mc_intr(device, &handled); + if (handled) + ret = IRQ_HANDLED; + + nvkm_intr_rearm_locked(device); +done_unlock: + spin_unlock(&device->intr.lock); + return ret; +} + +void +nvkm_intr_rearm(struct nvkm_device *device) +{ + spin_lock_irq(&device->intr.lock); + nvkm_intr_rearm_locked(device); + device->intr.armed = true; + spin_unlock_irq(&device->intr.lock); +} + +void +nvkm_intr_unarm(struct nvkm_device *device) +{ + spin_lock_irq(&device->intr.lock); + nvkm_intr_unarm_locked(device); + device->intr.armed = false; + spin_unlock_irq(&device->intr.lock); +} + +int +nvkm_intr_install(struct nvkm_device *device) +{ + int ret; + + device->intr.irq = device->func->irq(device); + if (device->intr.irq < 0) + return device->intr.irq; + + ret = request_irq(device->intr.irq, nvkm_intr, IRQF_SHARED, "nvkm", device); + if (ret) + return ret; + + device->intr.alloc = true; + return 0; +} + +void +nvkm_intr_dtor(struct nvkm_device *device) +{ + if (device->intr.alloc) + free_irq(device->intr.irq, device); +} + +void +nvkm_intr_ctor(struct nvkm_device *device) +{ + spin_lock_init(&device->intr.lock); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index c45ff9df0727..44fdb6f5f225 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2734,6 +2734,8 @@ nvkm_device_fini(struct nvkm_device *device, bool suspend) if (device->func->fini) device->func->fini(device, suspend); + nvkm_intr_unarm(device); + time = ktime_to_us(ktime_get()) - time; nvdev_trace(device, "%s completed in %lldus...\n", action, time); return 0; @@ -2759,6 +2761,8 @@ nvkm_device_preinit(struct nvkm_device *device) nvdev_trace(device, "preinit running...\n"); time = ktime_to_us(ktime_get()); + nvkm_intr_unarm(device); + if (device->func->preinit) { ret = device->func->preinit(device); if (ret) @@ -2804,6 +2808,8 @@ nvkm_device_init(struct nvkm_device *device) nvdev_trace(device, "init running...\n"); time = ktime_to_us(ktime_get()); + nvkm_intr_rearm(device); + if (device->func->init) { ret = device->func->init(device); if (ret) @@ -2841,6 +2847,8 @@ nvkm_device_del(struct nvkm_device **pdevice) if (device) { mutex_lock(&nv_devices_mutex); + nvkm_intr_dtor(device); + list_for_each_entry_safe_reverse(subdev, subtmp, &device->subdev, head) nvkm_subdev_del(&subdev); @@ -3148,6 +3156,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, device->name = device->chip->name; mutex_init(&device->mutex); + nvkm_intr_ctor(device); #define NVKM_LAYOUT_ONCE(type,data,ptr) \ if (device->chip->ptr.inst && (subdev_mask & (BIT_ULL(type)))) { \ @@ -3189,7 +3198,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, #undef NVKM_LAYOUT_INST #undef NVKM_LAYOUT_ONCE - ret = 0; + ret = nvkm_intr_install(device); done: if (device->pri && (!mmio || ret)) { iounmap(device->pri); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c index f302d2b5782a..abccb2bb68a6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c @@ -1574,6 +1574,12 @@ nvkm_device_pci_resource_size(struct nvkm_device *device, unsigned bar) return pci_resource_len(pdev->pdev, bar); } +static int +nvkm_device_pci_irq(struct nvkm_device *device) +{ + return nvkm_device_pci(device)->pdev->irq; +} + static void nvkm_device_pci_fini(struct nvkm_device *device, bool suspend) { @@ -1612,6 +1618,7 @@ nvkm_device_pci_func = { .dtor = nvkm_device_pci_dtor, .preinit = nvkm_device_pci_preinit, .fini = nvkm_device_pci_fini, + .irq = nvkm_device_pci_irq, .resource_addr = nvkm_device_pci_resource_addr, .resource_size = nvkm_device_pci_resource_size, .cpu_coherent = !IS_ENABLED(CONFIG_ARM), diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index ac9e122586bc..87caa4a72921 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -206,45 +206,12 @@ nvkm_device_tegra_resource_size(struct nvkm_device *device, unsigned bar) return res ? resource_size(res) : 0; } -static irqreturn_t -nvkm_device_tegra_intr(int irq, void *arg) -{ - struct nvkm_device_tegra *tdev = arg; - struct nvkm_device *device = &tdev->device; - bool handled = false; - nvkm_mc_intr_unarm(device); - nvkm_mc_intr(device, &handled); - nvkm_mc_intr_rearm(device); - return handled ? IRQ_HANDLED : IRQ_NONE; -} - -static void -nvkm_device_tegra_fini(struct nvkm_device *device, bool suspend) -{ - struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); - if (tdev->irq) { - free_irq(tdev->irq, tdev); - tdev->irq = 0; - } -} - static int -nvkm_device_tegra_init(struct nvkm_device *device) +nvkm_device_tegra_irq(struct nvkm_device *device) { struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); - int irq, ret; - - irq = platform_get_irq_byname(tdev->pdev, "stall"); - if (irq < 0) - return irq; - ret = request_irq(irq, nvkm_device_tegra_intr, - IRQF_SHARED, "nvkm", tdev); - if (ret) - return ret; - - tdev->irq = irq; - return 0; + return platform_get_irq_byname(tdev->pdev, "stall"); } static void * @@ -260,8 +227,7 @@ static const struct nvkm_device_func nvkm_device_tegra_func = { .tegra = nvkm_device_tegra, .dtor = nvkm_device_tegra_dtor, - .init = nvkm_device_tegra_init, - .fini = nvkm_device_tegra_fini, + .irq = nvkm_device_tegra_irq, .resource_addr = nvkm_device_tegra_resource_addr, .resource_size = nvkm_device_tegra_resource_size, .cpu_coherent = false, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c index a7d42ea8ba28..5a0de45d36ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c @@ -26,7 +26,15 @@ #include #include -#include + +void +nvkm_pci_msi_rearm(struct nvkm_device *device) +{ + struct nvkm_pci *pci = device->pci; + + if (pci && pci->msi) + pci->func->msi_rearm(pci); +} u32 nvkm_pci_rd32(struct nvkm_pci *pci, u16 addr) @@ -65,24 +73,6 @@ nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow) nvkm_pci_wr32(pci, 0x0050, data); } -static irqreturn_t -nvkm_pci_intr(int irq, void *arg) -{ - struct nvkm_pci *pci = arg; - struct nvkm_device *device = pci->subdev.device; - bool handled = false; - - if (pci->irq < 0) - return IRQ_HANDLED; - - nvkm_mc_intr_unarm(device); - if (pci->msi) - pci->func->msi_rearm(pci); - nvkm_mc_intr(device, &handled); - nvkm_mc_intr_rearm(device); - return handled ? IRQ_HANDLED : IRQ_NONE; -} - static int nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend) { @@ -107,7 +97,6 @@ static int nvkm_pci_oneinit(struct nvkm_subdev *subdev) { struct nvkm_pci *pci = nvkm_pci(subdev); - struct pci_dev *pdev = pci->pdev; int ret; if (pci_is_pcie(pci->pdev)) { @@ -116,11 +105,6 @@ nvkm_pci_oneinit(struct nvkm_subdev *subdev) return ret; } - ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci); - if (ret) - return ret; - - pci->irq = pdev->irq; return 0; } @@ -157,15 +141,6 @@ nvkm_pci_dtor(struct nvkm_subdev *subdev) nvkm_agp_dtor(pci); - if (pci->irq >= 0) { - /* freq_irq() will call the handler, we use pci->irq == -1 - * to signal that it's been torn down and should be a noop. - */ - int irq = pci->irq; - pci->irq = -1; - free_irq(irq, pci); - } - if (pci->msi) pci_disable_msi(pci->pdev); @@ -192,7 +167,6 @@ nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device, nvkm_subdev_ctor(&nvkm_pci_func, device, type, inst, &pci->subdev); pci->func = func; pci->pdev = device->func->pci(device)->pdev; - pci->irq = -1; pci->pcie.speed = -1; pci->pcie.width = -1; -- cgit v1.2.3 From 3ebd64aa3c4fe7fa2e73f6fa5f81490721a9c4e1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:52 +1000 Subject: drm/nouveau/intr: support multiple trees, and explicit interfaces Turing adds a second top-level interrupt tree in HW, in addition to the trees available via NV_PMC. Most of the interrupts we care about are exposed in both trees, but not all of them, and we have some rather nasty hacks to route the fault buffer interrupts. Ampere removes the NV_PMC trees entirely. Here we add some infrastructure to be able to handle all of this more cleanly, as well as providing more explicit control over handlers. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/device.h | 2 + drivers/gpu/drm/nouveau/include/nvkm/core/intr.h | 60 +++++ drivers/gpu/drm/nouveau/nvkm/core/intr.c | 284 ++++++++++++++++++++- 3 files changed, 344 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index 6752a4c317e2..555e3fe06341 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -63,6 +63,8 @@ struct nvkm_device { struct list_head subdev; struct { + struct list_head intr; + struct list_head prio[NVKM_INTR_PRIO_NR]; spinlock_t lock; int irq; bool alloc; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h b/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h index b4d49ff40c6a..ec7db1312277 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h @@ -3,10 +3,70 @@ #define __NVKM_INTR_H__ #include struct nvkm_device; +struct nvkm_subdev; + +enum nvkm_intr_prio { + NVKM_INTR_PRIO_VBLANK = 0, + NVKM_INTR_PRIO_NORMAL, + NVKM_INTR_PRIO_NR +}; + +enum nvkm_intr_type { + NVKM_INTR_SUBDEV = -1, /* lookup vector by requesting subdev, in mapping table. */ + NVKM_INTR_VECTOR_0 = 0, +}; + +struct nvkm_intr { + const struct nvkm_intr_func { + bool (*pending)(struct nvkm_intr *); + void (*unarm)(struct nvkm_intr *); + void (*rearm)(struct nvkm_intr *); + void (*block)(struct nvkm_intr *, int leaf, u32 mask); + void (*allow)(struct nvkm_intr *, int leaf, u32 mask); + void (*reset)(struct nvkm_intr *, int leaf, u32 mask); + } *func; + const struct nvkm_intr_data { + int type; /* enum nvkm_subdev_type (+ve), enum nvkm_intr_type (-ve) */ + int inst; + int leaf; + u32 mask; /* 0-terminated. */ + } *data; + + struct nvkm_subdev *subdev; + int leaves; + u32 *stat; + u32 *mask; + + struct list_head head; +}; void nvkm_intr_ctor(struct nvkm_device *); void nvkm_intr_dtor(struct nvkm_device *); int nvkm_intr_install(struct nvkm_device *); void nvkm_intr_unarm(struct nvkm_device *); void nvkm_intr_rearm(struct nvkm_device *); + +int nvkm_intr_add(const struct nvkm_intr_func *, const struct nvkm_intr_data *, + struct nvkm_subdev *, int leaves, struct nvkm_intr *); +void nvkm_intr_block(struct nvkm_subdev *, enum nvkm_intr_type); +void nvkm_intr_allow(struct nvkm_subdev *, enum nvkm_intr_type); + +struct nvkm_inth; +typedef irqreturn_t (*nvkm_inth_func)(struct nvkm_inth *); + +struct nvkm_inth { + struct nvkm_intr *intr; + int leaf; + u32 mask; + nvkm_inth_func func; + + atomic_t allowed; + + struct list_head head; +}; + +int nvkm_inth_add(struct nvkm_intr *, enum nvkm_intr_type, enum nvkm_intr_prio, + struct nvkm_subdev *, nvkm_inth_func, struct nvkm_inth *); +void nvkm_inth_allow(struct nvkm_inth *); +void nvkm_inth_block(struct nvkm_inth *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/core/intr.c b/drivers/gpu/drm/nouveau/nvkm/core/intr.c index 89f601567749..ff95e018fa78 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/intr.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/intr.c @@ -20,19 +20,147 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include - +#include +#include #include +#include + #include +static int +nvkm_intr_xlat(struct nvkm_subdev *subdev, struct nvkm_intr *intr, + enum nvkm_intr_type type, int *leaf, u32 *mask) +{ + struct nvkm_device *device = subdev->device; + + if (type < NVKM_INTR_VECTOR_0) { + if (type == NVKM_INTR_SUBDEV) { + const struct nvkm_intr_data *data = intr->data; + struct nvkm_top_device *tdev; + + while (data && data->mask) { + if (data->type == NVKM_SUBDEV_TOP) { + list_for_each_entry(tdev, &device->top->device, head) { + if (tdev->intr >= 0 && + tdev->type == subdev->type && + tdev->inst == subdev->inst) { + if (data->mask & BIT(tdev->intr)) { + *leaf = data->leaf; + *mask = BIT(tdev->intr); + return 0; + } + } + } + } else + if (data->type == subdev->type && data->inst == subdev->inst) { + *leaf = data->leaf; + *mask = data->mask; + return 0; + } + + data++; + } + } else { + return -ENOSYS; + } + } else { + if (type < intr->leaves * sizeof(*intr->stat) * 8) { + *leaf = type / 32; + *mask = BIT(type % 32); + return 0; + } + } + + return -EINVAL; +} + +static struct nvkm_intr * +nvkm_intr_find(struct nvkm_subdev *subdev, enum nvkm_intr_type type, int *leaf, u32 *mask) +{ + struct nvkm_intr *intr; + int ret; + + list_for_each_entry(intr, &subdev->device->intr.intr, head) { + ret = nvkm_intr_xlat(subdev, intr, type, leaf, mask); + if (ret == 0) + return intr; + } + + return NULL; +} + +static void +nvkm_intr_allow_locked(struct nvkm_intr *intr, int leaf, u32 mask) +{ + intr->mask[leaf] |= mask; + if (intr->func->allow) { + if (intr->func->reset) + intr->func->reset(intr, leaf, mask); + intr->func->allow(intr, leaf, mask); + } +} + +void +nvkm_intr_allow(struct nvkm_subdev *subdev, enum nvkm_intr_type type) +{ + struct nvkm_device *device = subdev->device; + struct nvkm_intr *intr; + unsigned long flags; + int leaf; + u32 mask; + + intr = nvkm_intr_find(subdev, type, &leaf, &mask); + if (intr) { + nvkm_debug(intr->subdev, "intr %d/%08x allowed by %s\n", leaf, mask, subdev->name); + spin_lock_irqsave(&device->intr.lock, flags); + nvkm_intr_allow_locked(intr, leaf, mask); + spin_unlock_irqrestore(&device->intr.lock, flags); + } +} + +static void +nvkm_intr_block_locked(struct nvkm_intr *intr, int leaf, u32 mask) +{ + intr->mask[leaf] &= ~mask; + if (intr->func->block) + intr->func->block(intr, leaf, mask); +} + +void +nvkm_intr_block(struct nvkm_subdev *subdev, enum nvkm_intr_type type) +{ + struct nvkm_device *device = subdev->device; + struct nvkm_intr *intr; + unsigned long flags; + int leaf; + u32 mask; + + intr = nvkm_intr_find(subdev, type, &leaf, &mask); + if (intr) { + nvkm_debug(intr->subdev, "intr %d/%08x blocked by %s\n", leaf, mask, subdev->name); + spin_lock_irqsave(&device->intr.lock, flags); + nvkm_intr_block_locked(intr, leaf, mask); + spin_unlock_irqrestore(&device->intr.lock, flags); + } +} + static void nvkm_intr_rearm_locked(struct nvkm_device *device) { + struct nvkm_intr *intr; + + list_for_each_entry(intr, &device->intr.intr, head) + intr->func->rearm(intr); nvkm_mc_intr_rearm(device); } static void nvkm_intr_unarm_locked(struct nvkm_device *device) { + struct nvkm_intr *intr; + + list_for_each_entry(intr, &device->intr.intr, head) + intr->func->unarm(intr); nvkm_mc_intr_unarm(device); } @@ -40,9 +168,13 @@ static irqreturn_t nvkm_intr(int irq, void *arg) { struct nvkm_device *device = arg; + struct nvkm_intr *intr; + struct nvkm_inth *inth; irqreturn_t ret = IRQ_NONE; - bool handled; + bool pending = false, handled; + int prio, leaf; + /* Disable all top-level interrupt sources, and re-arm MSI interrupts. */ spin_lock(&device->intr.lock); if (!device->intr.armed) goto done_unlock; @@ -50,20 +182,103 @@ nvkm_intr(int irq, void *arg) nvkm_intr_unarm_locked(device); nvkm_pci_msi_rearm(device); + /* Fetch pending interrupt masks. */ + list_for_each_entry(intr, &device->intr.intr, head) { + if (intr->func->pending(intr)) + pending = true; + } + nvkm_mc_intr(device, &handled); if (handled) ret = IRQ_HANDLED; + if (!pending) + goto done; + + /* Check that GPU is still on the bus by reading NV_PMC_BOOT_0. */ + if (WARN_ON(nvkm_rd32(device, 0x000000) == 0xffffffff)) + goto done; + + /* Execute handlers. */ + for (prio = 0; prio < ARRAY_SIZE(device->intr.prio); prio++) { + list_for_each_entry(inth, &device->intr.prio[prio], head) { + struct nvkm_intr *intr = inth->intr; + + if (intr->stat[inth->leaf] & inth->mask) { + if (atomic_read(&inth->allowed)) { + if (intr->func->reset) + intr->func->reset(intr, inth->leaf, inth->mask); + if (inth->func(inth) == IRQ_HANDLED) + ret = IRQ_HANDLED; + } + } + } + } + + /* Nothing handled? Some debugging/protection from IRQ storms is in order... */ + if (ret == IRQ_NONE) { + list_for_each_entry(intr, &device->intr.intr, head) { + for (leaf = 0; leaf < intr->leaves; leaf++) { + if (intr->stat[leaf]) { + nvkm_warn(intr->subdev, "intr%d: %08x\n", + leaf, intr->stat[leaf]); + nvkm_intr_block_locked(intr, leaf, intr->stat[leaf]); + } + } + } + } + +done: + /* Re-enable all top-level interrupt sources. */ nvkm_intr_rearm_locked(device); done_unlock: spin_unlock(&device->intr.lock); return ret; } +int +nvkm_intr_add(const struct nvkm_intr_func *func, const struct nvkm_intr_data *data, + struct nvkm_subdev *subdev, int leaves, struct nvkm_intr *intr) +{ + struct nvkm_device *device = subdev->device; + int i; + + intr->func = func; + intr->data = data; + intr->subdev = subdev; + intr->leaves = leaves; + intr->stat = kcalloc(leaves, sizeof(*intr->stat), GFP_KERNEL); + intr->mask = kcalloc(leaves, sizeof(*intr->mask), GFP_KERNEL); + if (!intr->stat || !intr->mask) { + kfree(intr->stat); + return -ENOMEM; + } + + if (intr->subdev->debug >= NV_DBG_DEBUG) { + for (i = 0; i < intr->leaves; i++) + intr->mask[i] = ~0; + } + + spin_lock_irq(&device->intr.lock); + list_add_tail(&intr->head, &device->intr.intr); + spin_unlock_irq(&device->intr.lock); + return 0; +} + void nvkm_intr_rearm(struct nvkm_device *device) { + struct nvkm_intr *intr; + int i; + spin_lock_irq(&device->intr.lock); + list_for_each_entry(intr, &device->intr.intr, head) { + for (i = 0; intr->func->block && i < intr->leaves; i++) { + intr->func->block(intr, i, ~0); + intr->func->allow(intr, i, intr->mask[i]); + } + } + nvkm_intr_rearm_locked(device); device->intr.armed = true; spin_unlock_irq(&device->intr.lock); @@ -98,6 +313,14 @@ nvkm_intr_install(struct nvkm_device *device) void nvkm_intr_dtor(struct nvkm_device *device) { + struct nvkm_intr *intr, *intt; + + list_for_each_entry_safe(intr, intt, &device->intr.intr, head) { + list_del(&intr->head); + kfree(intr->mask); + kfree(intr->stat); + } + if (device->intr.alloc) free_irq(device->intr.irq, device); } @@ -105,5 +328,62 @@ nvkm_intr_dtor(struct nvkm_device *device) void nvkm_intr_ctor(struct nvkm_device *device) { + int i; + + INIT_LIST_HEAD(&device->intr.intr); + for (i = 0; i < ARRAY_SIZE(device->intr.prio); i++) + INIT_LIST_HEAD(&device->intr.prio[i]); + spin_lock_init(&device->intr.lock); + device->intr.armed = false; +} + +void +nvkm_inth_block(struct nvkm_inth *inth) +{ + if (unlikely(!inth->intr)) + return; + + atomic_set(&inth->allowed, 0); +} + +void +nvkm_inth_allow(struct nvkm_inth *inth) +{ + struct nvkm_intr *intr = inth->intr; + unsigned long flags; + + if (unlikely(!inth->intr)) + return; + + spin_lock_irqsave(&intr->subdev->device->intr.lock, flags); + if (!atomic_xchg(&inth->allowed, 1)) { + if ((intr->mask[inth->leaf] & inth->mask) != inth->mask) + nvkm_intr_allow_locked(intr, inth->leaf, inth->mask); + } + spin_unlock_irqrestore(&intr->subdev->device->intr.lock, flags); +} + +int +nvkm_inth_add(struct nvkm_intr *intr, enum nvkm_intr_type type, enum nvkm_intr_prio prio, + struct nvkm_subdev *subdev, nvkm_inth_func func, struct nvkm_inth *inth) +{ + struct nvkm_device *device = subdev->device; + int ret; + + if (WARN_ON(inth->mask)) + return -EBUSY; + + ret = nvkm_intr_xlat(subdev, intr, type, &inth->leaf, &inth->mask); + if (ret) + return ret; + + nvkm_debug(intr->subdev, "intr %d/%08x requested by %s\n", + inth->leaf, inth->mask, subdev->name); + + inth->intr = intr; + inth->func = func; + atomic_set(&inth->allowed, 0); + list_add_tail(&inth->head, &device->intr.prio[prio]); + return 0; } -- cgit v1.2.3 From a7ab200aebc23095474e6dc8e335e60473086236 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:53 +1000 Subject: drm/nouveau/intr: add nvkm_subdev_intr() compatibility It's quite a lot of tedious and error-prone work to switch over all the subdevs at once, so allow an nvkm_intr to request new-style handlers to be created that wrap the existing interfaces. This will allow a more gradual transition. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/device.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/core/intr.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 2 + drivers/gpu/drm/nouveau/nvkm/core/intr.c | 61 ++++++++++++++++++++++ 4 files changed, 65 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index 555e3fe06341..f65b5009acf7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -69,6 +69,7 @@ struct nvkm_device { int irq; bool alloc; bool armed; + bool legacy_done; } intr; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h b/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h index ec7db1312277..a003d6a544b0 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h @@ -30,6 +30,7 @@ struct nvkm_intr { int inst; int leaf; u32 mask; /* 0-terminated. */ + bool legacy; /* auto-create "legacy" nvkm_subdev_intr() handler */ } *data; struct nvkm_subdev *subdev; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h index 96113c8bee8c..20e1fc90c536 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h @@ -21,6 +21,8 @@ struct nvkm_subdev { u32 debug; struct list_head head; + struct nvkm_inth inth; + void **pself; bool oneinit; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/intr.c b/drivers/gpu/drm/nouveau/nvkm/core/intr.c index ff95e018fa78..3f3fe3d416e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/intr.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/intr.c @@ -265,12 +265,73 @@ nvkm_intr_add(const struct nvkm_intr_func *func, const struct nvkm_intr_data *da return 0; } +static irqreturn_t +nvkm_intr_subdev(struct nvkm_inth *inth) +{ + struct nvkm_subdev *subdev = container_of(inth, typeof(*subdev), inth); + + nvkm_subdev_intr(subdev); + return IRQ_HANDLED; +} + +static void +nvkm_intr_subdev_add_dev(struct nvkm_intr *intr, enum nvkm_subdev_type type, int inst) +{ + struct nvkm_subdev *subdev; + enum nvkm_intr_prio prio; + int ret; + + subdev = nvkm_device_subdev(intr->subdev->device, type, inst); + if (!subdev || !subdev->func->intr) + return; + + if (type == NVKM_ENGINE_DISP) + prio = NVKM_INTR_PRIO_VBLANK; + else + prio = NVKM_INTR_PRIO_NORMAL; + + ret = nvkm_inth_add(intr, NVKM_INTR_SUBDEV, prio, subdev, nvkm_intr_subdev, &subdev->inth); + if (WARN_ON(ret)) + return; + + nvkm_inth_allow(&subdev->inth); +} + +static void +nvkm_intr_subdev_add(struct nvkm_intr *intr) +{ + const struct nvkm_intr_data *data; + struct nvkm_device *device = intr->subdev->device; + struct nvkm_top_device *tdev; + + for (data = intr->data; data && data->mask; data++) { + if (data->legacy) { + if (data->type == NVKM_SUBDEV_TOP) { + list_for_each_entry(tdev, &device->top->device, head) { + if (tdev->intr < 0 || !(data->mask & BIT(tdev->intr))) + continue; + + nvkm_intr_subdev_add_dev(intr, tdev->type, tdev->inst); + } + } else { + nvkm_intr_subdev_add_dev(intr, data->type, data->inst); + } + } + } +} + void nvkm_intr_rearm(struct nvkm_device *device) { struct nvkm_intr *intr; int i; + if (unlikely(!device->intr.legacy_done)) { + list_for_each_entry(intr, &device->intr.intr, head) + nvkm_intr_subdev_add(intr); + device->intr.legacy_done = true; + } + spin_lock_irq(&device->intr.lock); list_for_each_entry(intr, &device->intr.intr, head) { for (i = 0; intr->func->block && i < intr->leaves; i++) { -- cgit v1.2.3 From f83d1c3114182a0d826c929912e5ae94b7aeebc6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:53 +1000 Subject: drm/nouveau/vfn: add stub subdev for dev_func Initially for NV_USERMODE class, and Turing/Ampere's new interrupt tree. v2. fixup for ga103 early merge Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/layout.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h | 18 ++++++++ drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 12 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild | 5 +++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c | 48 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c | 33 +++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c | 33 +++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h | 12 ++++++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c | 33 +++++++++++++++ 11 files changed, 197 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h index 7afe1579b20f..a344ddb77c80 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: MIT */ +NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VFN , struct nvkm_vfn , vfn) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_PCI , struct nvkm_pci , pci) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VBIOS , struct nvkm_bios , bios) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_DEVINIT , struct nvkm_devinit , devinit) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h new file mode 100644 index 000000000000..85c1bd36ee50 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_VFN_H__ +#define __NVKM_VFN_H__ +#include + +struct nvkm_vfn { + const struct nvkm_vfn_func *func; + struct nvkm_subdev subdev; + + struct { + u32 priv; + } addr; +}; + +int gv100_vfn_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_vfn **); +int tu102_vfn_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_vfn **); +int ga100_vfn_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_vfn **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 44fdb6f5f225..88b92306dd49 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2385,6 +2385,7 @@ nv140_chipset = { .therm = { 0x00000001, gp100_therm_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, gk104_top_new }, + .vfn = { 0x00000001, gv100_vfn_new }, .ce = { 0x000001ff, gv100_ce_new }, .disp = { 0x00000001, gv100_disp_new }, .dma = { 0x00000001, gv100_dma_new }, @@ -2419,6 +2420,7 @@ nv162_chipset = { .therm = { 0x00000001, gp100_therm_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, gk104_top_new }, + .vfn = { 0x00000001, tu102_vfn_new }, .ce = { 0x0000001f, tu102_ce_new }, .disp = { 0x00000001, tu102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, @@ -2453,6 +2455,7 @@ nv164_chipset = { .therm = { 0x00000001, gp100_therm_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, gk104_top_new }, + .vfn = { 0x00000001, tu102_vfn_new }, .ce = { 0x0000001f, tu102_ce_new }, .disp = { 0x00000001, tu102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, @@ -2487,6 +2490,7 @@ nv166_chipset = { .therm = { 0x00000001, gp100_therm_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, gk104_top_new }, + .vfn = { 0x00000001, tu102_vfn_new }, .ce = { 0x0000001f, tu102_ce_new }, .disp = { 0x00000001, tu102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, @@ -2521,6 +2525,7 @@ nv167_chipset = { .therm = { 0x00000001, gp100_therm_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, gk104_top_new }, + .vfn = { 0x00000001, tu102_vfn_new }, .ce = { 0x0000001f, tu102_ce_new }, .disp = { 0x00000001, tu102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, @@ -2555,6 +2560,7 @@ nv168_chipset = { .therm = { 0x00000001, gp100_therm_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, gk104_top_new }, + .vfn = { 0x00000001, tu102_vfn_new }, .ce = { 0x0000001f, tu102_ce_new }, .disp = { 0x00000001, tu102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, @@ -2581,6 +2587,7 @@ nv170_chipset = { .privring = { 0x00000001, gm200_privring_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, + .vfn = { 0x00000001, ga100_vfn_new }, }; static const struct nvkm_device_chip @@ -2599,6 +2606,7 @@ nv172_chipset = { .privring = { 0x00000001, gm200_privring_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, + .vfn = { 0x00000001, ga100_vfn_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, @@ -2620,6 +2628,7 @@ nv173_chipset = { .privring = { 0x00000001, gm200_privring_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, + .vfn = { 0x00000001, ga100_vfn_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, @@ -2641,6 +2650,7 @@ nv174_chipset = { .privring = { 0x00000001, gm200_privring_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, + .vfn = { 0x00000001, ga100_vfn_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, @@ -2662,6 +2672,7 @@ nv176_chipset = { .privring = { 0x00000001, gm200_privring_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, + .vfn = { 0x00000001, ga100_vfn_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, @@ -2683,6 +2694,7 @@ nv177_chipset = { .privring = { 0x00000001, gm200_privring_new }, .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, + .vfn = { 0x00000001, ga100_vfn_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h index 93949b3c7214..24faaac15891 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild index 2cb24fff7e32..4c2f6fc4ef58 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild @@ -23,4 +23,5 @@ include $(src)/nvkm/subdev/privring/Kbuild include $(src)/nvkm/subdev/therm/Kbuild include $(src)/nvkm/subdev/timer/Kbuild include $(src)/nvkm/subdev/top/Kbuild +include $(src)/nvkm/subdev/vfn/Kbuild include $(src)/nvkm/subdev/volt/Kbuild diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild new file mode 100644 index 000000000000..21c975a6b206 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MIT +nvkm-y += nvkm/subdev/vfn/base.o +nvkm-y += nvkm/subdev/vfn/gv100.o +nvkm-y += nvkm/subdev/vfn/tu102.o +nvkm-y += nvkm/subdev/vfn/ga100.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c new file mode 100644 index 000000000000..682ca3ed725b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c @@ -0,0 +1,48 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +static void * +nvkm_vfn_dtor(struct nvkm_subdev *subdev) +{ + return nvkm_vfn(subdev); +} + +static const struct nvkm_subdev_func +nvkm_vfn = { + .dtor = nvkm_vfn_dtor, +}; + +int +nvkm_vfn_new_(const struct nvkm_vfn_func *func, struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, u32 addr, struct nvkm_vfn **pvfn) +{ + struct nvkm_vfn *vfn; + + if (!(vfn = *pvfn = kzalloc(sizeof(*vfn), GFP_KERNEL))) + return -ENOMEM; + + nvkm_subdev_ctor(&nvkm_vfn, device, type, inst, &vfn->subdev); + vfn->func = func; + vfn->addr.priv = addr; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c new file mode 100644 index 000000000000..979402dff659 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c @@ -0,0 +1,33 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +static const struct nvkm_vfn_func +ga100_vfn = { +}; + +int +ga100_vfn_new(struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_vfn **pvfn) +{ + return nvkm_vfn_new_(&ga100_vfn, device, type, inst, 0xb80000, pvfn); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c new file mode 100644 index 000000000000..83dd79bddd86 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c @@ -0,0 +1,33 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +static const struct nvkm_vfn_func +gv100_vfn = { +}; + +int +gv100_vfn_new(struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_vfn **pvfn) +{ + return nvkm_vfn_new_(&gv100_vfn, device, type, inst, 0, pvfn); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h new file mode 100644 index 000000000000..174817c76bf9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_VFN_PRIV_H__ +#define __NVKM_VFN_PRIV_H__ +#define nvkm_vfn(p) container_of((p), struct nvkm_vfn, subdev) +#include + +struct nvkm_vfn_func { +}; + +int nvkm_vfn_new_(const struct nvkm_vfn_func *, struct nvkm_device *, enum nvkm_subdev_type, int, + u32 addr, struct nvkm_vfn **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c new file mode 100644 index 000000000000..999e50f5c36b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c @@ -0,0 +1,33 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +static const struct nvkm_vfn_func +tu102_vfn = { +}; + +int +tu102_vfn_new(struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_vfn **pvfn) +{ + return nvkm_vfn_new_(&tu102_vfn, device, type, inst, 0xb80000, pvfn); +} -- cgit v1.2.3 From 58c3d3c837297051479d552753f04e4561453403 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:53 +1000 Subject: drm/nouveau/vfn: move NV_USERMODE class from host - uses proper class IDs for Turing/Ampere Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/class.h | 2 + drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h | 3 + drivers/gpu/drm/nouveau/nvif/user.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/device/user.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 3 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c | 20 +------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h | 8 --- .../gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c | 45 --------------- .../gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c | 45 --------------- drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c | 4 ++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c | 3 + drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c | 3 + drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h | 8 +++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c | 3 + drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c | 67 ++++++++++++++++++++++ 18 files changed, 100 insertions(+), 125 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index 3e9d181b5dda..a623fb67280b 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -63,6 +63,8 @@ #define NV04_DISP /* cl0046.h */ 0x00000046 #define VOLTA_USERMODE_A 0x0000c361 +#define TURING_USERMODE_A 0x0000c461 +#define AMPERE_USERMODE_A 0x0000c561 #define MAXWELL_FAULT_BUFFER_A /* clb069.h */ 0x0000b069 #define VOLTA_FAULT_BUFFER_A /* clb069.h */ 0x0000c369 diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h index 85c1bd36ee50..fb04d5cd34bf 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h @@ -9,7 +9,10 @@ struct nvkm_vfn { struct { u32 priv; + u32 user; } addr; + + struct nvkm_device_oclass user; }; int gv100_vfn_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_vfn **); diff --git a/drivers/gpu/drm/nouveau/nvif/user.c b/drivers/gpu/drm/nouveau/nvif/user.c index d89f5b67b304..b648a5e036af 100644 --- a/drivers/gpu/drm/nouveau/nvif/user.c +++ b/drivers/gpu/drm/nouveau/nvif/user.c @@ -41,7 +41,9 @@ nvif_user_ctor(struct nvif_device *device, const char *name) int version; const struct nvif_user_func *func; } users[] = { - { VOLTA_USERMODE_A, -1, &nvif_userc361 }, + { AMPERE_USERMODE_A, -1, &nvif_userc361 }, + { TURING_USERMODE_A, -1, &nvif_userc361 }, + { VOLTA_USERMODE_A, -1, &nvif_userc361 }, {} }; int cid, ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c index 45f509c11c36..9b39ec341615 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c @@ -342,6 +342,8 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index, sclass = &device->mmu->user; else if (device->fault && index-- == 0) sclass = &device->fault->user; + else if (device->vfn && index-- == 0) + sclass = &device->vfn->user; else return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index 5e831d347a95..0fa4df299009 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -35,6 +35,3 @@ nvkm-y += nvkm/engine/fifo/gpfifogf100.o nvkm-y += nvkm/engine/fifo/gpfifogk104.o nvkm-y += nvkm/engine/fifo/gpfifogv100.o nvkm-y += nvkm/engine/fifo/gpfifotu102.o - -nvkm-y += nvkm/engine/fifo/usergv100.o -nvkm-y += nvkm/engine/fifo/usertu102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c index c630dbd2911a..e228ca3a5203 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c @@ -22,7 +22,6 @@ #define ga102_fifo(p) container_of((p), struct ga102_fifo, base.engine) #define ga102_chan(p) container_of((p), struct ga102_chan, object) #include -#include "user.h" #include #include @@ -242,33 +241,16 @@ ga102_chan_oclass = { .ctor = ga102_chan_new, }; -static int -ga102_user_new(struct nvkm_device *device, - const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) -{ - return tu102_fifo_user_new(oclass, argv, argc, pobject); -} - -static const struct nvkm_device_oclass -ga102_user_oclass = { - .ctor = ga102_user_new, -}; - static int ga102_fifo_sclass(struct nvkm_oclass *oclass, int index, const struct nvkm_device_oclass **class) { if (index == 0) { - oclass->base = (struct nvkm_sclass) { -1, -1, VOLTA_USERMODE_A }; - *class = &ga102_user_oclass; - return 0; - } else - if (index == 1) { oclass->base = (struct nvkm_sclass) { 0, 0, AMPERE_CHANNEL_GPFIFO_B }; *class = &ga102_chan_oclass; return 0; } - return 2; + return 1; } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index faf0fe9f704c..f56369d59219 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -22,7 +22,6 @@ #include "gk104.h" #include "cgrp.h" #include "changk104.h" -#include "user.h" #include @@ -295,7 +294,6 @@ gv100_fifo = { .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, .runlist = &gv100_fifo_runlist, - .user = {{-1,-1,VOLTA_USERMODE_A }, gv100_fifo_user_new }, .chan = {{ 0, 0,VOLTA_CHANNEL_GPFIFO_A}, gv100_fifo_gpfifo_new }, .cgrp_force = true, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 260b197f81bc..b800cfc5bfd9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -22,7 +22,6 @@ #include "gk104.h" #include "cgrp.h" #include "changk104.h" -#include "user.h" #include #include @@ -110,7 +109,6 @@ tu102_fifo = { .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, .runlist = &tu102_fifo_runlist, - .user = {{-1,-1,VOLTA_USERMODE_A }, tu102_fifo_user_new }, .chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu102_fifo_gpfifo_new }, .cgrp_force = true, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h deleted file mode 100644 index 54a3a3092cc0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __NVKM_FIFO_USER_H__ -#define __NVKM_FIFO_USER_H__ -#include "priv.h" -int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -int tu102_fifo_user_new(const struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c deleted file mode 100644 index 3dc3b8b312de..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "user.h" - -static int -gv100_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct nvkm_device *device = object->engine->subdev.device; - *addr = 0x810000 + device->func->resource_addr(device, 0); - *size = 0x010000; - *type = NVKM_OBJECT_MAP_IO; - return 0; -} - -static const struct nvkm_object_func -gv100_fifo_user = { - .map = gv100_fifo_user_map, -}; - -int -gv100_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - return nvkm_object_new_(&gv100_fifo_user, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c deleted file mode 100644 index 217268f8ccad..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "user.h" - -static int -tu102_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct nvkm_device *device = object->engine->subdev.device; - *addr = 0xbb0000 + device->func->resource_addr(device, 0); - *size = 0x010000; - *type = NVKM_OBJECT_MAP_IO; - return 0; -} - -static const struct nvkm_object_func -tu102_fifo_user = { - .map = tu102_fifo_user_map, -}; - -int -tu102_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - return nvkm_object_new_(&tu102_fifo_user, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild index 21c975a6b206..23cd21b40a25 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild @@ -1,5 +1,6 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/subdev/vfn/base.o +nvkm-y += nvkm/subdev/vfn/uvfn.o nvkm-y += nvkm/subdev/vfn/gv100.o nvkm-y += nvkm/subdev/vfn/tu102.o nvkm-y += nvkm/subdev/vfn/ga100.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c index 682ca3ed725b..3aa042eec104 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c @@ -44,5 +44,9 @@ nvkm_vfn_new_(const struct nvkm_vfn_func *func, struct nvkm_device *device, nvkm_subdev_ctor(&nvkm_vfn, device, type, inst, &vfn->subdev); vfn->func = func; vfn->addr.priv = addr; + vfn->addr.user = vfn->addr.priv + func->user.addr; + + vfn->user.ctor = nvkm_uvfn_new; + vfn->user.base = func->user.base; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c index 979402dff659..626b64230fe5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c @@ -21,8 +21,11 @@ */ #include "priv.h" +#include + static const struct nvkm_vfn_func ga100_vfn = { + .user = { 0x030000, 0x010000, { -1, -1, AMPERE_USERMODE_A } }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c index 83dd79bddd86..ddd39d714c4a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c @@ -21,8 +21,11 @@ */ #include "priv.h" +#include + static const struct nvkm_vfn_func gv100_vfn = { + .user = { 0x810000, 0x010000, { -1, -1, VOLTA_USERMODE_A } }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h index 174817c76bf9..e6f436532392 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h @@ -5,8 +5,16 @@ #include struct nvkm_vfn_func { + struct { + u32 addr; + u32 size; + const struct nvkm_sclass base; + } user; }; int nvkm_vfn_new_(const struct nvkm_vfn_func *, struct nvkm_device *, enum nvkm_subdev_type, int, u32 addr, struct nvkm_vfn **); + +int nvkm_uvfn_new(struct nvkm_device *, const struct nvkm_oclass *, void *, u32, + struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c index 999e50f5c36b..9e1745d31fbb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c @@ -21,8 +21,11 @@ */ #include "priv.h" +#include + static const struct nvkm_vfn_func tu102_vfn = { + .user = { 0x030000, 0x010000, { -1, -1, TURING_USERMODE_A } }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c new file mode 100644 index 000000000000..c5460a14c541 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c @@ -0,0 +1,67 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#define nvkm_uvfn(p) container_of((p), struct nvkm_uvfn, object) +#include "priv.h" + +#include + +struct nvkm_uvfn { + struct nvkm_object object; + struct nvkm_vfn *vfn; +}; + +static int +nvkm_uvfn_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct nvkm_vfn *vfn = nvkm_uvfn(object)->vfn; + struct nvkm_device *device = vfn->subdev.device; + + *addr = device->func->resource_addr(device, 0) + vfn->addr.user; + *size = vfn->func->user.size; + *type = NVKM_OBJECT_MAP_IO; + return 0; +} + +static const struct nvkm_object_func +nvkm_uvfn = { + .map = nvkm_uvfn_map, +}; + +int +nvkm_uvfn_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, + void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_uvfn *uvfn; + + if (argc != 0) + return -ENOSYS; + + if (!(uvfn = kzalloc(sizeof(*uvfn), GFP_KERNEL))) + return -ENOMEM; + + nvkm_object_ctor(&nvkm_uvfn, oclass, &uvfn->object); + uvfn->vfn = device->vfn; + + *pobject = &uvfn->object; + return 0; +} -- cgit v1.2.3 From e650738055cebe1dec82765232697052bf6c22d5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:54 +1000 Subject: drm/nouveau/vfn/tu102-: support new-style interrupt tree - switches ampere over now, and removes its hack mc implementation Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h | 2 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c | 16 +---- drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c | 8 +++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c | 11 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h | 5 ++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c | 72 +++++++++++++++++++++++ 6 files changed, 99 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h index fb04d5cd34bf..cc6d0796c265 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h @@ -12,6 +12,8 @@ struct nvkm_vfn { u32 user; } addr; + struct nvkm_intr intr; + struct nvkm_device_oclass user; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c index 4105175dfccd..ec3eedfa541a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c @@ -24,36 +24,23 @@ static void ga100_mc_intr_unarm(struct nvkm_mc *mc) { - nvkm_wr32(mc->subdev.device, 0xb81610, 0x00000004); } static void ga100_mc_intr_rearm(struct nvkm_mc *mc) { - nvkm_wr32(mc->subdev.device, 0xb81608, 0x00000004); -} - -static void -ga100_mc_intr_mask(struct nvkm_mc *mc, u32 mask, u32 intr) -{ - nvkm_wr32(mc->subdev.device, 0xb81210, mask & intr ); - nvkm_wr32(mc->subdev.device, 0xb81410, mask & ~(mask & intr)); } static u32 ga100_mc_intr_stat(struct nvkm_mc *mc) { - u32 intr_top = nvkm_rd32(mc->subdev.device, 0xb81600), intr = 0x00000000; - if (intr_top & 0x00000004) - intr = nvkm_mask(mc->subdev.device, 0xb81010, 0x00000000, 0x00000000); - return intr; + return 0; } static void ga100_mc_init(struct nvkm_mc *mc) { nv50_mc_init(mc); - nvkm_wr32(mc->subdev.device, 0xb81210, 0xffffffff); } static const struct nvkm_mc_func @@ -62,7 +49,6 @@ ga100_mc = { .intr = gp100_mc_intr, .intr_unarm = ga100_mc_intr_unarm, .intr_rearm = ga100_mc_intr_rearm, - .intr_mask = ga100_mc_intr_mask, .intr_stat = ga100_mc_intr_stat, .reset = gk104_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c index 3aa042eec104..62e81d551f44 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c @@ -37,6 +37,7 @@ nvkm_vfn_new_(const struct nvkm_vfn_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, u32 addr, struct nvkm_vfn **pvfn) { struct nvkm_vfn *vfn; + int ret; if (!(vfn = *pvfn = kzalloc(sizeof(*vfn), GFP_KERNEL))) return -ENOMEM; @@ -46,6 +47,13 @@ nvkm_vfn_new_(const struct nvkm_vfn_func *func, struct nvkm_device *device, vfn->addr.priv = addr; vfn->addr.user = vfn->addr.priv + func->user.addr; + if (vfn->func->intr) { + ret = nvkm_intr_add(vfn->func->intr, vfn->func->intrs, + &vfn->subdev, 8, &vfn->intr); + if (ret) + return ret; + } + vfn->user.ctor = nvkm_uvfn_new; vfn->user.base = func->user.base; return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c index 626b64230fe5..fd5c6931322d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c @@ -23,8 +23,19 @@ #include +static const struct nvkm_intr_data +ga100_vfn_intrs[] = { + { NVKM_ENGINE_DISP , 0, 4, 0x04000000, true }, + { NVKM_SUBDEV_GPIO , 0, 4, 0x00200000, true }, + { NVKM_SUBDEV_I2C , 0, 4, 0x00200000, true }, + { NVKM_SUBDEV_PRIVRING, 0, 4, 0x40000000, true }, + {} +}; + static const struct nvkm_vfn_func ga100_vfn = { + .intr = &tu102_vfn_intr, + .intrs = ga100_vfn_intrs, .user = { 0x030000, 0x010000, { -1, -1, AMPERE_USERMODE_A } }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h index e6f436532392..96d53c02041b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h @@ -5,6 +5,9 @@ #include struct nvkm_vfn_func { + const struct nvkm_intr_func *intr; + const struct nvkm_intr_data *intrs; + struct { u32 addr; u32 size; @@ -15,6 +18,8 @@ struct nvkm_vfn_func { int nvkm_vfn_new_(const struct nvkm_vfn_func *, struct nvkm_device *, enum nvkm_subdev_type, int, u32 addr, struct nvkm_vfn **); +extern const struct nvkm_intr_func tu102_vfn_intr; + int nvkm_uvfn_new(struct nvkm_device *, const struct nvkm_oclass *, void *, u32, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c index 9e1745d31fbb..3d063fb5e136 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c @@ -23,8 +23,80 @@ #include +static void +tu102_vfn_intr_reset(struct nvkm_intr *intr, int leaf, u32 mask) +{ + struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr); + + nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1000 + (leaf * 4), mask); +} + +static void +tu102_vfn_intr_allow(struct nvkm_intr *intr, int leaf, u32 mask) +{ + struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr); + + nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1200 + (leaf * 4), mask); +} + +static void +tu102_vfn_intr_block(struct nvkm_intr *intr, int leaf, u32 mask) +{ + struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr); + + nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1400 + (leaf * 4), mask); +} + +static void +tu102_vfn_intr_rearm(struct nvkm_intr *intr) +{ + struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr); + + nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1608, 0x0000000f); +} + +static void +tu102_vfn_intr_unarm(struct nvkm_intr *intr) +{ + struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr); + + nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1610, 0x0000000f); +} + +static bool +tu102_vfn_intr_pending(struct nvkm_intr *intr) +{ + struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr); + struct nvkm_device *device = vfn->subdev.device; + u32 intr_top = nvkm_rd32(device, vfn->addr.priv + 0x1600); + int pending = 0, leaf; + + for (leaf = 0; leaf < 8; leaf++) { + if (intr_top & BIT(leaf / 2)) { + intr->stat[leaf] = nvkm_rd32(device, vfn->addr.priv + 0x1000 + (leaf * 4)); + if (intr->stat[leaf]) + pending++; + } else { + intr->stat[leaf] = 0; + } + } + + return pending != 0; +} + +const struct nvkm_intr_func +tu102_vfn_intr = { + .pending = tu102_vfn_intr_pending, + .unarm = tu102_vfn_intr_unarm, + .rearm = tu102_vfn_intr_rearm, + .block = tu102_vfn_intr_block, + .allow = tu102_vfn_intr_allow, + .reset = tu102_vfn_intr_reset, +}; + static const struct nvkm_vfn_func tu102_vfn = { + .intr = &tu102_vfn_intr, .user = { 0x030000, 0x010000, { -1, -1, TURING_USERMODE_A } }, }; -- cgit v1.2.3 From b59d810a47423e61ae4e0ded502585e6ee9b1d76 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:54 +1000 Subject: drm/nouveau/fault/tu102: switch to explicit intr handlers - reads vectors from HW, rather than being hardcoded - removes hacks to support routing via old interfaces Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/include/nvkm/subdev/fault.h | 2 + drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h | 2 + drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c | 107 +++++++++------------ drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c | 13 --- 4 files changed, 52 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h index e781c5e4dcae..e40bbf378a8d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h @@ -7,6 +7,8 @@ struct nvkm_fault { const struct nvkm_fault_func *func; struct nvkm_subdev subdev; + struct nvkm_inth info_fault; + struct nvkm_fault_buffer *buffer[2]; int buffer_nr; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h index 30cc0d088897..a5510332c402 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h @@ -16,6 +16,8 @@ struct nvkm_fault_buffer { u32 put; struct nvkm_memory *mem; u64 addr; + + struct nvkm_inth inth; }; int nvkm_fault_new_(const struct nvkm_fault_func *, struct nvkm_device *, enum nvkm_subdev_type, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c index 917a7343db31..967efaddae28 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c @@ -24,20 +24,27 @@ #include #include #include +#include #include #include +static irqreturn_t +tu102_fault_buffer_notify(struct nvkm_inth *inth) +{ + struct nvkm_fault_buffer *buffer = container_of(inth, typeof(*buffer), inth); + + nvkm_event_ntfy(&buffer->fault->event, buffer->id, NVKM_FAULT_BUFFER_EVENT_PENDING); + return IRQ_HANDLED; +} + static void tu102_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable) { - /*XXX: Earlier versions of RM touched the old regs on Turing, - * which don't appear to actually work anymore, but newer - * versions of RM don't appear to touch anything at all.. - */ - struct nvkm_device *device = buffer->fault->subdev.device; - - nvkm_mc_intr_mask(device, NVKM_SUBDEV_FAULT, 0, enable); + if (enable) + nvkm_inth_allow(&buffer->inth); + else + nvkm_inth_block(&buffer->inth); } static void @@ -46,10 +53,6 @@ tu102_fault_buffer_fini(struct nvkm_fault_buffer *buffer) struct nvkm_device *device = buffer->fault->subdev.device; const u32 foff = buffer->id * 0x20; - /* Disable the fault interrupts */ - nvkm_wr32(device, 0xb81408, 0x1); - nvkm_wr32(device, 0xb81410, 0x10); - nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x00000000); } @@ -59,10 +62,6 @@ tu102_fault_buffer_init(struct nvkm_fault_buffer *buffer) struct nvkm_device *device = buffer->fault->subdev.device; const u32 foff = buffer->id * 0x20; - /* Enable the fault interrupts */ - nvkm_wr32(device, 0xb81208, 0x1); - nvkm_wr32(device, 0xb81210, 0x10); - nvkm_mask(device, 0xb83010 + foff, 0xc0000000, 0x40000000); nvkm_wr32(device, 0xb83004 + foff, upper_32_bits(buffer->addr)); nvkm_wr32(device, 0xb83000 + foff, lower_32_bits(buffer->addr)); @@ -82,9 +81,10 @@ tu102_fault_buffer_info(struct nvkm_fault_buffer *buffer) buffer->put = 0xb8300c + foff; } -static void -tu102_fault_intr_fault(struct nvkm_fault *fault) +static irqreturn_t +tu102_fault_info_fault(struct nvkm_inth *inth) { + struct nvkm_fault *fault = container_of(inth, typeof(*fault), info_fault); struct nvkm_subdev *subdev = &fault->subdev; struct nvkm_device *device = subdev->device; struct nvkm_fault_data info; @@ -106,45 +106,9 @@ tu102_fault_intr_fault(struct nvkm_fault *fault) info.reason = (info1 & 0x0000001f); nvkm_fifo_fault(device->fifo, &info); -} - -static void -tu102_fault_intr(struct nvkm_fault *fault) -{ - struct nvkm_subdev *subdev = &fault->subdev; - struct nvkm_device *device = subdev->device; - u32 stat = nvkm_rd32(device, 0xb83094); - - if (stat & 0x80000000) { - tu102_fault_intr_fault(fault); - nvkm_wr32(device, 0xb83094, 0x80000000); - stat &= ~0x80000000; - } - - if (stat & 0x00000200) { - /* Clear the associated interrupt flag */ - nvkm_wr32(device, 0xb81010, 0x10); - if (fault->buffer[0]) { - nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING); - stat &= ~0x00000200; - } - } - - /* Replayable MMU fault */ - if (stat & 0x00000100) { - /* Clear the associated interrupt flag */ - nvkm_wr32(device, 0xb81008, 0x1); - - if (fault->buffer[1]) { - nvkm_event_ntfy(&fault->event, 1, NVKM_FAULT_BUFFER_EVENT_PENDING); - stat &= ~0x00000100; - } - } - - if (stat) { - nvkm_debug(subdev, "intr %08x\n", stat); - } + nvkm_wr32(device, 0xb83094, 0x80000000); + return IRQ_HANDLED; } static void @@ -155,23 +119,48 @@ tu102_fault_fini(struct nvkm_fault *fault) if (fault->buffer[0]) fault->func->buffer.fini(fault->buffer[0]); - /*XXX: disable priv faults */ + + nvkm_inth_block(&fault->info_fault); } static void tu102_fault_init(struct nvkm_fault *fault) { - /*XXX: enable priv faults */ + nvkm_inth_allow(&fault->info_fault); + fault->func->buffer.init(fault->buffer[0]); nvkm_event_ntfy_allow(&fault->nrpfb); } +static int +tu102_fault_oneinit(struct nvkm_fault *fault) +{ + struct nvkm_device *device = fault->subdev.device; + struct nvkm_intr *intr = &device->vfn->intr; + int ret, i; + + ret = nvkm_inth_add(intr, nvkm_rd32(device, 0x100ee0) & 0x0000ffff, + NVKM_INTR_PRIO_NORMAL, &fault->subdev, tu102_fault_info_fault, + &fault->info_fault); + if (ret) + return ret; + + for (i = 0; i < fault->buffer_nr; i++) { + ret = nvkm_inth_add(intr, nvkm_rd32(device, 0x100ee4 + (i * 4)) >> 16, + NVKM_INTR_PRIO_NORMAL, &fault->subdev, + tu102_fault_buffer_notify, &fault->buffer[i]->inth); + if (ret) + return ret; + } + + return gv100_fault_oneinit(fault); +} + static const struct nvkm_fault_func tu102_fault = { - .oneinit = gv100_fault_oneinit, + .oneinit = tu102_fault_oneinit, .init = tu102_fault_init, .fini = tu102_fault_fini, - .intr = tu102_fault_intr, .buffer.nr = 2, .buffer.entry_size = 32, .buffer.info = tu102_fault_buffer_info, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c index a96084b34a78..630a9c9e7ac9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c @@ -39,11 +39,6 @@ tu102_mc_intr_update(struct tu102_mc *mc) nvkm_wr32(device, 0x000180 + (i * 0x04), ~mask); nvkm_wr32(device, 0x000160 + (i * 0x04), mask); } - - if (mask & 0x00000200) - nvkm_wr32(device, 0xb81608, 0x6); - else - nvkm_wr32(device, 0xb81610, 0x6); } static void @@ -88,14 +83,6 @@ tu102_mc_intr_stat(struct nvkm_mc *mc) struct nvkm_device *device = mc->subdev.device; u32 intr0 = nvkm_rd32(device, 0x000100); u32 intr1 = nvkm_rd32(device, 0x000104); - u32 intr_top = nvkm_rd32(device, 0xb81600); - - /* Turing and above route the MMU fault interrupts via a different - * interrupt tree with different control registers. For the moment remap - * them back to the old PMC vector. - */ - if (intr_top & 0x00000006) - intr0 |= 0x00000200; return intr0 | intr1; } -- cgit v1.2.3 From e5f92c8735b6ff415aafdd0af85232f2592174c3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:54 +1000 Subject: drm/nouveau/fault/ga100: initial support TU102 implementation should be OK for Ampere now. v2. fixup for ga103 early merge Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 88b92306dd49..a36c46aff242 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2577,6 +2577,7 @@ nv170_chipset = { .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, + .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga100_fb_new }, .gpio = { 0x00000001, gk104_gpio_new }, .i2c = { 0x00000001, gm200_i2c_new }, @@ -2596,6 +2597,7 @@ nv172_chipset = { .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, + .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, .i2c = { 0x00000001, gm200_i2c_new }, @@ -2618,6 +2620,7 @@ nv173_chipset = { .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, + .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, .i2c = { 0x00000001, gm200_i2c_new }, @@ -2640,6 +2643,7 @@ nv174_chipset = { .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, + .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, .i2c = { 0x00000001, gm200_i2c_new }, @@ -2662,6 +2666,7 @@ nv176_chipset = { .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, + .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, .i2c = { 0x00000001, gm200_i2c_new }, @@ -2684,6 +2689,7 @@ nv177_chipset = { .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, + .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, .i2c = { 0x00000001, gm200_i2c_new }, -- cgit v1.2.3 From fe76fe497c30080ce8962ea62c5c13c6814e1a83 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:55 +1000 Subject: drm/nouveau/mc: implement intr handling on top of nvkm_intr - new-style handlers can now be used here too - decent clean-up Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h | 6 +- drivers/gpu/drm/nouveau/nvkm/core/intr.c | 10 +- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 10 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild | 1 - drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c | 113 ++++---------------- drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c | 34 +++--- drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c | 34 +++--- drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c | 28 +---- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c | 81 ++++---------- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c | 36 +++---- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c | 8 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c | 124 +++++++++------------- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c | 10 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c | 62 +++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c | 64 +++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c | 20 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c | 22 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c | 6 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c | 28 +++-- drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h | 42 +++----- drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c | 123 --------------------- 21 files changed, 285 insertions(+), 577 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h index cb86a56e68d4..127ac545e4b2 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h @@ -6,15 +6,14 @@ struct nvkm_mc { const struct nvkm_mc_func *func; struct nvkm_subdev subdev; + + struct nvkm_intr intr; }; void nvkm_mc_enable(struct nvkm_device *, enum nvkm_subdev_type, int); void nvkm_mc_disable(struct nvkm_device *, enum nvkm_subdev_type, int); bool nvkm_mc_enabled(struct nvkm_device *, enum nvkm_subdev_type, int); void nvkm_mc_reset(struct nvkm_device *, enum nvkm_subdev_type, int); -void nvkm_mc_intr(struct nvkm_device *, bool *handled); -void nvkm_mc_intr_unarm(struct nvkm_device *); -void nvkm_mc_intr_rearm(struct nvkm_device *); void nvkm_mc_intr_mask(struct nvkm_device *, enum nvkm_subdev_type, int, bool enable); void nvkm_mc_unk260(struct nvkm_device *, u32 data); @@ -31,6 +30,5 @@ int gk104_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n int gk20a_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **); int gp100_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **); int gp10b_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **); -int tu102_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **); int ga100_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/core/intr.c b/drivers/gpu/drm/nouveau/nvkm/core/intr.c index 3f3fe3d416e2..e20b7ca218c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/intr.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/intr.c @@ -25,8 +25,6 @@ #include #include -#include - static int nvkm_intr_xlat(struct nvkm_subdev *subdev, struct nvkm_intr *intr, enum nvkm_intr_type type, int *leaf, u32 *mask) @@ -151,7 +149,6 @@ nvkm_intr_rearm_locked(struct nvkm_device *device) list_for_each_entry(intr, &device->intr.intr, head) intr->func->rearm(intr); - nvkm_mc_intr_rearm(device); } static void @@ -161,7 +158,6 @@ nvkm_intr_unarm_locked(struct nvkm_device *device) list_for_each_entry(intr, &device->intr.intr, head) intr->func->unarm(intr); - nvkm_mc_intr_unarm(device); } static irqreturn_t @@ -171,7 +167,7 @@ nvkm_intr(int irq, void *arg) struct nvkm_intr *intr; struct nvkm_inth *inth; irqreturn_t ret = IRQ_NONE; - bool pending = false, handled; + bool pending = false; int prio, leaf; /* Disable all top-level interrupt sources, and re-arm MSI interrupts. */ @@ -188,10 +184,6 @@ nvkm_intr(int irq, void *arg) pending = true; } - nvkm_mc_intr(device, &handled); - if (handled) - ret = IRQ_HANDLED; - if (!pending) goto done; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index a36c46aff242..587aebcda78c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2412,7 +2412,7 @@ nv162_chipset = { .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .ltc = { 0x00000001, gp102_ltc_new }, - .mc = { 0x00000001, tu102_mc_new }, + .mc = { 0x00000001, gp100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, .pmu = { 0x00000001, gp102_pmu_new }, @@ -2447,7 +2447,7 @@ nv164_chipset = { .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .ltc = { 0x00000001, gp102_ltc_new }, - .mc = { 0x00000001, tu102_mc_new }, + .mc = { 0x00000001, gp100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, .pmu = { 0x00000001, gp102_pmu_new }, @@ -2482,7 +2482,7 @@ nv166_chipset = { .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .ltc = { 0x00000001, gp102_ltc_new }, - .mc = { 0x00000001, tu102_mc_new }, + .mc = { 0x00000001, gp100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, .pmu = { 0x00000001, gp102_pmu_new }, @@ -2517,7 +2517,7 @@ nv167_chipset = { .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .ltc = { 0x00000001, gp102_ltc_new }, - .mc = { 0x00000001, tu102_mc_new }, + .mc = { 0x00000001, gp100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, .pmu = { 0x00000001, gp102_pmu_new }, @@ -2552,7 +2552,7 @@ nv168_chipset = { .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .ltc = { 0x00000001, gp102_ltc_new }, - .mc = { 0x00000001, tu102_mc_new }, + .mc = { 0x00000001, gp100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, .pmu = { 0x00000001, gp102_pmu_new }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild index ac2b34e9ac6a..2a3255ced8b7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild @@ -13,5 +13,4 @@ nvkm-y += nvkm/subdev/mc/gk104.o nvkm-y += nvkm/subdev/mc/gk20a.o nvkm-y += nvkm/subdev/mc/gp100.o nvkm-y += nvkm/subdev/mc/gp10b.o -nvkm-y += nvkm/subdev/mc/tu102.o nvkm-y += nvkm/subdev/mc/ga100.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c index 21c4af3f81d5..322237e2ff80 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c @@ -37,84 +37,14 @@ nvkm_mc_unk260(struct nvkm_device *device, u32 data) void nvkm_mc_intr_mask(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, bool en) { - struct nvkm_mc *mc = device->mc; - const struct nvkm_mc_map *map; - if (likely(mc) && mc->func->intr_mask) { - u32 mask = nvkm_top_intr_mask(device, type, inst); - for (map = mc->func->intr; !mask && map->stat; map++) { - if (map->type == type && map->inst == inst) - mask = map->stat; - } - mc->func->intr_mask(mc, mask, en ? mask : 0); - } -} - -void -nvkm_mc_intr_unarm(struct nvkm_device *device) -{ - struct nvkm_mc *mc = device->mc; - if (likely(mc)) - mc->func->intr_unarm(mc); -} - -void -nvkm_mc_intr_rearm(struct nvkm_device *device) -{ - struct nvkm_mc *mc = device->mc; - if (likely(mc)) - mc->func->intr_rearm(mc); -} - -static u32 -nvkm_mc_intr_stat(struct nvkm_mc *mc) -{ - u32 intr = mc->func->intr_stat(mc); - if (WARN_ON_ONCE(intr == 0xffffffff)) - intr = 0; /* likely fallen off the bus */ - return intr; -} - -void -nvkm_mc_intr(struct nvkm_device *device, bool *handled) -{ - struct nvkm_mc *mc = device->mc; - struct nvkm_top *top = device->top; - struct nvkm_top_device *tdev; - struct nvkm_subdev *subdev; - const struct nvkm_mc_map *map; - u32 stat, intr; - - if (unlikely(!mc)) - return; - - stat = intr = nvkm_mc_intr_stat(mc); + struct nvkm_subdev *subdev = nvkm_device_subdev(device, type, inst); - if (top) { - list_for_each_entry(tdev, &top->device, head) { - if (tdev->intr >= 0 && (stat & BIT(tdev->intr))) { - subdev = nvkm_device_subdev(device, tdev->type, tdev->inst); - if (subdev) { - nvkm_subdev_intr(subdev); - stat &= ~BIT(tdev->intr); - if (!stat) - break; - } - } - } - } - - for (map = mc->func->intr; map->stat; map++) { - if (intr & map->stat) { - subdev = nvkm_device_subdev(device, map->type, map->inst); - if (subdev) - nvkm_subdev_intr(subdev); - stat &= ~map->stat; - } + if (subdev) { + if (en) + nvkm_intr_allow(subdev, NVKM_INTR_SUBDEV); + else + nvkm_intr_block(subdev, NVKM_INTR_SUBDEV); } - - if (stat) - nvkm_error(&mc->subdev, "intr %08x\n", stat); - *handled = intr != 0; } static u32 @@ -177,20 +107,12 @@ nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_subdev_type type, int inst } -static int -nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend) -{ - nvkm_mc_intr_unarm(subdev->device); - return 0; -} - static int nvkm_mc_init(struct nvkm_subdev *subdev) { struct nvkm_mc *mc = nvkm_mc(subdev); if (mc->func->init) mc->func->init(mc); - nvkm_mc_intr_rearm(subdev->device); return 0; } @@ -204,24 +126,27 @@ static const struct nvkm_subdev_func nvkm_mc = { .dtor = nvkm_mc_dtor, .init = nvkm_mc_init, - .fini = nvkm_mc_fini, }; -void -nvkm_mc_ctor(const struct nvkm_mc_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_mc *mc) -{ - nvkm_subdev_ctor(&nvkm_mc, device, type, inst, &mc->subdev); - mc->func = func; -} - int nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc) { struct nvkm_mc *mc; + int ret; + if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL))) return -ENOMEM; - nvkm_mc_ctor(func, device, type, inst, *pmc); + + nvkm_subdev_ctor(&nvkm_mc, device, type, inst, &mc->subdev); + mc->func = func; + + if (mc->func->intr) { + ret = nvkm_intr_add(mc->func->intr, mc->func->intrs, &mc->subdev, + mc->func->intr_nonstall ? 2 : 1, &mc->intr); + if (ret) + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c index 4cfc1c984006..8a8267ecfe1d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c @@ -34,30 +34,28 @@ g84_mc_reset[] = { {} }; -static const struct nvkm_mc_map -g84_mc_intr[] = { - { 0x04000000, NVKM_ENGINE_DISP }, - { 0x00020000, NVKM_ENGINE_VP }, - { 0x00008000, NVKM_ENGINE_BSP }, - { 0x00004000, NVKM_ENGINE_CIPHER }, - { 0x00001000, NVKM_ENGINE_GR }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x00000001, NVKM_ENGINE_MPEG }, - { 0x0002d101, NVKM_SUBDEV_FB }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x00200000, NVKM_SUBDEV_GPIO }, - { 0x00200000, NVKM_SUBDEV_I2C }, - { 0x00100000, NVKM_SUBDEV_TIMER }, +static const struct nvkm_intr_data +g84_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, + { NVKM_ENGINE_VP , 0, 0, 0x00020000, true }, + { NVKM_ENGINE_BSP , 0, 0, 0x00008000, true }, + { NVKM_ENGINE_CIPHER, 0, 0, 0x00004000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true }, + { NVKM_SUBDEV_FB , 0, 0, 0x0002d101, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, {}, }; static const struct nvkm_mc_func g84_mc = { .init = nv50_mc_init, - .intr = g84_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_stat = nv04_mc_intr_stat, + .intr = &nv04_mc_intr, + .intrs = g84_mc_intrs, .reset = g84_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c index b7e58d75d894..e099d419f1ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c @@ -34,30 +34,28 @@ g98_mc_reset[] = { {} }; -static const struct nvkm_mc_map -g98_mc_intr[] = { - { 0x04000000, NVKM_ENGINE_DISP }, - { 0x00020000, NVKM_ENGINE_MSPDEC }, - { 0x00008000, NVKM_ENGINE_MSVLD }, - { 0x00004000, NVKM_ENGINE_SEC }, - { 0x00001000, NVKM_ENGINE_GR }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x00000001, NVKM_ENGINE_MSPPP }, - { 0x0002d101, NVKM_SUBDEV_FB }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x00200000, NVKM_SUBDEV_GPIO }, - { 0x00200000, NVKM_SUBDEV_I2C }, - { 0x00100000, NVKM_SUBDEV_TIMER }, +static const struct nvkm_intr_data +g98_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, + { NVKM_ENGINE_MSPDEC, 0, 0, 0x00020000, true }, + { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true }, + { NVKM_ENGINE_SEC , 0, 0, 0x00004000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true }, + { NVKM_SUBDEV_FB , 0, 0, 0x0002d101, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, {}, }; static const struct nvkm_mc_func g98_mc = { .init = nv50_mc_init, - .intr = g98_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_stat = nv04_mc_intr_stat, + .intr = &nv04_mc_intr, + .intrs = g98_mc_intrs, .reset = g98_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c index ec3eedfa541a..98ccce9585eb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c @@ -21,35 +21,9 @@ */ #include "priv.h" -static void -ga100_mc_intr_unarm(struct nvkm_mc *mc) -{ -} - -static void -ga100_mc_intr_rearm(struct nvkm_mc *mc) -{ -} - -static u32 -ga100_mc_intr_stat(struct nvkm_mc *mc) -{ - return 0; -} - -static void -ga100_mc_init(struct nvkm_mc *mc) -{ - nv50_mc_init(mc); -} - static const struct nvkm_mc_func ga100_mc = { - .init = ga100_mc_init, - .intr = gp100_mc_intr, - .intr_unarm = ga100_mc_intr_unarm, - .intr_rearm = ga100_mc_intr_rearm, - .intr_stat = ga100_mc_intr_stat, + .init = nv50_mc_init, .reset = gk104_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c index 3a589c6f7fad..b2846eaea34c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c @@ -36,63 +36,28 @@ gf100_mc_reset[] = { {} }; -static const struct nvkm_mc_map -gf100_mc_intr[] = { - { 0x04000000, NVKM_ENGINE_DISP }, - { 0x00020000, NVKM_ENGINE_MSPDEC }, - { 0x00008000, NVKM_ENGINE_MSVLD }, - { 0x00001000, NVKM_ENGINE_GR }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x00000040, NVKM_ENGINE_CE, 1 }, - { 0x00000020, NVKM_ENGINE_CE, 0 }, - { 0x00000001, NVKM_ENGINE_MSPPP }, - { 0x40000000, NVKM_SUBDEV_PRIVRING }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x08000000, NVKM_SUBDEV_FB }, - { 0x02000000, NVKM_SUBDEV_LTC }, - { 0x01000000, NVKM_SUBDEV_PMU }, - { 0x00200000, NVKM_SUBDEV_GPIO }, - { 0x00200000, NVKM_SUBDEV_I2C }, - { 0x00100000, NVKM_SUBDEV_TIMER }, - { 0x00040000, NVKM_SUBDEV_THERM }, - { 0x00002000, NVKM_SUBDEV_FB }, +static const struct nvkm_intr_data +gf100_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, + { NVKM_ENGINE_MSPDEC , 0, 0, 0x00020000, true }, + { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_CE , 1, 0, 0x00000040, true }, + { NVKM_ENGINE_CE , 0, 0, 0x00000020, true }, + { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true }, + { NVKM_SUBDEV_PRIVRING, 0, 0, 0x40000000, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_FB , 0, 0, 0x08002000, true }, + { NVKM_SUBDEV_LTC , 0, 0, 0x02000000, true }, + { NVKM_SUBDEV_PMU , 0, 0, 0x01000000, true }, + { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, + { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true }, {}, }; -void -gf100_mc_intr_unarm(struct nvkm_mc *mc) -{ - struct nvkm_device *device = mc->subdev.device; - nvkm_wr32(device, 0x000140, 0x00000000); - nvkm_wr32(device, 0x000144, 0x00000000); - nvkm_rd32(device, 0x000140); -} - -void -gf100_mc_intr_rearm(struct nvkm_mc *mc) -{ - struct nvkm_device *device = mc->subdev.device; - nvkm_wr32(device, 0x000140, 0x00000001); - nvkm_wr32(device, 0x000144, 0x00000001); -} - -u32 -gf100_mc_intr_stat(struct nvkm_mc *mc) -{ - struct nvkm_device *device = mc->subdev.device; - u32 intr0 = nvkm_rd32(device, 0x000100); - u32 intr1 = nvkm_rd32(device, 0x000104); - return intr0 | intr1; -} - -void -gf100_mc_intr_mask(struct nvkm_mc *mc, u32 mask, u32 stat) -{ - struct nvkm_device *device = mc->subdev.device; - nvkm_mask(device, 0x000640, mask, stat); - nvkm_mask(device, 0x000644, mask, stat); -} - void gf100_mc_unk260(struct nvkm_mc *mc, u32 data) { @@ -102,11 +67,9 @@ gf100_mc_unk260(struct nvkm_mc *mc, u32 data) static const struct nvkm_mc_func gf100_mc = { .init = nv50_mc_init, - .intr = gf100_mc_intr, - .intr_unarm = gf100_mc_intr_unarm, - .intr_rearm = gf100_mc_intr_rearm, - .intr_mask = gf100_mc_intr_mask, - .intr_stat = gf100_mc_intr_stat, + .intr = >215_mc_intr, + .intrs = gf100_mc_intrs, + .intr_nonstall = true, .reset = gf100_mc_reset, .unk260 = gf100_mc_unk260, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c index d9b9067fa93f..edf82e4568bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c @@ -30,31 +30,29 @@ gk104_mc_reset[] = { {} }; -const struct nvkm_mc_map -gk104_mc_intr[] = { - { 0x04000000, NVKM_ENGINE_DISP }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x40000000, NVKM_SUBDEV_PRIVRING }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x08000000, NVKM_SUBDEV_FB }, - { 0x02000000, NVKM_SUBDEV_LTC }, - { 0x01000000, NVKM_SUBDEV_PMU }, - { 0x00200000, NVKM_SUBDEV_GPIO }, - { 0x00200000, NVKM_SUBDEV_I2C }, - { 0x00100000, NVKM_SUBDEV_TIMER }, - { 0x00040000, NVKM_SUBDEV_THERM }, - { 0x00002000, NVKM_SUBDEV_FB }, +const struct nvkm_intr_data +gk104_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_SUBDEV_PRIVRING, 0, 0, 0x40000000, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_FB , 0, 0, 0x08002000, true }, + { NVKM_SUBDEV_LTC , 0, 0, 0x02000000, true }, + { NVKM_SUBDEV_PMU , 0, 0, 0x01000000, true }, + { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, + { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true }, + { NVKM_SUBDEV_TOP , 0, 0, 0xffffffff, true }, {}, }; static const struct nvkm_mc_func gk104_mc = { .init = nv50_mc_init, - .intr = gk104_mc_intr, - .intr_unarm = gf100_mc_intr_unarm, - .intr_rearm = gf100_mc_intr_rearm, - .intr_mask = gf100_mc_intr_mask, - .intr_stat = gf100_mc_intr_stat, + .intr = >215_mc_intr, + .intrs = gk104_mc_intrs, + .intr_nonstall = true, .reset = gk104_mc_reset, .unk260 = gf100_mc_unk260, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c index 03590292749a..931985343ab5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c @@ -26,11 +26,9 @@ static const struct nvkm_mc_func gk20a_mc = { .init = nv50_mc_init, - .intr = gk104_mc_intr, - .intr_unarm = gf100_mc_intr_unarm, - .intr_rearm = gf100_mc_intr_rearm, - .intr_mask = gf100_mc_intr_mask, - .intr_stat = gf100_mc_intr_stat, + .intr = >215_mc_intr, + .intrs = gk104_mc_intrs, + .intr_nonstall = true, .reset = gk104_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c index 5fd1a0595c33..5dfdf75af255 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c @@ -21,108 +21,80 @@ * * Authors: Ben Skeggs */ -#define gp100_mc(p) container_of((p), struct gp100_mc, base) #include "priv.h" -struct gp100_mc { - struct nvkm_mc base; - spinlock_t lock; - bool intr; - u32 mask; +const struct nvkm_intr_data +gp100_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_SUBDEV_FAULT , 0, 0, 0x00000200, true }, + { NVKM_SUBDEV_PRIVRING, 0, 0, 0x40000000, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_FB , 0, 0, 0x08002000, true }, + { NVKM_SUBDEV_LTC , 0, 0, 0x02000000, true }, + { NVKM_SUBDEV_PMU , 0, 0, 0x01000000, true }, + { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, + { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true }, + { NVKM_SUBDEV_TOP , 0, 0, 0xffffffff, true }, + {}, }; static void -gp100_mc_intr_update(struct gp100_mc *mc) +gp100_mc_intr_allow(struct nvkm_intr *intr, int leaf, u32 mask) { - struct nvkm_device *device = mc->base.subdev.device; - u32 mask = mc->intr ? mc->mask : 0, i; - for (i = 0; i < 2; i++) { - nvkm_wr32(device, 0x000180 + (i * 0x04), ~mask); - nvkm_wr32(device, 0x000160 + (i * 0x04), mask); - } + struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr); + + nvkm_wr32(mc->subdev.device, 0x000160 + (leaf * 4), mask); } -void -gp100_mc_intr_unarm(struct nvkm_mc *base) +static void +gp100_mc_intr_block(struct nvkm_intr *intr, int leaf, u32 mask) { - struct gp100_mc *mc = gp100_mc(base); - unsigned long flags; - spin_lock_irqsave(&mc->lock, flags); - mc->intr = false; - gp100_mc_intr_update(mc); - spin_unlock_irqrestore(&mc->lock, flags); + struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr); + + nvkm_wr32(mc->subdev.device, 0x000180 + (leaf * 4), mask); } -void -gp100_mc_intr_rearm(struct nvkm_mc *base) +static void +gp100_mc_intr_rearm(struct nvkm_intr *intr) { - struct gp100_mc *mc = gp100_mc(base); - unsigned long flags; - spin_lock_irqsave(&mc->lock, flags); - mc->intr = true; - gp100_mc_intr_update(mc); - spin_unlock_irqrestore(&mc->lock, flags); + int i; + + for (i = 0; i < intr->leaves; i++) + intr->func->allow(intr, i, intr->mask[i]); } -void -gp100_mc_intr_mask(struct nvkm_mc *base, u32 mask, u32 intr) +static void +gp100_mc_intr_unarm(struct nvkm_intr *intr) { - struct gp100_mc *mc = gp100_mc(base); - unsigned long flags; - spin_lock_irqsave(&mc->lock, flags); - mc->mask = (mc->mask & ~mask) | intr; - gp100_mc_intr_update(mc); - spin_unlock_irqrestore(&mc->lock, flags); + int i; + + for (i = 0; i < intr->leaves; i++) + intr->func->block(intr, i, 0xffffffff); } -const struct nvkm_mc_map -gp100_mc_intr[] = { - { 0x04000000, NVKM_ENGINE_DISP }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x00000200, NVKM_SUBDEV_FAULT }, - { 0x40000000, NVKM_SUBDEV_PRIVRING }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x08000000, NVKM_SUBDEV_FB }, - { 0x02000000, NVKM_SUBDEV_LTC }, - { 0x01000000, NVKM_SUBDEV_PMU }, - { 0x00200000, NVKM_SUBDEV_GPIO }, - { 0x00200000, NVKM_SUBDEV_I2C }, - { 0x00100000, NVKM_SUBDEV_TIMER }, - { 0x00040000, NVKM_SUBDEV_THERM }, - { 0x00002000, NVKM_SUBDEV_FB }, - {}, +const struct nvkm_intr_func +gp100_mc_intr = { + .pending = nv04_mc_intr_pending, + .unarm = gp100_mc_intr_unarm, + .rearm = gp100_mc_intr_rearm, + .block = gp100_mc_intr_block, + .allow = gp100_mc_intr_allow, }; static const struct nvkm_mc_func gp100_mc = { .init = nv50_mc_init, - .intr = gp100_mc_intr, - .intr_unarm = gp100_mc_intr_unarm, - .intr_rearm = gp100_mc_intr_rearm, - .intr_mask = gp100_mc_intr_mask, - .intr_stat = gf100_mc_intr_stat, + .intr = &gp100_mc_intr, + .intrs = gp100_mc_intrs, + .intr_nonstall = true, .reset = gk104_mc_reset, }; -int -gp100_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc) -{ - struct gp100_mc *mc; - - if (!(mc = kzalloc(sizeof(*mc), GFP_KERNEL))) - return -ENOMEM; - nvkm_mc_ctor(func, device, type, inst, &mc->base); - *pmc = &mc->base; - - spin_lock_init(&mc->lock); - mc->intr = false; - mc->mask = 0x7fffffff; - return 0; -} - int gp100_mc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc) { - return gp100_mc_new_(&gp100_mc, device, type, inst, pmc); + return nvkm_mc_new_(&gp100_mc, device, type, inst, pmc); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c index dd581d030ced..6b83c6bf308c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c @@ -34,16 +34,14 @@ gp10b_mc_init(struct nvkm_mc *mc) static const struct nvkm_mc_func gp10b_mc = { .init = gp10b_mc_init, - .intr = gp100_mc_intr, - .intr_unarm = gp100_mc_intr_unarm, - .intr_rearm = gp100_mc_intr_rearm, - .intr_mask = gp100_mc_intr_mask, - .intr_stat = gf100_mc_intr_stat, + .intr = &gp100_mc_intr, + .intrs = gp100_mc_intrs, + .intr_nonstall = true, .reset = gk104_mc_reset, }; int gp10b_mc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc) { - return gp100_mc_new_(&gp10b_mc, device, type, inst, pmc); + return nvkm_mc_new_(&gp10b_mc, device, type, inst, pmc); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c index 1b4d43531dba..330ef92f5e50 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c @@ -34,39 +34,55 @@ gt215_mc_reset[] = { {} }; -static const struct nvkm_mc_map -gt215_mc_intr[] = { - { 0x04000000, NVKM_ENGINE_DISP }, - { 0x00400000, NVKM_ENGINE_CE, 0 }, - { 0x00020000, NVKM_ENGINE_MSPDEC }, - { 0x00008000, NVKM_ENGINE_MSVLD }, - { 0x00001000, NVKM_ENGINE_GR }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x00000001, NVKM_ENGINE_MSPPP }, - { 0x00429101, NVKM_SUBDEV_FB }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x00200000, NVKM_SUBDEV_GPIO }, - { 0x00200000, NVKM_SUBDEV_I2C }, - { 0x00100000, NVKM_SUBDEV_TIMER }, - { 0x00080000, NVKM_SUBDEV_THERM }, - { 0x00040000, NVKM_SUBDEV_PMU }, +static const struct nvkm_intr_data +gt215_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, + { NVKM_ENGINE_CE , 0, 0, 0x00400000, true }, + { NVKM_ENGINE_MSPDEC, 0, 0, 0x00020000, true }, + { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true }, + { NVKM_SUBDEV_FB , 0, 0, 0x00429101, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, + { NVKM_SUBDEV_THERM , 0, 0, 0x00080000, true }, + { NVKM_SUBDEV_PMU , 0, 0, 0x00040000, true }, {}, }; static void -gt215_mc_intr_mask(struct nvkm_mc *mc, u32 mask, u32 stat) +gt215_mc_intr_allow(struct nvkm_intr *intr, int leaf, u32 mask) +{ + struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr); + + nvkm_mask(mc->subdev.device, 0x000640 + (leaf * 4), mask, mask); +} + +static void +gt215_mc_intr_block(struct nvkm_intr *intr, int leaf, u32 mask) { - nvkm_mask(mc->subdev.device, 0x000640, mask, stat); + struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr); + + nvkm_mask(mc->subdev.device, 0x000640 + (leaf * 4), mask, 0); } +const struct nvkm_intr_func +gt215_mc_intr = { + .pending = nv04_mc_intr_pending, + .unarm = nv04_mc_intr_unarm, + .rearm = nv04_mc_intr_rearm, + .block = gt215_mc_intr_block, + .allow = gt215_mc_intr_allow, +}; + static const struct nvkm_mc_func gt215_mc = { .init = nv50_mc_init, - .intr = gt215_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_mask = gt215_mc_intr_mask, - .intr_stat = nv04_mc_intr_stat, + .intr = &nv04_mc_intr, + .intrs = gt215_mc_intrs, .reset = gt215_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c index bc0d09bafa99..00adf6833d26 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c @@ -30,37 +30,61 @@ nv04_mc_reset[] = { {} }; -static const struct nvkm_mc_map -nv04_mc_intr[] = { - { 0x01010000, NVKM_ENGINE_DISP }, - { 0x00001000, NVKM_ENGINE_GR }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x00100000, NVKM_SUBDEV_TIMER }, +static const struct nvkm_intr_data +nv04_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x01010000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true }, {} }; void -nv04_mc_intr_unarm(struct nvkm_mc *mc) +nv04_mc_intr_rearm(struct nvkm_intr *intr) { - struct nvkm_device *device = mc->subdev.device; - nvkm_wr32(device, 0x000140, 0x00000000); - nvkm_rd32(device, 0x000140); + struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr); + int leaf; + + for (leaf = 0; leaf < intr->leaves; leaf++) + nvkm_wr32(mc->subdev.device, 0x000140 + (leaf * 4), 0x00000001); } void -nv04_mc_intr_rearm(struct nvkm_mc *mc) +nv04_mc_intr_unarm(struct nvkm_intr *intr) { - struct nvkm_device *device = mc->subdev.device; - nvkm_wr32(device, 0x000140, 0x00000001); + struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr); + int leaf; + + for (leaf = 0; leaf < intr->leaves; leaf++) + nvkm_wr32(mc->subdev.device, 0x000140 + (leaf * 4), 0x00000000); + + nvkm_rd32(mc->subdev.device, 0x000140); } -u32 -nv04_mc_intr_stat(struct nvkm_mc *mc) +bool +nv04_mc_intr_pending(struct nvkm_intr *intr) { - return nvkm_rd32(mc->subdev.device, 0x000100); + struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr); + bool pending = false; + int leaf; + + for (leaf = 0; leaf < intr->leaves; leaf++) { + intr->stat[leaf] = nvkm_rd32(mc->subdev.device, 0x000100 + (leaf * 4)); + if (intr->stat[leaf]) + pending = true; + } + + return pending; } +const struct nvkm_intr_func +nv04_mc_intr = { + .pending = nv04_mc_intr_pending, + .unarm = nv04_mc_intr_unarm, + .rearm = nv04_mc_intr_rearm, +}; + void nv04_mc_init(struct nvkm_mc *mc) { @@ -72,10 +96,8 @@ nv04_mc_init(struct nvkm_mc *mc) static const struct nvkm_mc_func nv04_mc = { .init = nv04_mc_init, - .intr = nv04_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_stat = nv04_mc_intr_stat, + .intr = &nv04_mc_intr, + .intrs = nv04_mc_intrs, .reset = nv04_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c index ab59ca1ee068..1cef78827f57 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c @@ -23,23 +23,21 @@ */ #include "priv.h" -static const struct nvkm_mc_map -nv11_mc_intr[] = { - { 0x03010000, NVKM_ENGINE_DISP }, - { 0x00001000, NVKM_ENGINE_GR }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x00100000, NVKM_SUBDEV_TIMER }, +static const struct nvkm_intr_data +nv11_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x03010000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true }, {} }; static const struct nvkm_mc_func nv11_mc = { .init = nv04_mc_init, - .intr = nv11_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_stat = nv04_mc_intr_stat, + .intr = &nv04_mc_intr, + .intrs = nv11_mc_intrs, .reset = nv04_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c index 03d756e26e57..ac70c359bce0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c @@ -31,24 +31,22 @@ nv17_mc_reset[] = { {} }; -const struct nvkm_mc_map -nv17_mc_intr[] = { - { 0x03010000, NVKM_ENGINE_DISP }, - { 0x00001000, NVKM_ENGINE_GR }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x00000001, NVKM_ENGINE_MPEG }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x00100000, NVKM_SUBDEV_TIMER }, +const struct nvkm_intr_data +nv17_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x03010000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true }, {} }; static const struct nvkm_mc_func nv17_mc = { .init = nv04_mc_init, - .intr = nv17_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_stat = nv04_mc_intr_stat, + .intr = &nv04_mc_intr, + .intrs = nv17_mc_intrs, .reset = nv17_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c index 95f65766e8b0..0a054459a949 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c @@ -40,10 +40,8 @@ nv44_mc_init(struct nvkm_mc *mc) static const struct nvkm_mc_func nv44_mc = { .init = nv44_mc_init, - .intr = nv17_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_stat = nv04_mc_intr_stat, + .intr = &nv04_mc_intr, + .intrs = nv17_mc_intrs, .reset = nv17_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c index fce3613cdfa5..6a02ed754c3f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c @@ -23,17 +23,17 @@ */ #include "priv.h" -static const struct nvkm_mc_map -nv50_mc_intr[] = { - { 0x04000000, NVKM_ENGINE_DISP }, - { 0x00001000, NVKM_ENGINE_GR }, - { 0x00000100, NVKM_ENGINE_FIFO }, - { 0x00000001, NVKM_ENGINE_MPEG }, - { 0x00001101, NVKM_SUBDEV_FB }, - { 0x10000000, NVKM_SUBDEV_BUS }, - { 0x00200000, NVKM_SUBDEV_GPIO }, - { 0x00200000, NVKM_SUBDEV_I2C }, - { 0x00100000, NVKM_SUBDEV_TIMER }, +static const struct nvkm_intr_data +nv50_mc_intrs[] = { + { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true }, + { NVKM_SUBDEV_FB , 0, 0, 0x00001101, true }, + { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, + { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, + { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true }, {}, }; @@ -47,10 +47,8 @@ nv50_mc_init(struct nvkm_mc *mc) static const struct nvkm_mc_func nv50_mc = { .init = nv50_mc_init, - .intr = nv50_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_stat = nv04_mc_intr_stat, + .intr = &nv04_mc_intr, + .intrs = nv50_mc_intrs, .reset = nv17_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h index c8bcabb98f99..3ecfe9b4fb05 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h @@ -4,8 +4,6 @@ #define nvkm_mc(p) container_of((p), struct nvkm_mc, subdev) #include -void nvkm_mc_ctor(const struct nvkm_mc_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_mc *); int nvkm_mc_new_(const struct nvkm_mc_func *, struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_mc **); @@ -18,46 +16,36 @@ struct nvkm_mc_map { struct nvkm_mc_func { void (*init)(struct nvkm_mc *); - const struct nvkm_mc_map *intr; - /* disable reporting of interrupts to host */ - void (*intr_unarm)(struct nvkm_mc *); - /* enable reporting of interrupts to host */ - void (*intr_rearm)(struct nvkm_mc *); - /* (un)mask delivery of specific interrupts */ - void (*intr_mask)(struct nvkm_mc *, u32 mask, u32 stat); - /* retrieve pending interrupt mask (NV_PMC_INTR) */ - u32 (*intr_stat)(struct nvkm_mc *); + + const struct nvkm_intr_func *intr; + const struct nvkm_intr_data *intrs; + bool intr_nonstall; + const struct nvkm_mc_map *reset; void (*unk260)(struct nvkm_mc *, u32); }; void nv04_mc_init(struct nvkm_mc *); -void nv04_mc_intr_unarm(struct nvkm_mc *); -void nv04_mc_intr_rearm(struct nvkm_mc *); -u32 nv04_mc_intr_stat(struct nvkm_mc *); +extern const struct nvkm_intr_func nv04_mc_intr; +bool nv04_mc_intr_pending(struct nvkm_intr *); +void nv04_mc_intr_unarm(struct nvkm_intr *); +void nv04_mc_intr_rearm(struct nvkm_intr *); extern const struct nvkm_mc_map nv04_mc_reset[]; -extern const struct nvkm_mc_map nv17_mc_intr[]; +extern const struct nvkm_intr_data nv17_mc_intrs[]; extern const struct nvkm_mc_map nv17_mc_reset[]; void nv44_mc_init(struct nvkm_mc *); void nv50_mc_init(struct nvkm_mc *); -void gk104_mc_init(struct nvkm_mc *); -void gf100_mc_intr_unarm(struct nvkm_mc *); -void gf100_mc_intr_rearm(struct nvkm_mc *); -void gf100_mc_intr_mask(struct nvkm_mc *, u32, u32); -u32 gf100_mc_intr_stat(struct nvkm_mc *); +extern const struct nvkm_intr_func gt215_mc_intr; void gf100_mc_unk260(struct nvkm_mc *, u32); -void gp100_mc_intr_unarm(struct nvkm_mc *); -void gp100_mc_intr_rearm(struct nvkm_mc *); -void gp100_mc_intr_mask(struct nvkm_mc *, u32, u32); -int gp100_mc_new_(const struct nvkm_mc_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_mc **); -extern const struct nvkm_mc_map gk104_mc_intr[]; +void gk104_mc_init(struct nvkm_mc *); +extern const struct nvkm_intr_data gk104_mc_intrs[]; extern const struct nvkm_mc_map gk104_mc_reset[]; -extern const struct nvkm_mc_map gp100_mc_intr[]; +extern const struct nvkm_intr_func gp100_mc_intr; +extern const struct nvkm_intr_data gp100_mc_intrs[]; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c deleted file mode 100644 index 630a9c9e7ac9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#define tu102_mc(p) container_of((p), struct tu102_mc, base) -#include "priv.h" - -struct tu102_mc { - struct nvkm_mc base; - spinlock_t lock; - bool intr; - u32 mask; -}; - -static void -tu102_mc_intr_update(struct tu102_mc *mc) -{ - struct nvkm_device *device = mc->base.subdev.device; - u32 mask = mc->intr ? mc->mask : 0, i; - - for (i = 0; i < 2; i++) { - nvkm_wr32(device, 0x000180 + (i * 0x04), ~mask); - nvkm_wr32(device, 0x000160 + (i * 0x04), mask); - } -} - -static void -tu102_mc_intr_unarm(struct nvkm_mc *base) -{ - struct tu102_mc *mc = tu102_mc(base); - unsigned long flags; - - spin_lock_irqsave(&mc->lock, flags); - mc->intr = false; - tu102_mc_intr_update(mc); - spin_unlock_irqrestore(&mc->lock, flags); -} - -static void -tu102_mc_intr_rearm(struct nvkm_mc *base) -{ - struct tu102_mc *mc = tu102_mc(base); - unsigned long flags; - - spin_lock_irqsave(&mc->lock, flags); - mc->intr = true; - tu102_mc_intr_update(mc); - spin_unlock_irqrestore(&mc->lock, flags); -} - -static void -tu102_mc_intr_mask(struct nvkm_mc *base, u32 mask, u32 intr) -{ - struct tu102_mc *mc = tu102_mc(base); - unsigned long flags; - - spin_lock_irqsave(&mc->lock, flags); - mc->mask = (mc->mask & ~mask) | intr; - tu102_mc_intr_update(mc); - spin_unlock_irqrestore(&mc->lock, flags); -} - -static u32 -tu102_mc_intr_stat(struct nvkm_mc *mc) -{ - struct nvkm_device *device = mc->subdev.device; - u32 intr0 = nvkm_rd32(device, 0x000100); - u32 intr1 = nvkm_rd32(device, 0x000104); - - return intr0 | intr1; -} - - -static const struct nvkm_mc_func -tu102_mc = { - .init = nv50_mc_init, - .intr = gp100_mc_intr, - .intr_unarm = tu102_mc_intr_unarm, - .intr_rearm = tu102_mc_intr_rearm, - .intr_mask = tu102_mc_intr_mask, - .intr_stat = tu102_mc_intr_stat, - .reset = gk104_mc_reset, -}; - -static int -tu102_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc) -{ - struct tu102_mc *mc; - - if (!(mc = kzalloc(sizeof(*mc), GFP_KERNEL))) - return -ENOMEM; - nvkm_mc_ctor(func, device, type, inst, &mc->base); - *pmc = &mc->base; - - spin_lock_init(&mc->lock); - mc->intr = false; - mc->mask = 0x7fffffff; - return 0; -} - -int -tu102_mc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc) -{ - return tu102_mc_new_(&tu102_mc, device, type, inst, pmc); -} -- cgit v1.2.3 From ebb195dbb3390324100cb85c22129f6334064b5f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:55 +1000 Subject: drm/nouveau/mc: move NV_PMC_ENABLE bashing to chipset-specific code Ampere needs different handling here, most of what we touch has moved. We probably want to refactor these interfaces in general, but I'm not yet sure how they should look, this will get the job done for now. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c | 17 ++++++--------- drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c | 29 ++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h | 8 +++++++ 16 files changed, 56 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c index 322237e2ff80..c85600ba69f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c @@ -73,9 +73,8 @@ nvkm_mc_reset(struct nvkm_device *device, enum nvkm_subdev_type type, int inst) { u64 pmc_enable = nvkm_mc_reset_mask(device, true, type, inst); if (pmc_enable) { - nvkm_mask(device, 0x000200, pmc_enable, 0x00000000); - nvkm_mask(device, 0x000200, pmc_enable, pmc_enable); - nvkm_rd32(device, 0x000200); + device->mc->func->device->disable(device->mc, pmc_enable); + device->mc->func->device->enable(device->mc, pmc_enable); } } @@ -84,17 +83,15 @@ nvkm_mc_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst { u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst); if (pmc_enable) - nvkm_mask(device, 0x000200, pmc_enable, 0x00000000); + device->mc->func->device->disable(device->mc, pmc_enable); } void nvkm_mc_enable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst) { u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst); - if (pmc_enable) { - nvkm_mask(device, 0x000200, pmc_enable, pmc_enable); - nvkm_rd32(device, 0x000200); - } + if (pmc_enable) + device->mc->func->device->enable(device->mc, pmc_enable); } bool @@ -102,11 +99,9 @@ nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_subdev_type type, int inst { u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst); - return (pmc_enable != 0) && - ((nvkm_rd32(device, 0x000200) & pmc_enable) == pmc_enable); + return (pmc_enable != 0) && device->mc->func->device->enabled(device->mc, pmc_enable); } - static int nvkm_mc_init(struct nvkm_subdev *subdev) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c index 8a8267ecfe1d..9feb7d167d23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c @@ -56,6 +56,7 @@ g84_mc = { .init = nv50_mc_init, .intr = &nv04_mc_intr, .intrs = g84_mc_intrs, + .device = &nv04_mc_device, .reset = g84_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c index e099d419f1ce..b0b328044e55 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c @@ -56,6 +56,7 @@ g98_mc = { .init = nv50_mc_init, .intr = &nv04_mc_intr, .intrs = g98_mc_intrs, + .device = &nv04_mc_device, .reset = g98_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c index 98ccce9585eb..842326a24393 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c @@ -24,6 +24,7 @@ static const struct nvkm_mc_func ga100_mc = { .init = nv50_mc_init, + .device = &nv04_mc_device, .reset = gk104_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c index b2846eaea34c..d5dba44235cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c @@ -71,6 +71,7 @@ gf100_mc = { .intrs = gf100_mc_intrs, .intr_nonstall = true, .reset = gf100_mc_reset, + .device = &nv04_mc_device, .unk260 = gf100_mc_unk260, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c index edf82e4568bf..023dfda735cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c @@ -54,6 +54,7 @@ gk104_mc = { .intrs = gk104_mc_intrs, .intr_nonstall = true, .reset = gk104_mc_reset, + .device = &nv04_mc_device, .unk260 = gf100_mc_unk260, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c index 931985343ab5..d98a6563a411 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c @@ -29,6 +29,7 @@ gk20a_mc = { .intr = >215_mc_intr, .intrs = gk104_mc_intrs, .intr_nonstall = true, + .device = &nv04_mc_device, .reset = gk104_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c index 5dfdf75af255..bffde40bb237 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c @@ -90,6 +90,7 @@ gp100_mc = { .intr = &gp100_mc_intr, .intrs = gp100_mc_intrs, .intr_nonstall = true, + .device = &nv04_mc_device, .reset = gk104_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c index 6b83c6bf308c..9bed9c5ea5d3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c @@ -37,6 +37,7 @@ gp10b_mc = { .intr = &gp100_mc_intr, .intrs = gp100_mc_intrs, .intr_nonstall = true, + .device = &nv04_mc_device, .reset = gk104_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c index 330ef92f5e50..41e17a470388 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c @@ -83,6 +83,7 @@ gt215_mc = { .init = nv50_mc_init, .intr = &nv04_mc_intr, .intrs = gt215_mc_intrs, + .device = &nv04_mc_device, .reset = gt215_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c index 00adf6833d26..04809caf36d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c @@ -30,6 +30,34 @@ nv04_mc_reset[] = { {} }; +static void +nv04_mc_device_disable(struct nvkm_mc *mc, u32 mask) +{ + nvkm_mask(mc->subdev.device, 0x000200, mask, 0x00000000); +} + +static void +nv04_mc_device_enable(struct nvkm_mc *mc, u32 mask) +{ + struct nvkm_device *device = mc->subdev.device; + + nvkm_mask(device, 0x000200, mask, mask); + nvkm_rd32(device, 0x000200); +} + +static bool +nv04_mc_device_enabled(struct nvkm_mc *mc, u32 mask) +{ + return (nvkm_rd32(mc->subdev.device, 0x000200) & mask) == mask; +} + +const struct nvkm_mc_device_func +nv04_mc_device = { + .enabled = nv04_mc_device_enabled, + .enable = nv04_mc_device_enable, + .disable = nv04_mc_device_disable, +}; + static const struct nvkm_intr_data nv04_mc_intrs[] = { { NVKM_ENGINE_DISP , 0, 0, 0x01010000, true }, @@ -98,6 +126,7 @@ nv04_mc = { .init = nv04_mc_init, .intr = &nv04_mc_intr, .intrs = nv04_mc_intrs, + .device = &nv04_mc_device, .reset = nv04_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c index 1cef78827f57..6a3e2f4753ef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c @@ -38,6 +38,7 @@ nv11_mc = { .init = nv04_mc_init, .intr = &nv04_mc_intr, .intrs = nv11_mc_intrs, + .device = &nv04_mc_device, .reset = nv04_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c index ac70c359bce0..2edc1cb0e379 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c @@ -47,6 +47,7 @@ nv17_mc = { .init = nv04_mc_init, .intr = &nv04_mc_intr, .intrs = nv17_mc_intrs, + .device = &nv04_mc_device, .reset = nv17_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c index 0a054459a949..649a9fcc0a2f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c @@ -42,6 +42,7 @@ nv44_mc = { .init = nv44_mc_init, .intr = &nv04_mc_intr, .intrs = nv17_mc_intrs, + .device = &nv04_mc_device, .reset = nv17_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c index 6a02ed754c3f..a42d20206e37 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c @@ -49,6 +49,7 @@ nv50_mc = { .init = nv50_mc_init, .intr = &nv04_mc_intr, .intrs = nv50_mc_intrs, + .device = &nv04_mc_device, .reset = nv17_mc_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h index 3ecfe9b4fb05..7f38d54b4bc2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h @@ -21,7 +21,14 @@ struct nvkm_mc_func { const struct nvkm_intr_data *intrs; bool intr_nonstall; + const struct nvkm_mc_device_func { + bool (*enabled)(struct nvkm_mc *, u32 mask); + void (*enable)(struct nvkm_mc *, u32 mask); + void (*disable)(struct nvkm_mc *, u32 mask); + } *device; + const struct nvkm_mc_map *reset; + void (*unk260)(struct nvkm_mc *, u32); }; @@ -30,6 +37,7 @@ extern const struct nvkm_intr_func nv04_mc_intr; bool nv04_mc_intr_pending(struct nvkm_intr *); void nv04_mc_intr_unarm(struct nvkm_intr *); void nv04_mc_intr_rearm(struct nvkm_intr *); +extern const struct nvkm_mc_device_func nv04_mc_device; extern const struct nvkm_mc_map nv04_mc_reset[]; extern const struct nvkm_intr_data nv17_mc_intrs[]; -- cgit v1.2.3 From 565bfaf1f26af0e9fc9aafbb7053da1187afe9f4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:55 +1000 Subject: drm/nouveau/mc/ga100: switch to using NV_PMC_DEVICE_ENABLE - NV_PMC_ENABLE still exists, but we don't touch anything in it yet Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c | 47 ++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c index 842326a24393..1e2eabec1a76 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c @@ -21,11 +21,52 @@ */ #include "priv.h" +static void +ga100_mc_device_disable(struct nvkm_mc *mc, u32 mask) +{ + struct nvkm_device *device = mc->subdev.device; + + nvkm_mask(device, 0x000600, mask, 0x00000000); + nvkm_rd32(device, 0x000600); + nvkm_rd32(device, 0x000600); +} + +static void +ga100_mc_device_enable(struct nvkm_mc *mc, u32 mask) +{ + struct nvkm_device *device = mc->subdev.device; + + nvkm_mask(device, 0x000600, mask, mask); + nvkm_rd32(device, 0x000600); + nvkm_rd32(device, 0x000600); +} + +static bool +ga100_mc_device_enabled(struct nvkm_mc *mc, u32 mask) +{ + return (nvkm_rd32(mc->subdev.device, 0x000600) & mask) == mask; +} + +const struct nvkm_mc_device_func +ga100_mc_device = { + .enabled = ga100_mc_device_enabled, + .enable = ga100_mc_device_enable, + .disable = ga100_mc_device_disable, +}; + +static void +ga100_mc_init(struct nvkm_mc *mc) +{ + struct nvkm_device *device = mc->subdev.device; + + nvkm_wr32(device, 0x000200, 0xffffffff); + nvkm_wr32(device, 0x000600, 0xffffffff); +} + static const struct nvkm_mc_func ga100_mc = { - .init = nv50_mc_init, - .device = &nv04_mc_device, - .reset = gk104_mc_reset, + .init = ga100_mc_init, + .device = &ga100_mc_device, }; int -- cgit v1.2.3 From 8478cd5a740a092163c8ad5b6da1a1b488eb42bd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:19 +1000 Subject: drm/nouveau/nvkm: add locking to subdev/engine init paths This wasn't really needed before; the main place this could race is with channel recovery, but (through potentially fragile means) shouldn't have been possible. However, a number of upcoming patches benefit from having better control over subdev init, necessitating some improvements here. - allows subdev/engine oneinit() without init() (host/fifo patches) - merges engine use locking/tracking into subdev, and extends it to fix some issues that will arise with future usage patterns (acr patches) Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/engine.h | 6 -- drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 25 ++++- drivers/gpu/drm/nouveau/nvkm/core/engine.c | 63 ++++------- drivers/gpu/drm/nouveau/nvkm/core/subdev.c | 117 +++++++++++++++++---- 4 files changed, 142 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h index e58923b67d74..6d15c13509bf 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h @@ -12,12 +12,6 @@ struct nvkm_engine { const struct nvkm_engine_func *func; struct nvkm_subdev subdev; spinlock_t lock; - - struct { - refcount_t refcount; - struct mutex mutex; - bool enabled; - } use; }; struct nvkm_engine_func { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h index 20e1fc90c536..f920a2de1735 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h @@ -17,12 +17,19 @@ struct nvkm_subdev { struct nvkm_device *device; enum nvkm_subdev_type type; int inst; + char name[16]; u32 debug; - struct list_head head; + + struct { + refcount_t refcount; + struct mutex mutex; + bool enabled; + } use; struct nvkm_inth inth; + struct list_head head; void **pself; bool oneinit; }; @@ -40,11 +47,23 @@ struct nvkm_subdev_func { extern const char *nvkm_subdev_type[NVKM_SUBDEV_NR]; int nvkm_subdev_new_(const struct nvkm_subdev_func *, struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_subdev **); -void nvkm_subdev_ctor(const struct nvkm_subdev_func *, struct nvkm_device *, - enum nvkm_subdev_type, int inst, struct nvkm_subdev *); +void __nvkm_subdev_ctor(const struct nvkm_subdev_func *, struct nvkm_device *, + enum nvkm_subdev_type, int inst, struct nvkm_subdev *); + +static inline void +nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_subdev *subdev) +{ + __nvkm_subdev_ctor(func, device, type, inst, subdev); + mutex_init(&subdev->use.mutex); +} + void nvkm_subdev_disable(struct nvkm_device *, enum nvkm_subdev_type, int inst); void nvkm_subdev_del(struct nvkm_subdev **); +int nvkm_subdev_ref(struct nvkm_subdev *); +void nvkm_subdev_unref(struct nvkm_subdev *); int nvkm_subdev_preinit(struct nvkm_subdev *); +int nvkm_subdev_oneinit(struct nvkm_subdev *); int nvkm_subdev_init(struct nvkm_subdev *); int nvkm_subdev_fini(struct nvkm_subdev *, bool suspend); int nvkm_subdev_info(struct nvkm_subdev *, u64, u64 *); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c index e41a39ae1597..558bd10e5518 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c @@ -39,12 +39,9 @@ void nvkm_engine_unref(struct nvkm_engine **pengine) { struct nvkm_engine *engine = *pengine; + if (engine) { - if (refcount_dec_and_mutex_lock(&engine->use.refcount, &engine->use.mutex)) { - nvkm_subdev_fini(&engine->subdev, false); - engine->use.enabled = false; - mutex_unlock(&engine->use.mutex); - } + nvkm_subdev_unref(&engine->subdev); *pengine = NULL; } } @@ -53,21 +50,13 @@ struct nvkm_engine * nvkm_engine_ref(struct nvkm_engine *engine) { int ret; + if (engine) { - if (!refcount_inc_not_zero(&engine->use.refcount)) { - mutex_lock(&engine->use.mutex); - if (!refcount_inc_not_zero(&engine->use.refcount)) { - engine->use.enabled = true; - if ((ret = nvkm_subdev_init(&engine->subdev))) { - engine->use.enabled = false; - mutex_unlock(&engine->use.mutex); - return ERR_PTR(ret); - } - refcount_set(&engine->use.refcount, 1); - } - mutex_unlock(&engine->use.mutex); - } + ret = nvkm_subdev_ref(&engine->subdev); + if (ret) + return ERR_PTR(ret); } + return engine; } @@ -117,26 +106,6 @@ nvkm_engine_init(struct nvkm_subdev *subdev) struct nvkm_engine *engine = nvkm_engine(subdev); struct nvkm_fb *fb = subdev->device->fb; int ret = 0, i; - s64 time; - - if (!engine->use.enabled) { - nvkm_trace(subdev, "init skipped, engine has no users\n"); - return ret; - } - - if (engine->func->oneinit && !engine->subdev.oneinit) { - nvkm_trace(subdev, "one-time init running...\n"); - time = ktime_to_us(ktime_get()); - ret = engine->func->oneinit(engine); - if (ret) { - nvkm_trace(subdev, "one-time init failed, %d\n", ret); - return ret; - } - - engine->subdev.oneinit = true; - time = ktime_to_us(ktime_get()) - time; - nvkm_trace(subdev, "one-time init completed in %lldus\n", time); - } if (engine->func->init) ret = engine->func->init(engine); @@ -146,6 +115,17 @@ nvkm_engine_init(struct nvkm_subdev *subdev) return ret; } +static int +nvkm_engine_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_engine *engine = nvkm_engine(subdev); + + if (engine->func->oneinit) + return engine->func->oneinit(engine); + + return 0; +} + static int nvkm_engine_preinit(struct nvkm_subdev *subdev) { @@ -161,7 +141,6 @@ nvkm_engine_dtor(struct nvkm_subdev *subdev) struct nvkm_engine *engine = nvkm_engine(subdev); if (engine->func->dtor) return engine->func->dtor(engine); - mutex_destroy(&engine->use.mutex); return engine; } @@ -169,6 +148,7 @@ const struct nvkm_subdev_func nvkm_engine = { .dtor = nvkm_engine_dtor, .preinit = nvkm_engine_preinit, + .oneinit = nvkm_engine_oneinit, .init = nvkm_engine_init, .fini = nvkm_engine_fini, .info = nvkm_engine_info, @@ -179,10 +159,9 @@ int nvkm_engine_ctor(const struct nvkm_engine_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, bool enable, struct nvkm_engine *engine) { - nvkm_subdev_ctor(&nvkm_engine, device, type, inst, &engine->subdev); engine->func = func; - refcount_set(&engine->use.refcount, 0); - mutex_init(&engine->use.mutex); + nvkm_subdev_ctor(&nvkm_engine, device, type, inst, &engine->subdev); + refcount_set(&engine->subdev.use.refcount, 0); if (!nvkm_boolopt(device->cfgopt, engine->subdev.name, enable)) { nvkm_debug(&engine->subdev, "disabled\n"); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c index a74b7acb6832..6c20e827a069 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c @@ -54,7 +54,7 @@ int nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend) { struct nvkm_device *device = subdev->device; - const char *action = suspend ? "suspend" : "fini"; + const char *action = suspend ? "suspend" : subdev->use.enabled ? "fini" : "reset"; s64 time; nvkm_trace(subdev, "%s running...\n", action); @@ -68,6 +68,7 @@ nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend) return ret; } } + subdev->use.enabled = false; nvkm_mc_reset(device, subdev->type, subdev->inst); @@ -97,30 +98,49 @@ nvkm_subdev_preinit(struct nvkm_subdev *subdev) return 0; } -int -nvkm_subdev_init(struct nvkm_subdev *subdev) +static int +nvkm_subdev_oneinit_(struct nvkm_subdev *subdev) { s64 time; int ret; - nvkm_trace(subdev, "init running...\n"); + if (!subdev->func->oneinit || subdev->oneinit) + return 0; + + nvkm_trace(subdev, "one-time init running...\n"); time = ktime_to_us(ktime_get()); + ret = subdev->func->oneinit(subdev); + if (ret) { + nvkm_error(subdev, "one-time init failed, %d\n", ret); + return ret; + } - if (subdev->func->oneinit && !subdev->oneinit) { - s64 time; - nvkm_trace(subdev, "one-time init running...\n"); - time = ktime_to_us(ktime_get()); - ret = subdev->func->oneinit(subdev); - if (ret) { - nvkm_error(subdev, "one-time init failed, %d\n", ret); - return ret; - } + subdev->oneinit = true; + time = ktime_to_us(ktime_get()) - time; + nvkm_trace(subdev, "one-time init completed in %lldus\n", time); + return 0; +} - subdev->oneinit = true; - time = ktime_to_us(ktime_get()) - time; - nvkm_trace(subdev, "one-time init completed in %lldus\n", time); +static int +nvkm_subdev_init_(struct nvkm_subdev *subdev) +{ + s64 time; + int ret; + + if (subdev->use.enabled) { + nvkm_trace(subdev, "init skipped, already running\n"); + return 0; } + nvkm_trace(subdev, "init running...\n"); + time = ktime_to_us(ktime_get()); + + ret = nvkm_subdev_oneinit_(subdev); + if (ret) + return ret; + + subdev->use.enabled = true; + if (subdev->func->init) { ret = subdev->func->init(subdev); if (ret) { @@ -134,6 +154,64 @@ nvkm_subdev_init(struct nvkm_subdev *subdev) return 0; } +int +nvkm_subdev_init(struct nvkm_subdev *subdev) +{ + int ret; + + mutex_lock(&subdev->use.mutex); + if (refcount_read(&subdev->use.refcount) == 0) { + nvkm_trace(subdev, "init skipped, no users\n"); + mutex_unlock(&subdev->use.mutex); + return 0; + } + + ret = nvkm_subdev_init_(subdev); + mutex_unlock(&subdev->use.mutex); + return ret; +} + +int +nvkm_subdev_oneinit(struct nvkm_subdev *subdev) +{ + int ret; + + mutex_lock(&subdev->use.mutex); + ret = nvkm_subdev_oneinit_(subdev); + mutex_unlock(&subdev->use.mutex); + return ret; +} + +void +nvkm_subdev_unref(struct nvkm_subdev *subdev) +{ + if (refcount_dec_and_mutex_lock(&subdev->use.refcount, &subdev->use.mutex)) { + nvkm_subdev_fini(subdev, false); + mutex_unlock(&subdev->use.mutex); + } +} + +int +nvkm_subdev_ref(struct nvkm_subdev *subdev) +{ + int ret; + + if (subdev && !refcount_inc_not_zero(&subdev->use.refcount)) { + mutex_lock(&subdev->use.mutex); + if (!refcount_inc_not_zero(&subdev->use.refcount)) { + if ((ret = nvkm_subdev_init_(subdev))) { + mutex_unlock(&subdev->use.mutex); + return ret; + } + + refcount_set(&subdev->use.refcount, 1); + } + mutex_unlock(&subdev->use.mutex); + } + + return 0; +} + void nvkm_subdev_del(struct nvkm_subdev **psubdev) { @@ -146,6 +224,7 @@ nvkm_subdev_del(struct nvkm_subdev **psubdev) list_del(&subdev->head); if (subdev->func->dtor) *psubdev = subdev->func->dtor(subdev); + mutex_destroy(&subdev->use.mutex); time = ktime_to_us(ktime_get()) - time; nvkm_trace(subdev, "destroy completed in %lldus\n", time); kfree(*psubdev); @@ -167,8 +246,8 @@ nvkm_subdev_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int } void -nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_subdev *subdev) +__nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_subdev *subdev) { subdev->func = func; subdev->device = device; @@ -180,6 +259,8 @@ nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device else strscpy(subdev->name, nvkm_subdev_type[type], sizeof(subdev->name)); subdev->debug = nvkm_dbgopt(device->dbgopt, subdev->name); + + refcount_set(&subdev->use.refcount, 1); list_add_tail(&subdev->head, &device->subdev); } -- cgit v1.2.3 From e442f1e453143c801b9fb213f514ceabb6c3b746 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:20 +1000 Subject: drm/nouveau/flcn: show falcon user in debug output Displays both owner/user of the falcon (when they differ), and takes both subdevs' debug levels into account when deciding whether to log the message. - runlist debugging will use one of the alternate macros added here Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 16 ++++++++-------- drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 15 +++++++++++---- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 7 +++---- 3 files changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index fd9a3f9a518e..d647d8acb15b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -21,14 +21,14 @@ void nvkm_falcon_v1_disable(struct nvkm_falcon *); void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *); int gp102_sec2_flcn_enable(struct nvkm_falcon *); -#define FLCN_PRINTK(t,f,fmt,a...) do { \ - if ((f)->owner->name != (f)->name) \ - nvkm_##t((f)->owner, "%s: "fmt"\n", (f)->name, ##a); \ - else \ - nvkm_##t((f)->owner, fmt"\n", ##a); \ -} while(0) -#define FLCN_DBG(f,fmt,a...) FLCN_PRINTK(debug, (f), fmt, ##a) -#define FLCN_ERR(f,fmt,a...) FLCN_PRINTK(error, (f), fmt, ##a) +#define FLCN_PRINTK(f,l,p,fmt,a...) ({ \ + if ((f)->owner->name != (f)->name) \ + nvkm_printk___((f)->owner, (f)->user, NV_DBG_##l, p, "%s:"fmt, (f)->name, ##a); \ + else \ + nvkm_printk___((f)->owner, (f)->user, NV_DBG_##l, p, fmt, ##a); \ +}) +#define FLCN_DBG(f,fmt,a...) FLCN_PRINTK((f), DEBUG, info, " "fmt"\n", ##a) +#define FLCN_ERR(f,fmt,a...) FLCN_PRINTK((f), ERROR, err, " "fmt"\n", ##a) /** * struct nvfw_falcon_msg - header for all messages diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h index f920a2de1735..bce6e1ba09ea 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h @@ -70,11 +70,18 @@ int nvkm_subdev_info(struct nvkm_subdev *, u64, u64 *); void nvkm_subdev_intr(struct nvkm_subdev *); /* subdev logging */ -#define nvkm_printk_(s,l,p,f,a...) do { \ - const struct nvkm_subdev *_subdev = (s); \ - if (CONFIG_NOUVEAU_DEBUG >= (l) && _subdev->debug >= (l)) \ - dev_##p(_subdev->device->dev, "%s: "f, _subdev->name, ##a); \ +#define nvkm_printk_ok(s,u,l) \ + ((CONFIG_NOUVEAU_DEBUG >= (l)) && ((s)->debug >= (l) || ((u) && (u)->debug >= (l)))) +#define nvkm_printk___(s,u,l,p,f,a...) do { \ + if (nvkm_printk_ok((s), (u), (l))) { \ + if ((u) && (u) != (s)) \ + dev_##p((s)->device->dev, "%s(%s):"f, (s)->name, (u)->name, ##a); \ + else \ + dev_##p((s)->device->dev, "%s:"f, (s)->name, ##a); \ + } \ } while(0) +#define nvkm_printk__(s,l,p,f,a...) nvkm_printk___((s), (s), (l), p, f, ##a) +#define nvkm_printk_(s,l,p,f,a...) nvkm_printk__((s), (l), p, " "f, ##a) #define nvkm_printk(s,l,p,f,a...) nvkm_printk_((s), NV_DBG_##l, p, f, ##a) #define nvkm_fatal(s,f,a...) nvkm_printk((s), FATAL, crit, f, ##a) #define nvkm_error(s,f,a...) nvkm_printk((s), ERROR, err, f, ##a) diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index 976cb7b7aa99..33564ac906a8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -82,8 +82,7 @@ struct nvkm_falcon_msgq { u32 position; }; -#define FLCNQ_PRINTK(t,q,f,a...) \ - FLCN_PRINTK(t, (q)->qmgr->falcon, "%s: "f, (q)->name, ##a) -#define FLCNQ_DBG(q,f,a...) FLCNQ_PRINTK(debug, (q), f, ##a) -#define FLCNQ_ERR(q,f,a...) FLCNQ_PRINTK(error, (q), f, ##a) +#define FLCNQ_PRINTK(q,l,p,f,a...) FLCN_PRINTK((q)->qmgr->falcon, l, p, "%s: "f, (q)->name, ##a) +#define FLCNQ_DBG(q,f,a...) FLCNQ_PRINTK((q), DEBUG, info, f, ##a) +#define FLCNQ_ERR(q,f,a...) FLCNQ_PRINTK((q), ERROR, err, f, ##a) #endif -- cgit v1.2.3 From 973b32443b090870903ad8346adfc911e7c0f188 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:21 +1000 Subject: drm/nouveau/imem: allow bar2 mapping of user allocations Will be used to init client-allocated USERD to default values. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/memory.h | 2 ++ .../gpu/drm/nouveau/include/nvkm/subdev/instmem.h | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c | 8 +++++++ drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c | 12 ++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c | 27 ++++++++++++++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h | 1 + 6 files changed, 46 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h index 74d3f1a809d7..d3b6a68ddda3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h @@ -37,6 +37,7 @@ struct nvkm_memory_func { void (*release)(struct nvkm_memory *); int (*map)(struct nvkm_memory *, u64 offset, struct nvkm_vmm *, struct nvkm_vma *, void *argv, u32 argc); + int (*kmap)(struct nvkm_memory *, struct nvkm_memory **); }; struct nvkm_memory_ptrs { @@ -63,6 +64,7 @@ void nvkm_memory_tags_put(struct nvkm_memory *, struct nvkm_device *, #define nvkm_memory_boot(p,v) (p)->func->boot((p),(v)) #define nvkm_memory_map(p,o,vm,va,av,ac) \ (p)->func->map((p),(o),(vm),(va),(av),(ac)) +#define nvkm_memory_kmap(p,i) ((p)->func->kmap ? (p)->func->kmap((p), (i)) : -ENOSYS) /* accessor macros - kmap()/done() must bracket use of the other accessor * macros to guarantee correct behaviour across all chipsets diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h index f967b97d163c..fcdaefc99fe8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h @@ -28,7 +28,7 @@ u32 nvkm_instmem_rd32(struct nvkm_instmem *, u32 addr); void nvkm_instmem_wr32(struct nvkm_instmem *, u32 addr, u32 data); int nvkm_instobj_new(struct nvkm_instmem *, u32 size, u32 align, bool zero, struct nvkm_memory **); - +int nvkm_instobj_wrap(struct nvkm_device *, struct nvkm_memory *, struct nvkm_memory **); int nv04_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_instmem **); int nv40_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_instmem **); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c index 03b1bdb27770..5c34416cb637 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c @@ -25,6 +25,7 @@ #include "ram.h" #include +#include #include struct nvkm_vram { @@ -34,6 +35,12 @@ struct nvkm_vram { struct nvkm_mm_node *mn; }; +static int +nvkm_vram_kmap(struct nvkm_memory *memory, struct nvkm_memory **pmemory) +{ + return nvkm_instobj_wrap(nvkm_vram(memory)->ram->fb->subdev.device, memory, pmemory); +} + static int nvkm_vram_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, struct nvkm_vma *vma, void *argv, u32 argc) @@ -98,6 +105,7 @@ nvkm_vram = { .addr = nvkm_vram_addr, .size = nvkm_vram_size, .map = nvkm_vram_map, + .kmap = nvkm_vram_kmap, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c index cd8163a52bb6..e0e4f97be029 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c @@ -89,6 +89,18 @@ nvkm_instobj_ctor(const struct nvkm_memory_func *func, spin_unlock(&imem->lock); } +int +nvkm_instobj_wrap(struct nvkm_device *device, + struct nvkm_memory *memory, struct nvkm_memory **pmemory) +{ + struct nvkm_instmem *imem = device->imem; + + if (!imem->func->memory_wrap) + return -ENOSYS; + + return imem->func->memory_wrap(imem, memory, pmemory); +} + int nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, struct nvkm_memory **pmemory) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c index c51bac76174c..4b2d7465d22f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c @@ -348,13 +348,11 @@ nv50_instobj_func = { }; static int -nv50_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, - struct nvkm_memory **pmemory) +nv50_instobj_wrap(struct nvkm_instmem *base, + struct nvkm_memory *memory, struct nvkm_memory **pmemory) { struct nv50_instmem *imem = nv50_instmem(base); struct nv50_instobj *iobj; - struct nvkm_device *device = imem->base.subdev.device; - u8 page = max(order_base_2(align), 12); if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) return -ENOMEM; @@ -365,7 +363,25 @@ nv50_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, refcount_set(&iobj->maps, 0); INIT_LIST_HEAD(&iobj->lru); - return nvkm_ram_get(device, 0, 1, page, size, true, true, &iobj->ram); + iobj->ram = nvkm_memory_ref(memory); + return 0; +} + +static int +nv50_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, + struct nvkm_memory **pmemory) +{ + u8 page = max(order_base_2(align), 12); + struct nvkm_memory *ram; + int ret; + + ret = nvkm_ram_get(imem->subdev.device, 0, 1, page, size, true, true, &ram); + if (ret) + return ret; + + ret = nv50_instobj_wrap(imem, ram, pmemory); + nvkm_memory_unref(&ram); + return ret; } /****************************************************************************** @@ -382,6 +398,7 @@ static const struct nvkm_instmem_func nv50_instmem = { .fini = nv50_instmem_fini, .memory_new = nv50_instobj_new, + .memory_wrap = nv50_instobj_wrap, .zero = false, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h index 56c15e30a5dd..fe92986a3885 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h @@ -12,6 +12,7 @@ struct nvkm_instmem_func { void (*wr32)(struct nvkm_instmem *, u32 addr, u32 data); int (*memory_new)(struct nvkm_instmem *, u32 size, u32 align, bool zero, struct nvkm_memory **); + int (*memory_wrap)(struct nvkm_instmem *, struct nvkm_memory *, struct nvkm_memory **); bool zero; }; -- cgit v1.2.3 From 8c18138c7633f7f9e609be6b11e48bb33a8dfb75 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:21 +1000 Subject: drm/nouveau/fifo: add chid_nr() - reads channel count from GPU from gm200 onwards - removes gm20b/gp10b (they become identical to gm200/gp100) Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/os.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 20 +++++----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 11 +++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 9 ++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 9 ++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 9 ++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c | 45 --------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c | 46 ---------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 9 ++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 7 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 9 ++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 15 ++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 33 ++++++++-------- 25 files changed, 114 insertions(+), 137 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h index d7ba3205207f..5a516b903fe9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h @@ -34,4 +34,5 @@ nvkm_blob_dtor(struct nvkm_blob *blob) blob->data = NULL; blob->size = 0; } + #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 5a19c71f7ccb..3cc7cfebfa5e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -72,9 +72,7 @@ int gk208_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct int gk20a_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int gm107_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int gm200_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); -int gm20b_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int gp100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); -int gp10b_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int gv100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int tu102_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int ga102_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 587aebcda78c..532231f1a0f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2130,7 +2130,7 @@ nv12b_chipset = { .volt = { 0x00000001, gm20b_volt_new }, .ce = { 0x00000004, gm200_ce_new }, .dma = { 0x00000001, gf119_dma_new }, - .fifo = { 0x00000001, gm20b_fifo_new }, + .fifo = { 0x00000001, gm200_fifo_new }, .gr = { 0x00000001, gm20b_gr_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -2356,7 +2356,7 @@ nv13b_chipset = { .top = { 0x00000001, gk104_top_new }, .ce = { 0x00000001, gp100_ce_new }, .dma = { 0x00000001, gf119_dma_new }, - .fifo = { 0x00000001, gp10b_fifo_new }, + .fifo = { 0x00000001, gp100_fifo_new }, .gr = { 0x00000001, gp10b_gr_new }, .sw = { 0x00000001, gf100_sw_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index 0fa4df299009..8599063e8622 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -13,9 +13,7 @@ nvkm-y += nvkm/engine/fifo/gk208.o nvkm-y += nvkm/engine/fifo/gk20a.o nvkm-y += nvkm/engine/fifo/gm107.o nvkm-y += nvkm/engine/fifo/gm200.o -nvkm-y += nvkm/engine/fifo/gm20b.o nvkm-y += nvkm/engine/fifo/gp100.o -nvkm-y += nvkm/engine/fifo/gp10b.o nvkm-y += nvkm/engine/fifo/gv100.o nvkm-y += nvkm/engine/fifo/tu102.o nvkm-y += nvkm/engine/fifo/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 518f3c492f01..b11a4cb18fc7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -24,14 +24,14 @@ #include "priv.h" #include "chan.h" -#include #include #include -#include #include #include +#include "gk104.h" + void nvkm_fifo_recover_chan(struct nvkm_fifo *fifo, int chid) { @@ -290,25 +290,27 @@ nvkm_fifo = { int nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, int nr, struct nvkm_fifo *fifo) + enum nvkm_subdev_type type, int inst, struct nvkm_fifo *fifo) { - int ret; + int ret, nr; fifo->func = func; - INIT_LIST_HEAD(&fifo->chan); spin_lock_init(&fifo->lock); mutex_init(&fifo->mutex); + ret = nvkm_engine_ctor(&nvkm_fifo, device, type, inst, true, &fifo->engine); + if (ret) + return ret; + + INIT_LIST_HEAD(&fifo->chan); + + nr = func->chid_nr ? func->chid_nr(fifo) : gk104_fifo(fifo)->func->chid_nr(fifo); if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR)) fifo->nr = NVKM_FIFO_CHID_NR; else fifo->nr = nr; bitmap_clear(fifo->mask, 0, fifo->nr); - ret = nvkm_engine_ctor(&nvkm_fifo, device, type, inst, true, &fifo->engine); - if (ret) - return ret; - if (func->uevent_init) { ret = nvkm_event_init(&nvkm_fifo_uevent_func, &fifo->engine.subdev, 1, 1, &fifo->uevent); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 3885c3830b94..c452388fd2a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -110,6 +110,7 @@ static const struct nvkm_fifo_func g84_fifo = { .dtor = nv50_fifo_dtor, .oneinit = nv50_fifo_oneinit, + .chid_nr = nv50_fifo_chid_nr, .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = g84_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 8b4f36b3e34b..e10c094c9a7d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -669,6 +669,7 @@ static const struct nvkm_fifo_func gf100_fifo = { .dtor = gf100_fifo_dtor, .oneinit = gf100_fifo_oneinit, + .chid_nr = nv50_fifo_chid_nr, .init = gf100_fifo_init, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, @@ -695,5 +696,5 @@ gf100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, INIT_WORK(&fifo->recover.work, gf100_fifo_recover_work); *pfifo = &fifo->base; - return nvkm_fifo_ctor(&gf100_fifo, device, type, inst, 128, &fifo->base); + return nvkm_fifo_ctor(&gf100_fifo, device, type, inst, &fifo->base); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index e771bd519ee2..e11b5eb8e196 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -1055,6 +1055,12 @@ gk104_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002140, 0x7fffffff); } +int +gk104_fifo_chid_nr(struct nvkm_fifo *fifo) +{ + return 4096; +} + void * gk104_fifo_dtor(struct nvkm_fifo *base) { @@ -1103,7 +1109,7 @@ gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device, INIT_WORK(&fifo->recover.work, gk104_fifo_recover_work); *pfifo = &fifo->base; - return nvkm_fifo_ctor(&gk104_fifo_, device, type, inst, nr, &fifo->base); + return nvkm_fifo_ctor(&gk104_fifo_, device, type, inst, &fifo->base); } const struct nvkm_enum @@ -1230,6 +1236,7 @@ gk104_fifo_fault_gpcclient[] = { static const struct gk104_fifo_func gk104_fifo = { + .chid_nr = gk104_fifo_chid_nr, .intr.fault = gf100_fifo_intr_fault, .pbdma = &gk104_fifo_pbdma, .fault.access = gk104_fifo_fault_access, @@ -1245,5 +1252,5 @@ int gk104_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gk104_fifo, device, type, inst, 4096, pfifo); + return gk104_fifo_new_(&gk104_fifo, device, type, inst, 0, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index f2d12ae73944..5eca8c757966 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -46,6 +46,8 @@ struct gk104_fifo { }; struct gk104_fifo_func { + int (*chid_nr)(struct nvkm_fifo *); + struct { void (*fault)(struct nvkm_fifo *, int unit); } intr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 915278c7e012..047e128febd1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -48,6 +48,7 @@ gk110_fifo_runlist = { static const struct gk104_fifo_func gk110_fifo = { + .chid_nr = gk104_fifo_chid_nr, .intr.fault = gf100_fifo_intr_fault, .pbdma = &gk104_fifo_pbdma, .fault.access = gk104_fifo_fault_access, @@ -63,5 +64,5 @@ int gk110_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gk110_fifo, device, type, inst, 4096, pfifo); + return gk104_fifo_new_(&gk110_fifo, device, type, inst, 0, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index cb703693de52..89b9c4fa35cc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -43,8 +43,15 @@ gk208_fifo_pbdma = { .init_timeout = gk208_fifo_pbdma_init_timeout, }; +static int +gk208_fifo_chid_nr(struct nvkm_fifo *fifo) +{ + return 1024; +} + static const struct gk104_fifo_func gk208_fifo = { + .chid_nr = gk208_fifo_chid_nr, .intr.fault = gf100_fifo_intr_fault, .pbdma = &gk208_fifo_pbdma, .fault.access = gk104_fifo_fault_access, @@ -60,5 +67,5 @@ int gk208_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gk208_fifo, device, type, inst, 1024, pfifo); + return gk104_fifo_new_(&gk208_fifo, device, type, inst, 0, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 6e35cf44c640..48cdcf9a4a72 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -26,6 +26,7 @@ static const struct gk104_fifo_func gk20a_fifo = { + .chid_nr = nv50_fifo_chid_nr, .intr.fault = gf100_fifo_intr_fault, .pbdma = &gk208_fifo_pbdma, .fault.access = gk104_fifo_fault_access, @@ -41,5 +42,5 @@ int gk20a_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gk20a_fifo, device, type, inst, 128, pfifo); + return gk104_fifo_new_(&gk20a_fifo, device, type, inst, 0, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 7af6e687d474..7b4244f184d2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -92,8 +92,15 @@ gm107_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) nvkm_fifo_fault(fifo, &info); } +static int +gm107_fifo_chid_nr(struct nvkm_fifo *fifo) +{ + return 2048; +} + static const struct gk104_fifo_func gm107_fifo = { + .chid_nr = gm107_fifo_chid_nr, .intr.fault = gm107_fifo_intr_fault, .pbdma = &gk208_fifo_pbdma, .fault.access = gk104_fifo_fault_access, @@ -109,5 +116,5 @@ int gm107_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gm107_fifo, device, type, inst, 2048, pfifo); + return gk104_fifo_new_(&gm107_fifo, device, type, inst, 0, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 573658cb6c73..17836a383c76 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -40,8 +40,15 @@ gm200_fifo_pbdma = { .init_timeout = gk208_fifo_pbdma_init_timeout, }; +int +gm200_fifo_chid_nr(struct nvkm_fifo *fifo) +{ + return nvkm_rd32(fifo->engine.subdev.device, 0x002008); +} + static const struct gk104_fifo_func gm200_fifo = { + .chid_nr = gm200_fifo_chid_nr, .intr.fault = gm107_fifo_intr_fault, .pbdma = &gm200_fifo_pbdma, .fault.access = gk104_fifo_fault_access, @@ -57,5 +64,5 @@ int gm200_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gm200_fifo, device, type, inst, 4096, pfifo); + return gk104_fifo_new_(&gm200_fifo, device, type, inst, 0, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c deleted file mode 100644 index 556c97e54f14..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#include "gk104.h" -#include "changk104.h" - -#include - -static const struct gk104_fifo_func -gm20b_fifo = { - .intr.fault = gm107_fifo_intr_fault, - .pbdma = &gm200_fifo_pbdma, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gm107_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, - .runlist = &gm107_fifo_runlist, - .chan = {{0,0,MAXWELL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, -}; - -int -gm20b_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, - struct nvkm_fifo **pfifo) -{ - return gk104_fifo_new_(&gm20b_fifo, device, type, inst, 512, pfifo); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 6b46b6b65b87..7a1ac3d863ec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -78,6 +78,7 @@ gp100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) static const struct gk104_fifo_func gp100_fifo = { + .chid_nr = gm200_fifo_chid_nr, .intr.fault = gp100_fifo_intr_fault, .pbdma = &gm200_fifo_pbdma, .fault.access = gk104_fifo_fault_access, @@ -94,5 +95,5 @@ int gp100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gp100_fifo, device, type, inst, 4096, pfifo); + return gk104_fifo_new_(&gp100_fifo, device, type, inst, 0, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c deleted file mode 100644 index 7a5929cb4d29..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#include "gk104.h" -#include "changk104.h" - -#include - -static const struct gk104_fifo_func -gp10b_fifo = { - .intr.fault = gp100_fifo_intr_fault, - .pbdma = &gm200_fifo_pbdma, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gp100_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, - .runlist = &gm107_fifo_runlist, - .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, - .cgrp_force = true, -}; - -int -gp10b_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, - struct nvkm_fifo **pfifo) -{ - return gk104_fifo_new_(&gp10b_fifo, device, type, inst, 512, pfifo); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index f56369d59219..0be50120476f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -287,6 +287,7 @@ gv100_fifo_fault_access[] = { static const struct gk104_fifo_func gv100_fifo = { + .chid_nr = gm200_fifo_chid_nr, .pbdma = &gm200_fifo_pbdma, .fault.access = gv100_fifo_fault_access, .fault.engine = gv100_fifo_fault_engine, @@ -302,5 +303,5 @@ int gv100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gv100_fifo, device, type, inst, 4096, pfifo); + return gk104_fifo_new_(&gv100_fifo, device, type, inst, 0, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index c6730c124769..e4b4133be3a4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -356,6 +356,12 @@ nv04_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, NV03_PFIFO_CACHES, 1); } +static int +nv04_fifo_chid_nr(struct nvkm_fifo *fifo) +{ + return 16; +} + int nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, int nr, const struct nv04_fifo_ramfc *ramfc, @@ -369,7 +375,7 @@ nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, fifo->ramfc = ramfc; *pfifo = &fifo->base; - ret = nvkm_fifo_ctor(func, device, type, inst, nr, &fifo->base); + ret = nvkm_fifo_ctor(func, device, type, inst, &fifo->base); if (ret) return ret; @@ -379,6 +385,7 @@ nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, static const struct nvkm_fifo_func nv04_fifo = { + .chid_nr = nv04_fifo_chid_nr, .init = nv04_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index f8887f0f2f82..94ad6ee19297 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -39,8 +39,15 @@ nv10_fifo_ramfc[] = { {} }; +int +nv10_fifo_chid_nr(struct nvkm_fifo *fifo) +{ + return 32; +} + static const struct nvkm_fifo_func nv10_fifo = { + .chid_nr = nv10_fifo_chid_nr, .init = nv04_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index 3f94c7b5b054..23d320362c86 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -79,6 +79,7 @@ nv17_fifo_init(struct nvkm_fifo *base) static const struct nvkm_fifo_func nv17_fifo = { + .chid_nr = nv10_fifo_chid_nr, .init = nv17_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index f9ea46809bc0..01e75c80b4f3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -110,6 +110,7 @@ nv40_fifo_init(struct nvkm_fifo *base) static const struct nvkm_fifo_func nv40_fifo = { + .chid_nr = nv10_fifo_chid_nr, .init = nv40_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index a08742cf425a..9d0cfb856401 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -96,6 +96,12 @@ nv50_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002500, 0x00000001); } +int +nv50_fifo_chid_nr(struct nvkm_fifo *fifo) +{ + return 128; +} + void * nv50_fifo_dtor(struct nvkm_fifo *base) { @@ -116,7 +122,7 @@ nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, return -ENOMEM; *pfifo = &fifo->base; - ret = nvkm_fifo_ctor(func, device, type, inst, 128, &fifo->base); + ret = nvkm_fifo_ctor(func, device, type, inst, &fifo->base); if (ret) return ret; @@ -129,6 +135,7 @@ static const struct nvkm_fifo_func nv50_fifo = { .dtor = nv50_fifo_dtor, .oneinit = nv50_fifo_oneinit, + .chid_nr = nv50_fifo_chid_nr, .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 79cec57647f0..66e93609c3c7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -4,8 +4,6 @@ #define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine) #include -int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - int nr, struct nvkm_fifo *); void nvkm_fifo_uevent(struct nvkm_fifo *); void nvkm_fifo_kevent(struct nvkm_fifo *, int chid); void nvkm_fifo_recover_chan(struct nvkm_fifo *, int chid); @@ -16,7 +14,10 @@ nvkm_fifo_chan_inst_locked(struct nvkm_fifo *, u64 inst); struct nvkm_fifo_chan_oclass; struct nvkm_fifo_func { void *(*dtor)(struct nvkm_fifo *); + int (*oneinit)(struct nvkm_fifo *); + int (*chid_nr)(struct nvkm_fifo *); + int (*info)(struct nvkm_fifo *, u64 mthd, u64 *data); void (*init)(struct nvkm_fifo *); void (*fini)(struct nvkm_fifo *); @@ -35,14 +36,24 @@ struct nvkm_fifo_func { const struct nvkm_fifo_chan_oclass *chan[]; }; +int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, + struct nvkm_fifo *); + void nv04_fifo_intr(struct nvkm_fifo *); int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *nv04_fifo_id_engine(struct nvkm_fifo *, int); void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); +int nv10_fifo_chid_nr(struct nvkm_fifo *); + +int nv50_fifo_chid_nr(struct nvkm_fifo *); + void gf100_fifo_intr_fault(struct nvkm_fifo *, int); +int gk104_fifo_chid_nr(struct nvkm_fifo *); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int); + +int gm200_fifo_chid_nr(struct nvkm_fifo *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index b800cfc5bfd9..63a3a2c0a824 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -24,12 +24,10 @@ #include "changk104.h" #include -#include +#include #include #include #include -#include -#include #include @@ -100,19 +98,6 @@ tu102_fifo_pbdma = { .init_timeout = gk208_fifo_pbdma_init_timeout, }; -static const struct gk104_fifo_func -tu102_fifo = { - .pbdma = &tu102_fifo_pbdma, - .fault.access = gv100_fifo_fault_access, - .fault.engine = tu102_fifo_fault_engine, - .fault.reason = gv100_fifo_fault_reason, - .fault.hubclient = gv100_fifo_fault_hubclient, - .fault.gpcclient = gv100_fifo_fault_gpcclient, - .runlist = &tu102_fifo_runlist, - .chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu102_fifo_gpfifo_new }, - .cgrp_force = true, -}; - static void tu102_fifo_recover_work(struct work_struct *w) { @@ -459,6 +444,20 @@ tu102_fifo_ = { .class_new = gk104_fifo_class_new, }; +static const struct gk104_fifo_func +tu102_fifo = { + .chid_nr = gm200_fifo_chid_nr, + .pbdma = &tu102_fifo_pbdma, + .fault.access = gv100_fifo_fault_access, + .fault.engine = tu102_fifo_fault_engine, + .fault.reason = gv100_fifo_fault_reason, + .fault.hubclient = gv100_fifo_fault_hubclient, + .fault.gpcclient = gv100_fifo_fault_gpcclient, + .runlist = &tu102_fifo_runlist, + .chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu102_fifo_gpfifo_new }, + .cgrp_force = true, +}; + int tu102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) @@ -471,5 +470,5 @@ tu102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, INIT_WORK(&fifo->recover.work, tu102_fifo_recover_work); *pfifo = &fifo->base; - return nvkm_fifo_ctor(&tu102_fifo_, device, type, inst, 4096, &fifo->base); + return nvkm_fifo_ctor(&tu102_fifo_, device, type, inst, &fifo->base); } -- cgit v1.2.3 From f5e4568991f60125712b03079bc037c6feb953f1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:21 +1000 Subject: drm/nouveau/fifo: unify handling of channel classes Adds the basic skeleton for common channel (group) interfaces. - common behaviour between =gk104 impl's - separates priv/user channel objects - passthrough to existing object for now, kludges removed later Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/class.h | 3 + drivers/gpu/drm/nouveau/include/nvkm/core/os.h | 4 + drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 43 ++--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h | 11 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 43 ++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 19 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c | 4 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c | 4 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c | 4 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c | 4 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 14 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 12 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 50 +----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 18 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 15 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 4 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c | 4 - .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 4 - .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 3 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 2 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c | 4 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 12 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 19 ++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 14 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 14 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 14 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 14 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 34 +++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 12 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 174 +++++++++++++++++++++ 36 files changed, 410 insertions(+), 191 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index a623fb67280b..e9d9f314a744 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -41,6 +41,7 @@ #define NVIF_CLASS_DISP_CHAN /* if0014.h */ 0x80000014 #define NVIF_CLASS_CHAN /* if0020.h */ 0x80000020 +#define NVIF_CLASS_CGRP /* if0021.h */ 0x80000021 /* the below match nvidia-assigned (either in hw, or sw) class numbers */ #define NV_NULL_CLASS 0x00000030 @@ -74,6 +75,8 @@ #define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e #define NV40_CHANNEL_DMA /* cl506b.h */ 0x0000406e +#define KEPLER_CHANNEL_GROUP_A /* if0021.h */ 0x0000a06c + #define NV50_CHANNEL_GPFIFO /* cl506f.h */ 0x0000506f #define G82_CHANNEL_GPFIFO /* cl826f.h */ 0x0000826f #define FERMI_CHANNEL_GPFIFO /* cl906f.h */ 0x0000906f diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h index 5a516b903fe9..e8705216ae4e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h @@ -35,4 +35,8 @@ nvkm_blob_dtor(struct nvkm_blob *blob) blob->size = 0; } +/*FIXME: remove after */ +#define nvkm_fifo_chan nvkm_chan +#define nvkm_fifo_chan_func nvkm_chan_func +#define nvkm_fifo_cgrp nvkm_cgrp #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 3cc7cfebfa5e..2f2059c5d4c9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -15,8 +15,9 @@ struct nvkm_fifo_engn { int usecount; }; -struct nvkm_fifo_chan { - const struct nvkm_fifo_chan_func *func; +struct nvkm_chan { + const struct nvkm_chan_func *func; + struct nvkm_fifo *fifo; u32 engm; struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index 8599063e8622..76d2bf1f6d8b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -33,3 +33,5 @@ nvkm-y += nvkm/engine/fifo/gpfifogf100.o nvkm-y += nvkm/engine/fifo/gpfifogk104.o nvkm-y += nvkm/engine/fifo/gpfifogv100.o nvkm-y += nvkm/engine/fifo/gpfifotu102.o + +nvkm-y += nvkm/engine/fifo/uchan.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index b11a4cb18fc7..06e47728e3a4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -155,27 +155,16 @@ nvkm_fifo_uevent(struct nvkm_fifo *fifo) } static int -nvkm_fifo_class_new_(struct nvkm_device *device, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nvkm_fifo_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, + void *argv, u32 argc, struct nvkm_object **pobject) { struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine); - return fifo->func->class_new(fifo, oclass, data, size, pobject); -} -static const struct nvkm_device_oclass -nvkm_fifo_class_ = { - .ctor = nvkm_fifo_class_new_, -}; + if (oclass->engn == &fifo->func->chan.user) + return nvkm_uchan_new(fifo, NULL, oclass, argv, argc, pobject); -static int -nvkm_fifo_class_new(struct nvkm_device *device, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - const struct nvkm_fifo_chan_oclass *sclass = oclass->engn; - struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine); - return sclass->ctor(fifo, oclass, data, size, pobject); + WARN_ON(1); + return -ENOSYS; } static const struct nvkm_device_oclass @@ -184,24 +173,20 @@ nvkm_fifo_class = { }; static int -nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, - const struct nvkm_device_oclass **class) +nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, const struct nvkm_device_oclass **class) { struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine); - const struct nvkm_fifo_chan_oclass *sclass; + const struct nvkm_fifo_func_chan *chan = &fifo->func->chan; int c = 0; - if (fifo->func->class_get) { - int ret = fifo->func->class_get(fifo, index, oclass); - if (ret == 0) - *class = &nvkm_fifo_class_; - return ret; - } + if (fifo->func->engine_id == gk104_fifo_engine_id) + chan = &gk104_fifo(fifo)->func->chan; - while ((sclass = fifo->func->chan[c])) { + /* *_CHANNEL_DMA, *_CHANNEL_GPFIFO_* */ + if (chan->user.oclass) { if (c++ == index) { - oclass->base = sclass->base; - oclass->engn = sclass; + oclass->base = chan->user; + oclass->engn = &fifo->func->chan.user; *class = &nvkm_fifo_class; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h index d0ac60b06720..9a677a1acf9b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h @@ -1,8 +1,11 @@ -#ifndef __NVKM_FIFO_CGRP_H__ -#define __NVKM_FIFO_CGRP_H__ -#include "priv.h" +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_CGRP_H__ +#define __NVKM_CGRP_H__ +#include -struct nvkm_fifo_cgrp { +struct nvkm_cgrp { + const struct nvkm_cgrp_func { + } *func; int id; struct list_head head; struct list_head chan; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 39d6b9217f8d..4d4905be4b92 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "chan.h" +#include "priv.h" #include #include @@ -140,7 +141,7 @@ nvkm_fifo_chan_child_func = { .fini[0] = nvkm_fifo_chan_child_fini, }; -static int +int nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) { @@ -258,11 +259,6 @@ nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct n struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); union nvif_chan_event_args *args = argv; - if (!uevent) - return 0; - if (argc != sizeof(args->v0) || args->v0.version != 0) - return -ENOSYS; - switch (args->v0.type) { case NVIF_CHAN_EVENT_V0_NON_STALL_INTR: return nvkm_uevent_add(uevent, &chan->fifo->uevent, 0, @@ -304,6 +300,18 @@ nvkm_fifo_chan_init(struct nvkm_object *object) return 0; } +void +nvkm_chan_del(struct nvkm_chan **pchan) +{ + struct nvkm_chan *chan = *pchan; + + if (!chan) + return; + + chan = nvkm_object_dtor(&chan->object); + kfree(chan); +} + static void * nvkm_fifo_chan_dtor(struct nvkm_object *object) { @@ -326,6 +334,7 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object) nvkm_gpuobj_del(&chan->push); nvkm_gpuobj_del(&chan->inst); + kfree(chan->func); return data; } @@ -340,20 +349,38 @@ nvkm_fifo_chan_func = { }; int -nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, +nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, struct nvkm_fifo *fifo, u32 size, u32 align, bool zero, u64 hvmm, u64 push, u32 engm, int bar, u32 base, u32 user, const struct nvkm_oclass *oclass, struct nvkm_fifo_chan *chan) { + struct nvkm_chan_func *func; struct nvkm_client *client = oclass->client; struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_dmaobj *dmaobj; unsigned long flags; int ret; - nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); + /*FIXME: temp kludge to ease transition, remove later */ + if (!(func = kmalloc(sizeof(*func), GFP_KERNEL))) + return -ENOMEM; + + *func = *fifo->func->chan.func; + func->dtor = fn->dtor; + func->init = fn->init; + func->fini = fn->fini; + func->engine_ctor = fn->engine_ctor; + func->engine_dtor = fn->engine_dtor; + func->engine_init = fn->engine_init; + func->engine_fini = fn->engine_fini; + func->object_ctor = fn->object_ctor; + func->object_dtor = fn->object_dtor; + func->submit_token = fn->submit_token; + chan->func = func; + + nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); chan->fifo = fifo; chan->engm = engm; INIT_LIST_HEAD(&chan->head); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 8ef972134f9b..24fbe6cf70e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -1,10 +1,10 @@ /* SPDX-License-Identifier: MIT */ -#ifndef __NVKM_FIFO_CHAN_H__ -#define __NVKM_FIFO_CHAN_H__ -#define nvkm_fifo_chan(p) container_of((p), struct nvkm_fifo_chan, object) -#include "priv.h" +#ifndef __NVKM_CHAN_H__ +#define __NVKM_CHAN_H__ +#define nvkm_chan(p) container_of((p), struct nvkm_chan, object) /*FIXME: remove later */ +#include -struct nvkm_fifo_chan_func { +struct nvkm_chan_func { void *(*dtor)(struct nvkm_fifo_chan *); void (*init)(struct nvkm_fifo_chan *); void (*fini)(struct nvkm_fifo_chan *); @@ -23,12 +23,7 @@ int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, u32 size, u32 align, bool zero, u64 vm, u64 push, u32 engm, int bar, u32 base, u32 user, const struct nvkm_oclass *, struct nvkm_fifo_chan *); +void nvkm_chan_del(struct nvkm_chan **); -struct nvkm_fifo_chan_oclass { - int (*ctor)(struct nvkm_fifo *, const struct nvkm_oclass *, - void *data, u32 size, struct nvkm_object **); - struct nvkm_sclass base; -}; - -int gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **); +int nvkm_fifo_chan_child_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c index dbcdc5fab990..d17d8c65d169 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -219,8 +218,5 @@ nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass = { - .base.oclass = NV03_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, .ctor = nv04_fifo_dma_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c index 07d80d54a07c..f45655072f9d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -90,8 +89,5 @@ nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, const struct nvkm_fifo_chan_oclass nv10_fifo_dma_oclass = { - .base.oclass = NV10_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, .ctor = nv10_fifo_dma_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c index edd70a114218..cd3f9f84ab9c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -91,8 +90,5 @@ nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, const struct nvkm_fifo_chan_oclass nv17_fifo_dma_oclass = { - .base.oclass = NV17_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, .ctor = nv17_fifo_dma_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c index 0411fb908457..c42c2e01d801 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -247,8 +246,5 @@ nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, const struct nvkm_fifo_chan_oclass nv40_fifo_dma_oclass = { - .base.oclass = NV40_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, .ctor = nv40_fifo_dma_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index c452388fd2a5..24732d355c83 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -21,9 +21,17 @@ * * Authors: Ben Skeggs */ +#include "chan.h" + #include "nv50.h" #include "channv50.h" +#include + +const struct nvkm_chan_func +g84_chan = { +}; + static void g84_fifo_uevent_fini(struct nvkm_fifo *fifo) { @@ -119,10 +127,8 @@ g84_fifo = { .start = nv04_fifo_start, .uevent_init = g84_fifo_uevent_init, .uevent_fini = g84_fifo_uevent_fini, - .chan = { - &g84_fifo_gpfifo_oclass, - NULL - }, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan, .oclass = &g84_fifo_gpfifo_oclass }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index e10c094c9a7d..25eda4fd2867 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -21,6 +21,8 @@ * * Authors: Ben Skeggs */ +#include "chan.h" + #include "gf100.h" #include "changf100.h" @@ -47,6 +49,10 @@ gf100_fifo_uevent_fini(struct nvkm_fifo *fifo) nvkm_mask(device, 0x002140, 0x80000000, 0x00000000); } +static const struct nvkm_chan_func +gf100_chan = { +}; + void gf100_fifo_runlist_commit(struct gf100_fifo *fifo) { @@ -678,10 +684,8 @@ gf100_fifo = { .id_engine = gf100_fifo_id_engine, .uevent_init = gf100_fifo_uevent_init, .uevent_fini = gf100_fifo_uevent_fini, - .chan = { - &gf100_fifo_gpfifo_oclass, - NULL - }, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan, .oclass = &gf100_fifo_gpfifo_oclass }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index e11b5eb8e196..1e15b88d59ae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -21,6 +21,8 @@ * * Authors: Ben Skeggs */ +#include "chan.h" + #include "gk104.h" #include "cgrp.h" #include "changk104.h" @@ -36,6 +38,10 @@ #include #include +static const struct nvkm_chan_func +gk104_chan = { +}; + void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, struct gk104_fifo_engine_status *status) @@ -83,45 +89,6 @@ gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, status->chan == &status->next ? "*" : " "); } -int -gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *argv, u32 argc, struct nvkm_object **pobject) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - if (oclass->engn == &fifo->func->chan) { - const struct gk104_fifo_chan_user *user = oclass->engn; - return user->ctor(fifo, oclass, argv, argc, pobject); - } else - if (oclass->engn == &fifo->func->user) { - const struct gk104_fifo_user_user *user = oclass->engn; - return user->ctor(oclass, argv, argc, pobject); - } - WARN_ON(1); - return -EINVAL; -} - -int -gk104_fifo_class_get(struct nvkm_fifo *base, int index, - struct nvkm_oclass *oclass) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - int c = 0; - - if (fifo->func->user.ctor && c++ == index) { - oclass->base = fifo->func->user.user; - oclass->engn = &fifo->func->user; - return 0; - } - - if (fifo->func->chan.ctor && c++ == index) { - oclass->base = fifo->func->chan.user; - oclass->engn = &fifo->func->chan; - return 0; - } - - return c; -} - void gk104_fifo_uevent_fini(struct nvkm_fifo *fifo) { @@ -1093,8 +1060,6 @@ gk104_fifo_ = { .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, - .class_get = gk104_fifo_class_get, - .class_new = gk104_fifo_class_new, }; int @@ -1245,7 +1210,8 @@ gk104_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .runlist = &gk104_fifo_runlist, - .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan, .ctor = &gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 5eca8c757966..be426734da02 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -76,18 +76,8 @@ struct gk104_fifo_func { struct nvkm_memory *, int entries); } *runlist; - struct gk104_fifo_user_user { - struct nvkm_sclass user; - int (*ctor)(const struct nvkm_oclass *, void *, u32, - struct nvkm_object **); - } user; - - struct gk104_fifo_chan_user { - struct nvkm_sclass user; - int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *, - void *, u32, struct nvkm_object **); - } chan; - bool cgrp_force; + struct nvkm_fifo_func_cgrp cgrp; + struct nvkm_fifo_func_chan chan; }; struct gk104_fifo_engine_status { @@ -121,10 +111,6 @@ int gk104_fifo_oneinit(struct nvkm_fifo *base); int gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data); void gk104_fifo_init(struct nvkm_fifo *base); void gk104_fifo_fini(struct nvkm_fifo *base); -int gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *argv, u32 argc, struct nvkm_object **pobject); -int gk104_fifo_class_get(struct nvkm_fifo *base, int index, - struct nvkm_oclass *oclass); void gk104_fifo_uevent_fini(struct nvkm_fifo *fifo); void gk104_fifo_uevent_init(struct nvkm_fifo *fifo); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 047e128febd1..df9b83cf382f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -21,14 +21,24 @@ * * Authors: Ben Skeggs */ -#include "gk104.h" #include "cgrp.h" +#include "chan.h" + +#include "gk104.h" #include "changk104.h" #include #include +const struct nvkm_chan_func +gk110_chan = { +}; + +const struct nvkm_cgrp_func +gk110_cgrp = { +}; + void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp, struct nvkm_memory *memory, u32 offset) @@ -57,7 +67,8 @@ gk110_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .runlist = &gk110_fifo_runlist, - .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_B}, gk104_fifo_gpfifo_new }, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 89b9c4fa35cc..003f244f89db 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -60,7 +60,8 @@ gk208_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .runlist = &gk110_fifo_runlist, - .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 48cdcf9a4a72..661c9f0cf7b9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -35,7 +35,8 @@ gk20a_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .runlist = &gk110_fifo_runlist, - .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, + .cgrp = {{ }, &gk110_cgrp }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 7b4244f184d2..910d97911a98 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -21,6 +21,8 @@ * * Authors: Ben Skeggs */ +#include "priv.h" +#include "chan.h" #include "gk104.h" #include "changk104.h" @@ -29,6 +31,10 @@ #include +const struct nvkm_chan_func +gm107_chan = { +}; + static void gm107_fifo_runlist_chan(struct gk104_fifo_chan *chan, struct nvkm_memory *memory, u32 offset) @@ -109,7 +115,8 @@ gm107_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .runlist = &gm107_fifo_runlist, - .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_B}, gk104_fifo_gpfifo_new }, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 17836a383c76..101027536a93 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -57,7 +57,8 @@ gm200_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .runlist = &gm107_fifo_runlist, - .chan = {{0,0,MAXWELL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, + .chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 7a1ac3d863ec..c52a4a0b361b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -87,8 +87,8 @@ gp100_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .runlist = &gm107_fifo_runlist, - .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, - .cgrp_force = true, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, + .chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c index 2121f517b1dd..3157a7633231 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -88,8 +87,5 @@ g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass = { - .base.oclass = G82_CHANNEL_GPFIFO, - .base.minver = 0, - .base.maxver = 0, .ctor = g84_fifo_gpfifo_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 4b1f6702680a..5d6e3a7b8f1e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -283,8 +282,5 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass = { - .base.oclass = FERMI_CHANNEL_GPFIFO, - .base.minver = 0, - .base.maxver = 0, .ctor = gf100_fifo_gpfifo_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index ea9852a5fdd8..6415e80a1fbf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -287,7 +286,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, /* Hack to support GPUs where even individual channels should be * part of a channel group. */ - if (fifo->func->cgrp_force) { + if (fifo->func->cgrp.force) { if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL))) return -ENOMEM; chan->cgrp->id = chan->base.chid; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index e8546fed4024..34a8e792c0e8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -168,7 +168,7 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, /* Hack to support GPUs where even individual channels should be * part of a channel group. */ - if (fifo->func->cgrp_force) { + if (fifo->func->cgrp.force) { if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL))) return -ENOMEM; chan->cgrp->id = chan->base.chid; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c index d8f28ec1e4a8..410fc9e6c1f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -86,8 +85,5 @@ nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass = { - .base.oclass = NV50_CHANNEL_GPFIFO, - .base.minver = 0, - .base.maxver = 0, .ctor = nv50_fifo_gpfifo_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 0be50120476f..ddca29852865 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -19,14 +19,20 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "gk104.h" +#include "chan.h" #include "cgrp.h" + +#include "gk104.h" #include "changk104.h" #include #include +static const struct nvkm_chan_func +gv100_chan = { +}; + void gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan, struct nvkm_memory *memory, u32 offset) @@ -295,8 +301,8 @@ gv100_fifo = { .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, .runlist = &gv100_fifo_runlist, - .chan = {{ 0, 0,VOLTA_CHANNEL_GPFIFO_A}, gv100_fifo_gpfifo_new }, - .cgrp_force = true, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, + .chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan, .ctor = gv100_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index e4b4133be3a4..95a30fbf65a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -21,6 +21,9 @@ * * Authors: Ben Skeggs */ +#include "cgrp.h" +#include "chan.h" + #include "nv04.h" #include "channv04.h" #include "regsnv04.h" @@ -31,6 +34,8 @@ #include #include +#include + static const struct nv04_fifo_ramfc nv04_fifo_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, @@ -44,6 +49,14 @@ nv04_fifo_ramfc[] = { {} }; +static const struct nvkm_chan_func +nv04_chan = { +}; + +const struct nvkm_cgrp_func +nv04_cgrp = { +}; + void nv04_fifo_pause(struct nvkm_fifo *base, unsigned long *pflags) __acquires(fifo->base.lock) @@ -392,10 +405,8 @@ nv04_fifo = { .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, - .chan = { - &nv04_fifo_dma_oclass, - NULL - }, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, NV03_CHANNEL_DMA }, &nv04_chan, .oclass = &nv04_fifo_dma_oclass }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index 94ad6ee19297..f07304e4b8c5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -21,10 +21,14 @@ * * Authors: Ben Skeggs */ +#include "chan.h" + #include "nv04.h" #include "channv04.h" #include "regsnv04.h" +#include + static const struct nv04_fifo_ramfc nv10_fifo_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, @@ -39,6 +43,10 @@ nv10_fifo_ramfc[] = { {} }; +static const struct nvkm_chan_func +nv10_chan = { +}; + int nv10_fifo_chid_nr(struct nvkm_fifo *fifo) { @@ -54,10 +62,8 @@ nv10_fifo = { .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, - .chan = { - &nv10_fifo_dma_oclass, - NULL - }, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, NV10_CHANNEL_DMA }, &nv10_chan, .oclass = &nv10_fifo_dma_oclass }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index 23d320362c86..858c8ba158c9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -21,6 +21,8 @@ * * Authors: Ben Skeggs */ +#include "chan.h" + #include "nv04.h" #include "channv04.h" #include "regsnv04.h" @@ -28,6 +30,8 @@ #include #include +#include + static const struct nv04_fifo_ramfc nv17_fifo_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, @@ -47,6 +51,10 @@ nv17_fifo_ramfc[] = { {} }; +static const struct nvkm_chan_func +nv17_chan = { +}; + static void nv17_fifo_init(struct nvkm_fifo *base) { @@ -86,10 +94,8 @@ nv17_fifo = { .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, - .chan = { - &nv17_fifo_dma_oclass, - NULL - }, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, NV17_CHANNEL_DMA }, &nv17_chan, .oclass = &nv17_fifo_dma_oclass }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index 01e75c80b4f3..30f924e3da3c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -21,6 +21,8 @@ * * Authors: Ben Skeggs */ +#include "chan.h" + #include "nv04.h" #include "channv04.h" #include "regsnv04.h" @@ -29,6 +31,8 @@ #include #include +#include + static const struct nv04_fifo_ramfc nv40_fifo_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, @@ -56,6 +60,10 @@ nv40_fifo_ramfc[] = { {} }; +static const struct nvkm_chan_func +nv40_chan = { +}; + static void nv40_fifo_init(struct nvkm_fifo *base) { @@ -117,10 +125,8 @@ nv40_fifo = { .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, - .chan = { - &nv40_fifo_dma_oclass, - NULL - }, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, NV40_CHANNEL_DMA }, &nv40_chan, .oclass = &nv40_fifo_dma_oclass }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 9d0cfb856401..f3f11a324591 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -21,11 +21,19 @@ * * Authors: Ben Skeggs */ +#include "chan.h" + #include "nv50.h" #include "channv50.h" #include +#include + +static const struct nvkm_chan_func +nv50_chan = { +}; + static void nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo) { @@ -142,10 +150,8 @@ nv50_fifo = { .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, - .chan = { - &nv50_fifo_gpfifo_oclass, - NULL - }, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, NV50_CHANNEL_GPFIFO }, &nv50_chan, .oclass = &nv50_fifo_gpfifo_oclass }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 66e93609c3c7..b8031c212c8b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -3,6 +3,8 @@ #define __NVKM_FIFO_PRIV_H__ #define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine) #include +struct nvkm_cgrp; +struct gk104_fifo; void nvkm_fifo_uevent(struct nvkm_fifo *); void nvkm_fifo_kevent(struct nvkm_fifo *, int chid); @@ -30,10 +32,23 @@ struct nvkm_fifo_func { void (*uevent_init)(struct nvkm_fifo *); void (*uevent_fini)(struct nvkm_fifo *); void (*recover_chan)(struct nvkm_fifo *, int chid); - int (*class_get)(struct nvkm_fifo *, int index, struct nvkm_oclass *); - int (*class_new)(struct nvkm_fifo *, const struct nvkm_oclass *, - void *, u32, struct nvkm_object **); - const struct nvkm_fifo_chan_oclass *chan[]; + + struct nvkm_fifo_func_cgrp { + struct nvkm_sclass user; + const struct nvkm_cgrp_func *func; + bool force; + } cgrp; + + struct nvkm_fifo_func_chan { + struct nvkm_sclass user; + const struct nvkm_chan_func *func; + const struct nvkm_fifo_chan_oclass { + int (*ctor)(struct nvkm_fifo *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); + } *oclass; + int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *, void *, u32, + struct nvkm_object **); + } chan; }; int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, @@ -44,16 +59,27 @@ int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *nv04_fifo_id_engine(struct nvkm_fifo *, int); void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); +extern const struct nvkm_cgrp_func nv04_cgrp; int nv10_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_nr(struct nvkm_fifo *); +extern const struct nvkm_chan_func g84_chan; + void gf100_fifo_intr_fault(struct nvkm_fifo *, int); int gk104_fifo_chid_nr(struct nvkm_fifo *); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int); +extern const struct nvkm_cgrp_func gk110_cgrp; +extern const struct nvkm_chan_func gk110_chan; + +extern const struct nvkm_chan_func gm107_chan; + int gm200_fifo_chid_nr(struct nvkm_fifo *); + +int nvkm_uchan_new(struct nvkm_fifo *, struct nvkm_cgrp *, const struct nvkm_oclass *, + void *argv, u32 argc, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 63a3a2c0a824..db9b802bd67c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -19,6 +19,8 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ +#include "chan.h" + #include "gk104.h" #include "cgrp.h" #include "changk104.h" @@ -31,6 +33,10 @@ #include +static const struct nvkm_chan_func +tu102_chan = { +}; + static void tu102_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, struct nvkm_memory *mem, int nr) @@ -440,8 +446,6 @@ tu102_fifo_ = { .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = tu102_fifo_recover_chan, - .class_get = gk104_fifo_class_get, - .class_new = gk104_fifo_class_new, }; static const struct gk104_fifo_func @@ -454,8 +458,8 @@ tu102_fifo = { .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, .runlist = &tu102_fifo_runlist, - .chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu102_fifo_gpfifo_new }, - .cgrp_force = true, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, + .chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan, .ctor = tu102_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c new file mode 100644 index 000000000000..a1d93f28b634 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -0,0 +1,174 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#define nvkm_uchan(p) container_of((p), struct nvkm_uchan, object) +#include "cgrp.h" +#include "chan.h" + +#include + +#include + +#include "gk104.h" + +struct nvkm_uchan { + struct nvkm_object object; + struct nvkm_chan *chan; +}; + +static int +nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) +{ + struct nvkm_chan *chan = nvkm_uchan(object)->chan; + union nvif_chan_event_args *args = argv; + + if (!uevent) + return 0; + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + switch (args->v0.type) { + case NVIF_CHAN_EVENT_V0_NON_STALL_INTR: + case NVIF_CHAN_EVENT_V0_KILLED: + return chan->object.func->uevent(&chan->object, argv, argc, uevent); + default: + break; + } + + return -ENOSYS; +} + +struct nvkm_uobj { + struct nvkm_oproxy oproxy; + struct nvkm_chan *chan; +}; + +static const struct nvkm_oproxy_func +nvkm_uchan_object = { +}; + +static int +nvkm_uchan_object_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_chan *chan = nvkm_uchan(oclass->parent)->chan; + struct nvkm_uobj *uobj; + struct nvkm_oclass _oclass; + + if (!(uobj = kzalloc(sizeof(*uobj), GFP_KERNEL))) + return -ENOMEM; + + nvkm_oproxy_ctor(&nvkm_uchan_object, oclass, &uobj->oproxy); + uobj->chan = chan; + *pobject = &uobj->oproxy.base; + + _oclass = *oclass; + _oclass.parent = &chan->object; + return nvkm_fifo_chan_child_new(&_oclass, argv, argc, &uobj->oproxy.object); +} + +static int +nvkm_uchan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass) +{ + struct nvkm_chan *chan = nvkm_uchan(object)->chan; + int ret; + + ret = chan->object.func->sclass(&chan->object, index, oclass); + if (ret) + return ret; + + oclass->ctor = nvkm_uchan_object_new; + return 0; +} + +static int +nvkm_uchan_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct nvkm_chan *chan = nvkm_uchan(object)->chan; + + return chan->object.func->map(&chan->object, argv, argc, type, addr, size); +} + +static int +nvkm_uchan_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_chan *chan = nvkm_uchan(object)->chan; + int ret; + + ret = chan->object.func->fini(&chan->object, suspend); + if (ret && suspend) + return ret; + + return 0; +} + +static int +nvkm_uchan_init(struct nvkm_object *object) +{ + struct nvkm_chan *chan = nvkm_uchan(object)->chan; + + return chan->object.func->init(&chan->object); +} + +static void * +nvkm_uchan_dtor(struct nvkm_object *object) +{ + struct nvkm_uchan *uchan = nvkm_uchan(object); + + nvkm_chan_del(&uchan->chan); + return uchan; +} + +static const struct nvkm_object_func +nvkm_uchan = { + .dtor = nvkm_uchan_dtor, + .init = nvkm_uchan_init, + .fini = nvkm_uchan_fini, + .map = nvkm_uchan_map, + .sclass = nvkm_uchan_sclass, + .uevent = nvkm_uchan_uevent, +}; + +int +nvkm_uchan_new(struct nvkm_fifo *fifo, struct nvkm_cgrp *cgrp, const struct nvkm_oclass *oclass, + void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_object *object = NULL; + struct nvkm_uchan *uchan; + int ret; + + if (!(uchan = kzalloc(sizeof(*uchan), GFP_KERNEL))) + return -ENOMEM; + + nvkm_object_ctor(&nvkm_uchan, oclass, &uchan->object); + *pobject = &uchan->object; + + if (!fifo->func->chan.func) + ret = gk104_fifo(fifo)->func->chan.ctor(gk104_fifo(fifo), oclass, argv, argc, &object); + else + ret = fifo->func->chan.oclass->ctor(fifo, oclass, argv, argc, &object); + if (!object) + return ret; + + uchan->chan = container_of(object, typeof(*uchan->chan), object); + return ret; +} -- cgit v1.2.3 From fd67738a28bf51a8113c0d1cc8f31d4f2f3776e0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:22 +1000 Subject: drm/nouveau/fifo: pre-move some blocks of code around - will make subsequent patches more obvious - no code changes Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 16 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c | 66 --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 172 ++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 448 ++++++++++----------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 66 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 32 +- 6 files changed, 400 insertions(+), 400 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 06e47728e3a4..b06db3b3d471 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -211,6 +211,14 @@ nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend) return 0; } +static int +nvkm_fifo_init(struct nvkm_engine *engine) +{ + struct nvkm_fifo *fifo = nvkm_fifo(engine); + fifo->func->init(fifo); + return 0; +} + static int nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data) { @@ -240,14 +248,6 @@ nvkm_fifo_preinit(struct nvkm_engine *engine) nvkm_mc_reset(engine->subdev.device, NVKM_ENGINE_FIFO, 0); } -static int -nvkm_fifo_init(struct nvkm_engine *engine) -{ - struct nvkm_fifo *fifo = nvkm_fifo(engine); - fifo->func->init(fifo); - return 0; -} - static void * nvkm_fifo_dtor(struct nvkm_engine *engine) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c index d17d8c65d169..ed2ae9e69987 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c @@ -69,72 +69,6 @@ nv04_fifo_dma_object_ctor(struct nvkm_fifo_chan *base, return hash; } -void -nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nv04_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_memory *fctx = device->imem->ramfc; - const struct nv04_fifo_ramfc *c; - unsigned long flags; - u32 mask = fifo->base.nr - 1; - u32 data = chan->ramfc; - u32 chid; - - /* prevent fifo context switches */ - spin_lock_irqsave(&fifo->base.lock, flags); - nvkm_wr32(device, NV03_PFIFO_CACHES, 0); - - /* if this channel is active, replace it with a null context */ - chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & mask; - if (chid == chan->base.chid) { - nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0); - nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); - - c = fifo->ramfc; - nvkm_kmap(fctx); - do { - u32 rm = ((1ULL << c->bits) - 1) << c->regs; - u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; - u32 rv = (nvkm_rd32(device, c->regp) & rm) >> c->regs; - u32 cv = (nvkm_ro32(fctx, c->ctxp + data) & ~cm); - nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs)); - } while ((++c)->bits); - nvkm_done(fctx); - - c = fifo->ramfc; - do { - nvkm_wr32(device, c->regp, 0x00000000); - } while ((++c)->bits); - - nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0); - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0); - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, mask); - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1); - nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); - } - - /* restore normal operation, after disabling dma mode */ - nvkm_mask(device, NV04_PFIFO_MODE, 1 << chan->base.chid, 0); - nvkm_wr32(device, NV03_PFIFO_CACHES, 1); - spin_unlock_irqrestore(&fifo->base.lock, flags); -} - -void -nv04_fifo_dma_init(struct nvkm_fifo_chan *base) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nv04_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 mask = 1 << chan->base.chid; - unsigned long flags; - spin_lock_irqsave(&fifo->base.lock, flags); - nvkm_mask(device, NV04_PFIFO_MODE, mask, mask); - spin_unlock_irqrestore(&fifo->base.lock, flags); -} - void * nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 25eda4fd2867..bd0b0c66e28f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -53,6 +53,52 @@ static const struct nvkm_chan_func gf100_chan = { }; +static const struct nvkm_bitfield +gf100_fifo_pbdma_intr[] = { +/* { 0x00008000, "" } seen with null ib push */ + { 0x00200000, "ILLEGAL_MTHD" }, + { 0x00800000, "EMPTY_SUBC" }, + {} +}; + +static void +gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit) +{ + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000)); + u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000)); + u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000)); + u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f; + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00003ffc); + struct nvkm_fifo_chan *chan; + unsigned long flags; + u32 show = stat; + char msg[128]; + + if (stat & 0x00800000) { + if (device->sw) { + if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data)) + show &= ~0x00800000; + } + } + + if (show) { + nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show); + chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); + nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] " + "subc %d mthd %04x data %08x\n", + unit, show, msg, chid, chan ? chan->inst->addr : 0, + chan ? chan->object.client->name : "unknown", + subc, mthd, data); + nvkm_fifo_chan_put(&fifo->base, flags, &chan); + } + + nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008); + nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); +} + void gf100_fifo_runlist_commit(struct gf100_fifo *fifo) { @@ -399,52 +445,6 @@ gf100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) nvkm_fifo_fault(fifo, &info); } -static const struct nvkm_bitfield -gf100_fifo_pbdma_intr[] = { -/* { 0x00008000, "" } seen with null ib push */ - { 0x00200000, "ILLEGAL_MTHD" }, - { 0x00800000, "EMPTY_SUBC" }, - {} -}; - -static void -gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000)); - u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000)); - u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000)); - u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f; - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00003ffc); - struct nvkm_fifo_chan *chan; - unsigned long flags; - u32 show= stat; - char msg[128]; - - if (stat & 0x00800000) { - if (device->sw) { - if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data)) - show &= ~0x00800000; - } - } - - if (show) { - nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show); - chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); - nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] " - "subc %d mthd %04x data %08x\n", - unit, show, msg, chid, chan ? chan->inst->addr : 0, - chan ? chan->object.client->name : "unknown", - subc, mthd, data); - nvkm_fifo_chan_put(&fifo->base, flags, &chan); - } - - nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008); - nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); -} - static void gf100_fifo_intr_runlist(struct gf100_fifo *fifo) { @@ -576,46 +576,6 @@ gf100_fifo_intr(struct nvkm_fifo *base) } } -static int -gf100_fifo_oneinit(struct nvkm_fifo *base) -{ - struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); - int ret; - - /* Determine number of PBDMAs by checking valid enable bits. */ - nvkm_wr32(device, 0x002204, 0xffffffff); - fifo->pbdma_nr = hweight32(nvkm_rd32(device, 0x002204)); - nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr); - - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, - false, &fifo->runlist.mem[0]); - if (ret) - return ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, - false, &fifo->runlist.mem[1]); - if (ret) - return ret; - - init_waitqueue_head(&fifo->runlist.wait); - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000, - 0x1000, false, &fifo->user.mem); - if (ret) - return ret; - - ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem), - &fifo->user.bar); - if (ret) - return ret; - - return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0); -} - static void gf100_fifo_fini(struct nvkm_fifo *base) { @@ -659,6 +619,46 @@ gf100_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */ } +static int +gf100_fifo_oneinit(struct nvkm_fifo *base) +{ + struct gf100_fifo *fifo = gf100_fifo(base); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); + int ret; + + /* Determine number of PBDMAs by checking valid enable bits. */ + nvkm_wr32(device, 0x002204, 0xffffffff); + fifo->pbdma_nr = hweight32(nvkm_rd32(device, 0x002204)); + nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr); + + + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, + false, &fifo->runlist.mem[0]); + if (ret) + return ret; + + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, + false, &fifo->runlist.mem[1]); + if (ret) + return ret; + + init_waitqueue_head(&fifo->runlist.wait); + + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000, + 0x1000, false, &fifo->user.mem); + if (ret) + return ret; + + ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem), + &fifo->user.bar); + if (ret) + return ret; + + return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0); +} + static void * gf100_fifo_dtor(struct nvkm_fifo *base) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 1e15b88d59ae..da26c5219e53 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -103,6 +103,70 @@ gk104_fifo_uevent_init(struct nvkm_fifo *fifo) nvkm_mask(device, 0x002140, 0x80000000, 0x80000000); } +static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = { + { 0x00000001, "HCE_RE_ILLEGAL_OP" }, + { 0x00000002, "HCE_RE_ALIGNB" }, + { 0x00000004, "HCE_PRIV" }, + { 0x00000008, "HCE_ILLEGAL_MTHD" }, + { 0x00000010, "HCE_ILLEGAL_CLASS" }, + {} +}; + +void +gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit) +{ + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 mask = nvkm_rd32(device, 0x04014c + (unit * 0x2000)); + u32 stat = nvkm_rd32(device, 0x040148 + (unit * 0x2000)) & mask; + u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff; + char msg[128]; + + if (stat) { + nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_1, stat); + nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n", + unit, stat, msg, chid, + nvkm_rd32(device, 0x040150 + (unit * 0x2000)), + nvkm_rd32(device, 0x040154 + (unit * 0x2000))); + } + + nvkm_wr32(device, 0x040148 + (unit * 0x2000), stat); +} + +static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { + { 0x00000001, "MEMREQ" }, + { 0x00000002, "MEMACK_TIMEOUT" }, + { 0x00000004, "MEMACK_EXTRA" }, + { 0x00000008, "MEMDAT_TIMEOUT" }, + { 0x00000010, "MEMDAT_EXTRA" }, + { 0x00000020, "MEMFLUSH" }, + { 0x00000040, "MEMOP" }, + { 0x00000080, "LBCONNECT" }, + { 0x00000100, "LBREQ" }, + { 0x00000200, "LBACK_TIMEOUT" }, + { 0x00000400, "LBACK_EXTRA" }, + { 0x00000800, "LBDAT_TIMEOUT" }, + { 0x00001000, "LBDAT_EXTRA" }, + { 0x00002000, "GPFIFO" }, + { 0x00004000, "GPPTR" }, + { 0x00008000, "GPENTRY" }, + { 0x00010000, "GPCRC" }, + { 0x00020000, "PBPTR" }, + { 0x00040000, "PBENTRY" }, + { 0x00080000, "PBCRC" }, + { 0x00100000, "XBARCONNECT" }, + { 0x00200000, "METHOD" }, + { 0x00400000, "METHODCRC" }, + { 0x00800000, "DEVICE" }, + { 0x02000000, "SEMAPHORE" }, + { 0x04000000, "ACQUIRE" }, + { 0x08000000, "PRI" }, + { 0x20000000, "NO_CTXSW_SEG" }, + { 0x40000000, "PBSEG" }, + { 0x80000000, "SIGNATURE" }, + {} +}; + void gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, struct nvkm_memory *mem, int nr) @@ -443,6 +507,128 @@ gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn) schedule_work(&fifo->recover.work); } +const struct nvkm_enum +gk104_fifo_fault_access[] = { + { 0x0, "READ" }, + { 0x1, "WRITE" }, + {} +}; + +const struct nvkm_enum +gk104_fifo_fault_engine[] = { + { 0x00, "GR", NULL, NVKM_ENGINE_GR }, + { 0x01, "DISPLAY" }, + { 0x02, "CAPTURE" }, + { 0x03, "IFB", NULL, NVKM_ENGINE_IFB }, + { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, + { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, + { 0x06, "SCHED" }, + { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO }, + { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO }, + { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO }, + { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO }, + { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO }, + { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO }, + { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO }, + { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO }, + { 0x0f, "HOSTSR" }, + { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD }, + { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP }, + { 0x13, "PERF" }, + { 0x14, "MSPDEC", NULL, NVKM_ENGINE_MSPDEC }, + { 0x15, "CE0", NULL, NVKM_ENGINE_CE, 0 }, + { 0x16, "CE1", NULL, NVKM_ENGINE_CE, 1 }, + { 0x17, "PMU" }, + { 0x18, "PTP" }, + { 0x19, "MSENC", NULL, NVKM_ENGINE_MSENC }, + { 0x1b, "CE2", NULL, NVKM_ENGINE_CE, 2 }, + {} +}; + +const struct nvkm_enum +gk104_fifo_fault_reason[] = { + { 0x00, "PDE" }, + { 0x01, "PDE_SIZE" }, + { 0x02, "PTE" }, + { 0x03, "VA_LIMIT_VIOLATION" }, + { 0x04, "UNBOUND_INST_BLOCK" }, + { 0x05, "PRIV_VIOLATION" }, + { 0x06, "RO_VIOLATION" }, + { 0x07, "WO_VIOLATION" }, + { 0x08, "PITCH_MASK_VIOLATION" }, + { 0x09, "WORK_CREATION" }, + { 0x0a, "UNSUPPORTED_APERTURE" }, + { 0x0b, "COMPRESSION_FAILURE" }, + { 0x0c, "UNSUPPORTED_KIND" }, + { 0x0d, "REGION_VIOLATION" }, + { 0x0e, "BOTH_PTES_VALID" }, + { 0x0f, "INFO_TYPE_POISONED" }, + {} +}; + +const struct nvkm_enum +gk104_fifo_fault_hubclient[] = { + { 0x00, "VIP" }, + { 0x01, "CE0" }, + { 0x02, "CE1" }, + { 0x03, "DNISO" }, + { 0x04, "FE" }, + { 0x05, "FECS" }, + { 0x06, "HOST" }, + { 0x07, "HOST_CPU" }, + { 0x08, "HOST_CPU_NB" }, + { 0x09, "ISO" }, + { 0x0a, "MMU" }, + { 0x0b, "MSPDEC" }, + { 0x0c, "MSPPP" }, + { 0x0d, "MSVLD" }, + { 0x0e, "NISO" }, + { 0x0f, "P2P" }, + { 0x10, "PD" }, + { 0x11, "PERF" }, + { 0x12, "PMU" }, + { 0x13, "RASTERTWOD" }, + { 0x14, "SCC" }, + { 0x15, "SCC_NB" }, + { 0x16, "SEC" }, + { 0x17, "SSYNC" }, + { 0x18, "GR_CE" }, + { 0x19, "CE2" }, + { 0x1a, "XV" }, + { 0x1b, "MMU_NB" }, + { 0x1c, "MSENC" }, + { 0x1d, "DFALCON" }, + { 0x1e, "SKED" }, + { 0x1f, "AFALCON" }, + {} +}; + +const struct nvkm_enum +gk104_fifo_fault_gpcclient[] = { + { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" }, + { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" }, + { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" }, + { 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" }, + { 0x0c, "RAST" }, + { 0x0d, "GCC" }, + { 0x0e, "GPCCS" }, + { 0x0f, "PROP_0" }, + { 0x10, "PROP_1" }, + { 0x11, "PROP_2" }, + { 0x12, "PROP_3" }, + { 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" }, + { 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" }, + { 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" }, + { 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" }, + { 0x1f, "GPM" }, + { 0x20, "LTP_UTLB_0" }, + { 0x21, "LTP_UTLB_1" }, + { 0x22, "LTP_UTLB_2" }, + { 0x23, "LTP_UTLB_3" }, + { 0x24, "GPC_RGG_UTLB" }, + {} +}; + static void gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) { @@ -624,40 +810,6 @@ gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo) nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat); } -static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { - { 0x00000001, "MEMREQ" }, - { 0x00000002, "MEMACK_TIMEOUT" }, - { 0x00000004, "MEMACK_EXTRA" }, - { 0x00000008, "MEMDAT_TIMEOUT" }, - { 0x00000010, "MEMDAT_EXTRA" }, - { 0x00000020, "MEMFLUSH" }, - { 0x00000040, "MEMOP" }, - { 0x00000080, "LBCONNECT" }, - { 0x00000100, "LBREQ" }, - { 0x00000200, "LBACK_TIMEOUT" }, - { 0x00000400, "LBACK_EXTRA" }, - { 0x00000800, "LBDAT_TIMEOUT" }, - { 0x00001000, "LBDAT_EXTRA" }, - { 0x00002000, "GPFIFO" }, - { 0x00004000, "GPPTR" }, - { 0x00008000, "GPENTRY" }, - { 0x00010000, "GPCRC" }, - { 0x00020000, "PBPTR" }, - { 0x00040000, "PBENTRY" }, - { 0x00080000, "PBCRC" }, - { 0x00100000, "XBARCONNECT" }, - { 0x00200000, "METHOD" }, - { 0x00400000, "METHODCRC" }, - { 0x00800000, "DEVICE" }, - { 0x02000000, "SEMAPHORE" }, - { 0x04000000, "ACQUIRE" }, - { 0x08000000, "PRI" }, - { 0x20000000, "NO_CTXSW_SEG" }, - { 0x40000000, "PBSEG" }, - { 0x80000000, "SIGNATURE" }, - {} -}; - void gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit) { @@ -698,36 +850,6 @@ gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit) nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); } -static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = { - { 0x00000001, "HCE_RE_ILLEGAL_OP" }, - { 0x00000002, "HCE_RE_ALIGNB" }, - { 0x00000004, "HCE_PRIV" }, - { 0x00000008, "HCE_ILLEGAL_MTHD" }, - { 0x00000010, "HCE_ILLEGAL_CLASS" }, - {} -}; - -void -gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 mask = nvkm_rd32(device, 0x04014c + (unit * 0x2000)); - u32 stat = nvkm_rd32(device, 0x040148 + (unit * 0x2000)) & mask; - u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff; - char msg[128]; - - if (stat) { - nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_1, stat); - nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n", - unit, stat, msg, chid, - nvkm_rd32(device, 0x040150 + (unit * 0x2000)), - nvkm_rd32(device, 0x040154 + (unit * 0x2000))); - } - - nvkm_wr32(device, 0x040148 + (unit * 0x2000), stat); -} - void gk104_fifo_intr_runlist(struct gk104_fifo *fifo) { @@ -899,6 +1021,44 @@ gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data) } } +void +gk104_fifo_init(struct nvkm_fifo *base) +{ + struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + int i; + + /* Enable PBDMAs. */ + fifo->func->pbdma->init(fifo); + + /* PBDMA[n] */ + for (i = 0; i < fifo->pbdma_nr; i++) { + nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ + } + + /* PBDMA[n].HCE */ + for (i = 0; i < fifo->pbdma_nr; i++) { + nvkm_wr32(device, 0x040148 + (i * 0x2000), 0xffffffff); /* INTR */ + nvkm_wr32(device, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */ + } + + nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); + + if (fifo->func->pbdma->init_timeout) + fifo->func->pbdma->init_timeout(fifo); + + nvkm_wr32(device, 0x002100, 0xffffffff); + nvkm_wr32(device, 0x002140, 0x7fffffff); +} + +int +gk104_fifo_chid_nr(struct nvkm_fifo *fifo) +{ + return 4096; +} + int gk104_fifo_oneinit(struct nvkm_fifo *base) { @@ -990,44 +1150,6 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0); } -void -gk104_fifo_init(struct nvkm_fifo *base) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; - int i; - - /* Enable PBDMAs. */ - fifo->func->pbdma->init(fifo); - - /* PBDMA[n] */ - for (i = 0; i < fifo->pbdma_nr; i++) { - nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ - } - - /* PBDMA[n].HCE */ - for (i = 0; i < fifo->pbdma_nr; i++) { - nvkm_wr32(device, 0x040148 + (i * 0x2000), 0xffffffff); /* INTR */ - nvkm_wr32(device, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */ - } - - nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); - - if (fifo->func->pbdma->init_timeout) - fifo->func->pbdma->init_timeout(fifo); - - nvkm_wr32(device, 0x002100, 0xffffffff); - nvkm_wr32(device, 0x002140, 0x7fffffff); -} - -int -gk104_fifo_chid_nr(struct nvkm_fifo *fifo) -{ - return 4096; -} - void * gk104_fifo_dtor(struct nvkm_fifo *base) { @@ -1077,128 +1199,6 @@ gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device, return nvkm_fifo_ctor(&gk104_fifo_, device, type, inst, &fifo->base); } -const struct nvkm_enum -gk104_fifo_fault_access[] = { - { 0x0, "READ" }, - { 0x1, "WRITE" }, - {} -}; - -const struct nvkm_enum -gk104_fifo_fault_engine[] = { - { 0x00, "GR", NULL, NVKM_ENGINE_GR }, - { 0x01, "DISPLAY" }, - { 0x02, "CAPTURE" }, - { 0x03, "IFB", NULL, NVKM_ENGINE_IFB }, - { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, - { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, - { 0x06, "SCHED" }, - { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO }, - { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO }, - { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO }, - { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO }, - { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO }, - { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO }, - { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO }, - { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO }, - { 0x0f, "HOSTSR" }, - { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD }, - { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP }, - { 0x13, "PERF" }, - { 0x14, "MSPDEC", NULL, NVKM_ENGINE_MSPDEC }, - { 0x15, "CE0", NULL, NVKM_ENGINE_CE, 0 }, - { 0x16, "CE1", NULL, NVKM_ENGINE_CE, 1 }, - { 0x17, "PMU" }, - { 0x18, "PTP" }, - { 0x19, "MSENC", NULL, NVKM_ENGINE_MSENC }, - { 0x1b, "CE2", NULL, NVKM_ENGINE_CE, 2 }, - {} -}; - -const struct nvkm_enum -gk104_fifo_fault_reason[] = { - { 0x00, "PDE" }, - { 0x01, "PDE_SIZE" }, - { 0x02, "PTE" }, - { 0x03, "VA_LIMIT_VIOLATION" }, - { 0x04, "UNBOUND_INST_BLOCK" }, - { 0x05, "PRIV_VIOLATION" }, - { 0x06, "RO_VIOLATION" }, - { 0x07, "WO_VIOLATION" }, - { 0x08, "PITCH_MASK_VIOLATION" }, - { 0x09, "WORK_CREATION" }, - { 0x0a, "UNSUPPORTED_APERTURE" }, - { 0x0b, "COMPRESSION_FAILURE" }, - { 0x0c, "UNSUPPORTED_KIND" }, - { 0x0d, "REGION_VIOLATION" }, - { 0x0e, "BOTH_PTES_VALID" }, - { 0x0f, "INFO_TYPE_POISONED" }, - {} -}; - -const struct nvkm_enum -gk104_fifo_fault_hubclient[] = { - { 0x00, "VIP" }, - { 0x01, "CE0" }, - { 0x02, "CE1" }, - { 0x03, "DNISO" }, - { 0x04, "FE" }, - { 0x05, "FECS" }, - { 0x06, "HOST" }, - { 0x07, "HOST_CPU" }, - { 0x08, "HOST_CPU_NB" }, - { 0x09, "ISO" }, - { 0x0a, "MMU" }, - { 0x0b, "MSPDEC" }, - { 0x0c, "MSPPP" }, - { 0x0d, "MSVLD" }, - { 0x0e, "NISO" }, - { 0x0f, "P2P" }, - { 0x10, "PD" }, - { 0x11, "PERF" }, - { 0x12, "PMU" }, - { 0x13, "RASTERTWOD" }, - { 0x14, "SCC" }, - { 0x15, "SCC_NB" }, - { 0x16, "SEC" }, - { 0x17, "SSYNC" }, - { 0x18, "GR_CE" }, - { 0x19, "CE2" }, - { 0x1a, "XV" }, - { 0x1b, "MMU_NB" }, - { 0x1c, "MSENC" }, - { 0x1d, "DFALCON" }, - { 0x1e, "SKED" }, - { 0x1f, "AFALCON" }, - {} -}; - -const struct nvkm_enum -gk104_fifo_fault_gpcclient[] = { - { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" }, - { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" }, - { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" }, - { 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" }, - { 0x0c, "RAST" }, - { 0x0d, "GCC" }, - { 0x0e, "GPCCS" }, - { 0x0f, "PROP_0" }, - { 0x10, "PROP_1" }, - { 0x11, "PROP_2" }, - { 0x12, "PROP_3" }, - { 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" }, - { 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" }, - { 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" }, - { 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" }, - { 0x1f, "GPM" }, - { 0x20, "LTP_UTLB_0" }, - { 0x21, "LTP_UTLB_1" }, - { 0x22, "LTP_UTLB_2" }, - { 0x23, "LTP_UTLB_3" }, - { 0x24, "GPC_RGG_UTLB" }, - {} -}; - static const struct gk104_fifo_func gk104_fifo = { .chid_nr = gk104_fifo_chid_nr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 95a30fbf65a1..f9f8371d3756 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -49,6 +49,72 @@ nv04_fifo_ramfc[] = { {} }; +void +nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nv04_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_memory *fctx = device->imem->ramfc; + const struct nv04_fifo_ramfc *c; + unsigned long flags; + u32 mask = fifo->base.nr - 1; + u32 data = chan->ramfc; + u32 chid; + + /* prevent fifo context switches */ + spin_lock_irqsave(&fifo->base.lock, flags); + nvkm_wr32(device, NV03_PFIFO_CACHES, 0); + + /* if this channel is active, replace it with a null context */ + chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & mask; + if (chid == chan->base.chid) { + nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0); + nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); + + c = fifo->ramfc; + nvkm_kmap(fctx); + do { + u32 rm = ((1ULL << c->bits) - 1) << c->regs; + u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; + u32 rv = (nvkm_rd32(device, c->regp) & rm) >> c->regs; + u32 cv = (nvkm_ro32(fctx, c->ctxp + data) & ~cm); + nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs)); + } while ((++c)->bits); + nvkm_done(fctx); + + c = fifo->ramfc; + do { + nvkm_wr32(device, c->regp, 0x00000000); + } while ((++c)->bits); + + nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, mask); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1); + nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); + } + + /* restore normal operation, after disabling dma mode */ + nvkm_mask(device, NV04_PFIFO_MODE, 1 << chan->base.chid, 0); + nvkm_wr32(device, NV03_PFIFO_CACHES, 1); + spin_unlock_irqrestore(&fifo->base.lock, flags); +} + +void +nv04_fifo_dma_init(struct nvkm_fifo_chan *base) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nv04_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 mask = 1 << chan->base.chid; + unsigned long flags; + spin_lock_irqsave(&fifo->base.lock, flags); + nvkm_mask(device, NV04_PFIFO_MODE, mask, mask); + spin_unlock_irqrestore(&fifo->base.lock, flags); +} + static const struct nvkm_chan_func nv04_chan = { }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index f3f11a324591..101015a1a7e9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -64,22 +64,6 @@ nv50_fifo_runlist_update(struct nv50_fifo *fifo) mutex_unlock(&fifo->base.mutex); } -int -nv50_fifo_oneinit(struct nvkm_fifo *base) -{ - struct nv50_fifo *fifo = nv50_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; - int ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, - false, &fifo->runlist[0]); - if (ret) - return ret; - - return nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, - false, &fifo->runlist[1]); -} - void nv50_fifo_init(struct nvkm_fifo *base) { @@ -110,6 +94,22 @@ nv50_fifo_chid_nr(struct nvkm_fifo *fifo) return 128; } +int +nv50_fifo_oneinit(struct nvkm_fifo *base) +{ + struct nv50_fifo *fifo = nv50_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + int ret; + + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, + false, &fifo->runlist[0]); + if (ret) + return ret; + + return nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, + false, &fifo->runlist[1]); +} + void * nv50_fifo_dtor(struct nvkm_fifo *base) { -- cgit v1.2.3 From 9be9c606c4be74b5e8cbebe5b1ea96821e27b04f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:22 +1000 Subject: drm/nouveau/fifo: merge gk104_fifo_func into nvkm_host_func This makes it easier to transition everything. - a couple of function renames for collisions Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 9 +---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 11 ++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 49 ++++++++++++------------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 39 +------------------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 18 +++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 18 +++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 18 +++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 25 ++++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 18 +++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 25 ++++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 21 +++++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 46 +++++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 29 +++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 4 +- 14 files changed, 219 insertions(+), 111 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index b06db3b3d471..4e099bf0a3fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -30,8 +30,6 @@ #include #include -#include "gk104.h" - void nvkm_fifo_recover_chan(struct nvkm_fifo *fifo, int chid) { @@ -58,7 +56,7 @@ nvkm_fifo_start(struct nvkm_fifo *fifo, unsigned long *flags) void nvkm_fifo_fault(struct nvkm_fifo *fifo, struct nvkm_fault_data *info) { - return fifo->func->fault(fifo, info); + return fifo->func->mmu_fault->recover(fifo, info); } void @@ -179,9 +177,6 @@ nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, const struct nvkm_dev const struct nvkm_fifo_func_chan *chan = &fifo->func->chan; int c = 0; - if (fifo->func->engine_id == gk104_fifo_engine_id) - chan = &gk104_fifo(fifo)->func->chan; - /* *_CHANNEL_DMA, *_CHANNEL_GPFIFO_* */ if (chan->user.oclass) { if (c++ == index) { @@ -289,7 +284,7 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, INIT_LIST_HEAD(&fifo->chan); - nr = func->chid_nr ? func->chid_nr(fifo) : gk104_fifo(fifo)->func->chid_nr(fifo); + nr = func->chid_nr(fifo); if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR)) fifo->nr = NVKM_FIFO_CHID_NR; else diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index bd0b0c66e28f..1a641b1fdfbf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -359,6 +359,11 @@ gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) nvkm_fifo_chan_put(&fifo->base, flags, &chan); } +static const struct nvkm_fifo_func_mmu_fault +gf100_fifo_mmu_fault = { + .recover = gf100_fifo_fault, +}; + static const struct nvkm_enum gf100_fifo_sched_reason[] = { { 0x0a, "CTXSW_TIMEOUT" }, @@ -422,7 +427,7 @@ gf100_fifo_intr_sched(struct gf100_fifo *fifo) } void -gf100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) +gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) { struct nvkm_device *device = fifo->engine.subdev.device; u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); @@ -541,7 +546,7 @@ gf100_fifo_intr(struct nvkm_fifo *base) u32 mask = nvkm_rd32(device, 0x00259c); while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_fault(&fifo->base, unit); + gf100_fifo_intr_mmu_fault_unit(&fifo->base, unit); nvkm_wr32(device, 0x00259c, (1 << unit)); mask &= ~(1 << unit); } @@ -679,7 +684,7 @@ gf100_fifo = { .init = gf100_fifo_init, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, - .fault = gf100_fifo_fault, + .mmu_fault = &gf100_fifo_mmu_fault, .engine_id = gf100_fifo_engine_id, .id_engine = gf100_fifo_id_engine, .uevent_init = gf100_fifo_uevent_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index da26c5219e53..880ddfec22f7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -397,7 +397,7 @@ gk104_fifo_recover_chid(struct gk104_fifo *fifo, int runl, int chid) return NULL; } -static void +void gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid) { struct gk104_fifo *fifo = gk104_fifo(base); @@ -629,7 +629,7 @@ gk104_fifo_fault_gpcclient[] = { {} }; -static void +void gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) { struct gk104_fifo *fifo = gk104_fifo(base); @@ -709,6 +709,11 @@ gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) spin_unlock_irqrestore(&fifo->base.lock, flags); } +const struct nvkm_fifo_func_mmu_fault +gk104_fifo_mmu_fault = { + .recover = gk104_fifo_fault, +}; + static const struct nvkm_enum gk104_fifo_bind_reason[] = { { 0x01, "BIND_NOT_UNBOUND" }, @@ -869,7 +874,7 @@ gk104_fifo_intr_engine(struct gk104_fifo *fifo) nvkm_fifo_uevent(&fifo->base); } -static void +void gk104_fifo_intr(struct nvkm_fifo *base) { struct gk104_fifo *fifo = gk104_fifo(base); @@ -924,7 +929,7 @@ gk104_fifo_intr(struct nvkm_fifo *base) u32 mask = nvkm_rd32(device, 0x00259c); while (mask) { u32 unit = __ffs(mask); - fifo->func->intr.fault(&fifo->base, unit); + fifo->func->intr_mmu_fault_unit(&fifo->base, unit); nvkm_wr32(device, 0x00259c, (1 << unit)); mask &= ~(1 << unit); } @@ -1168,22 +1173,6 @@ gk104_fifo_dtor(struct nvkm_fifo *base) return fifo; } -static const struct nvkm_fifo_func -gk104_fifo_ = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, - .info = gk104_fifo_info, - .init = gk104_fifo_init, - .fini = gk104_fifo_fini, - .intr = gk104_fifo_intr, - .fault = gk104_fifo_fault, - .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, - .recover_chan = gk104_fifo_recover_chan, -}; - int gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, int nr, struct nvkm_fifo **pfifo) @@ -1196,20 +1185,32 @@ gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device, INIT_WORK(&fifo->recover.work, gk104_fifo_recover_work); *pfifo = &fifo->base; - return nvkm_fifo_ctor(&gk104_fifo_, device, type, inst, &fifo->base); + return nvkm_fifo_ctor(func, device, type, inst, &fifo->base); } -static const struct gk104_fifo_func +static const struct nvkm_fifo_func gk104_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, .chid_nr = gk104_fifo_chid_nr, - .intr.fault = gf100_fifo_intr_fault, - .pbdma = &gk104_fifo_pbdma, + .info = gk104_fifo_info, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .mmu_fault = &gk104_fifo_mmu_fault, .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .runlist = &gk104_fifo_runlist, + .pbdma = &gk104_fifo_pbdma, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index be426734da02..962187740010 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -8,6 +8,8 @@ struct nvkm_fifo_cgrp; #include #include +#define gk104_fifo_func nvkm_fifo_func + struct gk104_fifo_chan; struct gk104_fifo { const struct gk104_fifo_func *func; @@ -45,41 +47,6 @@ struct gk104_fifo { } user; }; -struct gk104_fifo_func { - int (*chid_nr)(struct nvkm_fifo *); - - struct { - void (*fault)(struct nvkm_fifo *, int unit); - } intr; - - const struct gk104_fifo_pbdma_func { - int (*nr)(struct gk104_fifo *); - void (*init)(struct gk104_fifo *); - void (*init_timeout)(struct gk104_fifo *); - } *pbdma; - - struct { - const struct nvkm_enum *access; - const struct nvkm_enum *engine; - const struct nvkm_enum *reason; - const struct nvkm_enum *hubclient; - const struct nvkm_enum *gpcclient; - } fault; - - const struct gk104_fifo_runlist_func { - u8 size; - void (*cgrp)(struct nvkm_fifo_cgrp *, - struct nvkm_memory *, u32 offset); - void (*chan)(struct gk104_fifo_chan *, - struct nvkm_memory *, u32 offset); - void (*commit)(struct gk104_fifo *, int runl, - struct nvkm_memory *, int entries); - } *runlist; - - struct nvkm_fifo_func_cgrp cgrp; - struct nvkm_fifo_func_chan chan; -}; - struct gk104_fifo_engine_status { bool busy; bool faulted; @@ -135,14 +102,12 @@ void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, extern const struct gk104_fifo_pbdma_func gk208_fifo_pbdma; void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *); -void gm107_fifo_intr_fault(struct nvkm_fifo *, int); extern const struct nvkm_enum gm107_fifo_fault_engine[]; extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; extern const struct gk104_fifo_pbdma_func gm200_fifo_pbdma; int gm200_fifo_pbdma_nr(struct gk104_fifo *); -void gp100_fifo_intr_fault(struct nvkm_fifo *, int); extern const struct nvkm_enum gp100_fifo_fault_engine[]; extern const struct nvkm_enum gv100_fifo_fault_access[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index df9b83cf382f..9dcc54f1d016 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -56,17 +56,29 @@ gk110_fifo_runlist = { .commit = gk104_fifo_runlist_commit, }; -static const struct gk104_fifo_func +static const struct nvkm_fifo_func gk110_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, .chid_nr = gk104_fifo_chid_nr, - .intr.fault = gf100_fifo_intr_fault, - .pbdma = &gk104_fifo_pbdma, + .info = gk104_fifo_info, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .mmu_fault = &gk104_fifo_mmu_fault, .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, + .pbdma = &gk104_fifo_pbdma, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 003f244f89db..28791baf77f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -49,17 +49,29 @@ gk208_fifo_chid_nr(struct nvkm_fifo *fifo) return 1024; } -static const struct gk104_fifo_func +static const struct nvkm_fifo_func gk208_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, .chid_nr = gk208_fifo_chid_nr, - .intr.fault = gf100_fifo_intr_fault, - .pbdma = &gk208_fifo_pbdma, + .info = gk104_fifo_info, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .mmu_fault = &gk104_fifo_mmu_fault, .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, + .pbdma = &gk208_fifo_pbdma, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 661c9f0cf7b9..b62e3bb0294c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -24,17 +24,29 @@ #include -static const struct gk104_fifo_func +static const struct nvkm_fifo_func gk20a_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, - .intr.fault = gf100_fifo_intr_fault, - .pbdma = &gk208_fifo_pbdma, + .info = gk104_fifo_info, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .mmu_fault = &gk104_fifo_mmu_fault, .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, + .pbdma = &gk208_fifo_pbdma, .cgrp = {{ }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 910d97911a98..f996f1c1141a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -74,8 +74,13 @@ gm107_fifo_fault_engine[] = { {} }; +const struct nvkm_fifo_func_mmu_fault +gm107_fifo_mmu_fault = { + .recover = gk104_fifo_fault, +}; + void -gm107_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) +gm107_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) { struct nvkm_device *device = fifo->engine.subdev.device; u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); @@ -104,17 +109,29 @@ gm107_fifo_chid_nr(struct nvkm_fifo *fifo) return 2048; } -static const struct gk104_fifo_func +static const struct nvkm_fifo_func gm107_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, .chid_nr = gm107_fifo_chid_nr, - .intr.fault = gm107_fifo_intr_fault, - .pbdma = &gk208_fifo_pbdma, + .info = gk104_fifo_info, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, + .mmu_fault = &gm107_fifo_mmu_fault, .fault.access = gk104_fifo_fault_access, .fault.engine = gm107_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, + .pbdma = &gk208_fifo_pbdma, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 101027536a93..8f3da21ce1e7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -46,17 +46,29 @@ gm200_fifo_chid_nr(struct nvkm_fifo *fifo) return nvkm_rd32(fifo->engine.subdev.device, 0x002008); } -static const struct gk104_fifo_func +static const struct nvkm_fifo_func gm200_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, - .intr.fault = gm107_fifo_intr_fault, - .pbdma = &gm200_fifo_pbdma, + .info = gk104_fifo_info, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, + .mmu_fault = &gm107_fifo_mmu_fault, .fault.access = gk104_fifo_fault_access, .fault.engine = gm107_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, + .pbdma = &gm200_fifo_pbdma, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index c52a4a0b361b..dc590848c25c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -52,8 +52,13 @@ gp100_fifo_fault_engine[] = { {} }; +static const struct nvkm_fifo_func_mmu_fault +gp100_fifo_mmu_fault = { + .recover = gk104_fifo_fault, +}; + void -gp100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) +gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) { struct nvkm_device *device = fifo->engine.subdev.device; u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); @@ -76,17 +81,29 @@ gp100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) nvkm_fifo_fault(fifo, &info); } -static const struct gk104_fifo_func +static const struct nvkm_fifo_func gp100_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, - .intr.fault = gp100_fifo_intr_fault, - .pbdma = &gm200_fifo_pbdma, + .info = gk104_fifo_info, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .intr_mmu_fault_unit = gp100_fifo_intr_mmu_fault_unit, + .mmu_fault = &gp100_fifo_mmu_fault, .fault.access = gk104_fifo_fault_access, .fault.engine = gp100_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, + .pbdma = &gm200_fifo_pbdma, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index ddca29852865..36c02b5aac0f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -291,16 +291,33 @@ gv100_fifo_fault_access[] = { {} }; -static const struct gk104_fifo_func +static const struct nvkm_fifo_func_mmu_fault +gv100_fifo_mmu_fault = { + .recover = gk104_fifo_fault, +}; + +static const struct nvkm_fifo_func gv100_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, - .pbdma = &gm200_fifo_pbdma, + .info = gk104_fifo_info, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .mmu_fault = &gv100_fifo_mmu_fault, .fault.access = gv100_fifo_fault_access, .fault.engine = gv100_fifo_fault_engine, .fault.reason = gv100_fifo_fault_reason, .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = gk104_fifo_recover_chan, .runlist = &gv100_fifo_runlist, + .pbdma = &gm200_fifo_pbdma, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan, .ctor = gv100_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index b8031c212c8b..ba3dbc86435e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -4,7 +4,9 @@ #define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine) #include struct nvkm_cgrp; +struct nvkm_memory; struct gk104_fifo; +struct gk104_fifo_chan; void nvkm_fifo_uevent(struct nvkm_fifo *); void nvkm_fifo_kevent(struct nvkm_fifo *, int chid); @@ -23,8 +25,22 @@ struct nvkm_fifo_func { int (*info)(struct nvkm_fifo *, u64 mthd, u64 *data); void (*init)(struct nvkm_fifo *); void (*fini)(struct nvkm_fifo *); + void (*intr)(struct nvkm_fifo *); - void (*fault)(struct nvkm_fifo *, struct nvkm_fault_data *); + void (*intr_mmu_fault_unit)(struct nvkm_fifo *, int unit); + + const struct nvkm_fifo_func_mmu_fault { + void (*recover)(struct nvkm_fifo *, struct nvkm_fault_data *); + } *mmu_fault; + + struct { + const struct nvkm_enum *access; + const struct nvkm_enum *engine; + const struct nvkm_enum *reason; + const struct nvkm_enum *hubclient; + const struct nvkm_enum *gpcclient; + } fault; + int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *(*id_engine)(struct nvkm_fifo *, int engi); void (*pause)(struct nvkm_fifo *, unsigned long *); @@ -33,6 +49,22 @@ struct nvkm_fifo_func { void (*uevent_fini)(struct nvkm_fifo *); void (*recover_chan)(struct nvkm_fifo *, int chid); + const struct gk104_fifo_runlist_func { + u8 size; + void (*cgrp)(struct nvkm_fifo_cgrp *, + struct nvkm_memory *, u32 offset); + void (*chan)(struct gk104_fifo_chan *, + struct nvkm_memory *, u32 offset); + void (*commit)(struct gk104_fifo *, int runl, + struct nvkm_memory *, int entries); + } *runlist; + + const struct gk104_fifo_pbdma_func { + int (*nr)(struct gk104_fifo *); + void (*init)(struct gk104_fifo *); + void (*init_timeout)(struct gk104_fifo *); + } *pbdma; + struct nvkm_fifo_func_cgrp { struct nvkm_sclass user; const struct nvkm_cgrp_func *func; @@ -67,19 +99,29 @@ int nv50_fifo_chid_nr(struct nvkm_fifo *); extern const struct nvkm_chan_func g84_chan; -void gf100_fifo_intr_fault(struct nvkm_fifo *, int); +void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); int gk104_fifo_chid_nr(struct nvkm_fifo *); +void gk104_fifo_intr(struct nvkm_fifo *); +extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; +void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); +void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int); extern const struct nvkm_cgrp_func gk110_cgrp; extern const struct nvkm_chan_func gk110_chan; +void gm107_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); +extern const struct nvkm_fifo_func_mmu_fault gm107_fifo_mmu_fault; extern const struct nvkm_chan_func gm107_chan; int gm200_fifo_chid_nr(struct nvkm_fifo *); +void gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); + +extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault; + int nvkm_uchan_new(struct nvkm_fifo *, struct nvkm_cgrp *, const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index db9b802bd67c..274096316a1b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -339,6 +339,11 @@ tu102_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) spin_unlock_irqrestore(&fifo->base.lock, flags); } +const struct nvkm_fifo_func_mmu_fault +tu102_fifo_mmu_fault = { + .recover = tu102_fifo_fault, +}; + static void tu102_fifo_intr_ctxsw_timeout(struct gk104_fifo *fifo) { @@ -433,31 +438,27 @@ tu102_fifo_intr(struct nvkm_fifo *base) } static const struct nvkm_fifo_func -tu102_fifo_ = { +tu102_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, + .chid_nr = gm200_fifo_chid_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = tu102_fifo_intr, - .fault = tu102_fifo_fault, - .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, - .recover_chan = tu102_fifo_recover_chan, -}; - -static const struct gk104_fifo_func -tu102_fifo = { - .chid_nr = gm200_fifo_chid_nr, - .pbdma = &tu102_fifo_pbdma, + .mmu_fault = &tu102_fifo_mmu_fault, .fault.access = gv100_fifo_fault_access, .fault.engine = tu102_fifo_fault_engine, .fault.reason = gv100_fifo_fault_reason, .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, + .engine_id = gk104_fifo_engine_id, + .id_engine = gk104_fifo_id_engine, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .recover_chan = tu102_fifo_recover_chan, .runlist = &tu102_fifo_runlist, + .pbdma = &tu102_fifo_pbdma, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan, .ctor = tu102_fifo_gpfifo_new }, }; @@ -474,5 +475,5 @@ tu102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, INIT_WORK(&fifo->recover.work, tu102_fifo_recover_work); *pfifo = &fifo->base; - return nvkm_fifo_ctor(&tu102_fifo_, device, type, inst, &fifo->base); + return nvkm_fifo_ctor(&tu102_fifo, device, type, inst, &fifo->base); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index a1d93f28b634..42b49043deef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -162,8 +162,8 @@ nvkm_uchan_new(struct nvkm_fifo *fifo, struct nvkm_cgrp *cgrp, const struct nvkm nvkm_object_ctor(&nvkm_uchan, oclass, &uchan->object); *pobject = &uchan->object; - if (!fifo->func->chan.func) - ret = gk104_fifo(fifo)->func->chan.ctor(gk104_fifo(fifo), oclass, argv, argc, &object); + if (fifo->func->chan.ctor) + ret = fifo->func->chan.ctor(gk104_fifo(fifo), oclass, argv, argc, &object); else ret = fifo->func->chan.oclass->ctor(fifo, oclass, argv, argc, &object); if (!object) -- cgit v1.2.3 From 800ac1f8d708ea2b70ac55b3029687c1b4283431 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:23 +1000 Subject: drm/nouveau/fifo: add chid allocator We need to be able to allocate TSG IDs as well as channel IDs, also, Ampere has per-runlist channel IDs. - holds per-ID private data, which will be used for/to protect lookup - holds an nvkm_event which will be used for events tied to IDs - not used yet beyond setup, and switching use of "fifo->nr - 1" for channel ID mask to "chid->mask" Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 3 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 20 +++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 4 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c | 82 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h | 23 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 8 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 14 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 23 +++--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 9 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 9 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 9 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 6 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 1 + 26 files changed, 209 insertions(+), 21 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 2f2059c5d4c9..b688121f1a91 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -37,6 +37,9 @@ struct nvkm_fifo { const struct nvkm_fifo_func *func; struct nvkm_engine engine; + struct nvkm_chid *chid; + struct nvkm_chid *cgid; + DECLARE_BITMAP(mask, NVKM_FIFO_CHID_NR); int nr; struct list_head chan; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index 76d2bf1f6d8b..c985736bff2c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -1,5 +1,8 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/engine/fifo/base.o +nvkm-y += nvkm/engine/fifo/chan.o +nvkm-y += nvkm/engine/fifo/chid.o + nvkm-y += nvkm/engine/fifo/nv04.o nvkm-y += nvkm/engine/fifo/nv10.o nvkm-y += nvkm/engine/fifo/nv17.o @@ -18,7 +21,6 @@ nvkm-y += nvkm/engine/fifo/gv100.o nvkm-y += nvkm/engine/fifo/tu102.o nvkm-y += nvkm/engine/fifo/ga102.o -nvkm-y += nvkm/engine/fifo/chan.o nvkm-y += nvkm/engine/fifo/channv50.o nvkm-y += nvkm/engine/fifo/chang84.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 4e099bf0a3fa..e6b0653625f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -23,6 +23,7 @@ */ #include "priv.h" #include "chan.h" +#include "chid.h" #include #include @@ -218,13 +219,15 @@ static int nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + switch (mthd) { - case NV_DEVICE_HOST_CHANNELS: *data = fifo->nr; return 0; + case NV_DEVICE_HOST_CHANNELS: *data = fifo->chid ? fifo->chid->nr : 0; return 0; default: if (fifo->func->info) return fifo->func->info(fifo, mthd, data); break; } + return -ENOSYS; } @@ -232,8 +235,18 @@ static int nvkm_fifo_oneinit(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + int ret; + + /* Initialise CHID/CGID allocator(s) on GPUs where they aren't per-runlist. */ + if (fifo->func->chid_nr) { + ret = fifo->func->chid_ctor(fifo, fifo->func->chid_nr(fifo)); + if (ret) + return ret; + } + if (fifo->func->oneinit) return fifo->func->oneinit(fifo); + return 0; } @@ -248,6 +261,10 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); void *data = fifo; + + nvkm_chid_unref(&fifo->cgid); + nvkm_chid_unref(&fifo->chid); + if (fifo->func->dtor) data = fifo->func->dtor(fifo); nvkm_event_fini(&fifo->kevent); @@ -289,7 +306,6 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, fifo->nr = NVKM_FIFO_CHID_NR; else fifo->nr = nr; - bitmap_clear(fifo->mask, 0, fifo->nr); if (func->uevent_init) { ret = nvkm_event_init(&nvkm_fifo_uevent_func, &fifo->engine.subdev, 1, 1, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 4d4905be4b92..464c956aaca9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -32,6 +32,10 @@ #include +const struct nvkm_event_func +nvkm_chan_event = { +}; + struct nvkm_fifo_chan_object { struct nvkm_oproxy oproxy; struct nvkm_fifo_chan *chan; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 24fbe6cf70e1..a9c0e02b6f9f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -4,6 +4,8 @@ #define nvkm_chan(p) container_of((p), struct nvkm_chan, object) /*FIXME: remove later */ #include +extern const struct nvkm_event_func nvkm_chan_event; + struct nvkm_chan_func { void *(*dtor)(struct nvkm_fifo_chan *); void (*init)(struct nvkm_fifo_chan *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c new file mode 100644 index 000000000000..7c582bce7e24 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c @@ -0,0 +1,82 @@ +/* + * Copyright 2020 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "chid.h" + +static void +nvkm_chid_del(struct kref *kref) +{ + struct nvkm_chid *chid = container_of(kref, typeof(*chid), kref); + + nvkm_event_fini(&chid->event); + + kvfree(chid->data); + kfree(chid); +} + +void +nvkm_chid_unref(struct nvkm_chid **pchid) +{ + struct nvkm_chid *chid = *pchid; + + if (!chid) + return; + + kref_put(&chid->kref, nvkm_chid_del); + *pchid = NULL; +} + +struct nvkm_chid * +nvkm_chid_ref(struct nvkm_chid *chid) +{ + if (chid) + kref_get(&chid->kref); + + return chid; +} + +int +nvkm_chid_new(const struct nvkm_event_func *func, struct nvkm_subdev *subdev, + int nr, int first, int count, struct nvkm_chid **pchid) +{ + struct nvkm_chid *chid; + int id; + + if (!(chid = *pchid = kzalloc(struct_size(chid, used, nr), GFP_KERNEL))) + return -ENOMEM; + + kref_init(&chid->kref); + chid->nr = nr; + chid->mask = chid->nr - 1; + spin_lock_init(&chid->lock); + + if (!(chid->data = kvzalloc(sizeof(*chid->data) * nr, GFP_KERNEL))) { + nvkm_chid_unref(pchid); + return -ENOMEM; + } + + for (id = 0; id < first; id++) + __set_bit(id, chid->used); + for (id = first + count; id < nr; id++) + __set_bit(id, chid->used); + + return nvkm_event_init(func, subdev, 1, nr, &chid->event); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h new file mode 100644 index 000000000000..d359828dde80 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_CHID_H__ +#define __NVKM_CHID_H__ +#include + +struct nvkm_chid { + struct kref kref; + int nr; + u32 mask; + + struct nvkm_event event; + + void **data; + + spinlock_t lock; + unsigned long used[]; +}; + +int nvkm_chid_new(const struct nvkm_event_func *, struct nvkm_subdev *, + int nr, int first, int count, struct nvkm_chid **pchid); +struct nvkm_chid *nvkm_chid_ref(struct nvkm_chid *); +void nvkm_chid_unref(struct nvkm_chid **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 24732d355c83..dbb9df6f8eb5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -119,6 +119,7 @@ g84_fifo = { .dtor = nv50_fifo_dtor, .oneinit = nv50_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, + .chid_ctor = nv50_fifo_chid_ctor, .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = g84_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 1a641b1fdfbf..d8eeca818637 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "chan.h" +#include "chid.h" #include "gf100.h" #include "changf100.h" @@ -624,6 +625,12 @@ gf100_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */ } +int +gf100_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) +{ + return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr, &fifo->chid); +} + static int gf100_fifo_oneinit(struct nvkm_fifo *base) { @@ -681,6 +688,7 @@ gf100_fifo = { .dtor = gf100_fifo_dtor, .oneinit = gf100_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, + .chid_ctor = gf100_fifo_chid_ctor, .init = gf100_fifo_init, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 880ddfec22f7..c4fa4fc68d46 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "chan.h" +#include "chid.h" #include "gk104.h" #include "cgrp.h" @@ -1193,6 +1194,7 @@ gk104_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = gk104_fifo_chid_nr, + .chid_ctor = gf100_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 962187740010..af6a004a6267 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -74,7 +74,7 @@ void gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit); void gk104_fifo_intr_runlist(struct gk104_fifo *fifo); void gk104_fifo_intr_engine(struct gk104_fifo *fifo); void *gk104_fifo_dtor(struct nvkm_fifo *base); -int gk104_fifo_oneinit(struct nvkm_fifo *base); +int gk104_fifo_oneinit(struct nvkm_fifo *); int gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data); void gk104_fifo_init(struct nvkm_fifo *base); void gk104_fifo_fini(struct nvkm_fifo *base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 9dcc54f1d016..b23d50d1b351 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -23,6 +23,7 @@ */ #include "cgrp.h" #include "chan.h" +#include "chid.h" #include "gk104.h" #include "changk104.h" @@ -56,11 +57,24 @@ gk110_fifo_runlist = { .commit = gk104_fifo_runlist_commit, }; +int +gk110_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) +{ + int ret; + + ret = nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr, &fifo->cgid); + if (ret) + return ret; + + return gf100_fifo_chid_ctor(fifo, nr); +} + static const struct nvkm_fifo_func gk110_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = gk104_fifo_chid_nr, + .chid_ctor = gk110_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 28791baf77f8..1dd937bdbbae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -54,6 +54,7 @@ gk208_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = gk208_fifo_chid_nr, + .chid_ctor = gk110_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index b62e3bb0294c..d2e78d2a868a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -29,6 +29,7 @@ gk20a_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, + .chid_ctor = gk110_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index f996f1c1141a..32ef88a90d1e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -114,6 +114,7 @@ gm107_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = gm107_fifo_chid_nr, + .chid_ctor = gk110_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 8f3da21ce1e7..74891833926e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -51,6 +51,7 @@ gm200_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, + .chid_ctor = gk110_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index dc590848c25c..c1ad59d1223b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -86,6 +86,7 @@ gp100_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, + .chid_ctor = gk110_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 36c02b5aac0f..9e876bd871bb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -301,6 +301,7 @@ gv100_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, + .chid_ctor = gk110_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index f9f8371d3756..18fa5b933e9e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -23,6 +23,7 @@ */ #include "cgrp.h" #include "chan.h" +#include "chid.h" #include "nv04.h" #include "channv04.h" @@ -58,7 +59,6 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) struct nvkm_memory *fctx = device->imem->ramfc; const struct nv04_fifo_ramfc *c; unsigned long flags; - u32 mask = fifo->base.nr - 1; u32 data = chan->ramfc; u32 chid; @@ -67,7 +67,7 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) nvkm_wr32(device, NV03_PFIFO_CACHES, 0); /* if this channel is active, replace it with a null context */ - chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & mask; + chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.chid->mask; if (chid == chan->base.chid) { nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0); @@ -91,7 +91,7 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0); nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0); - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, mask); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.chid->mask); nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1); nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); } @@ -360,7 +360,7 @@ nv04_fifo_intr(struct nvkm_fifo *base) reassign = nvkm_rd32(device, NV03_PFIFO_CACHES) & 1; nvkm_wr32(device, NV03_PFIFO_CACHES, 0); - chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & (fifo->base.nr - 1); + chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.chid->mask; get = nvkm_rd32(device, NV03_PFIFO_CACHE1_GET); if (stat & NV_PFIFO_INTR_CACHE_ERROR) { @@ -407,10 +407,9 @@ nv04_fifo_intr(struct nvkm_fifo *base) } void -nv04_fifo_init(struct nvkm_fifo *base) +nv04_fifo_init(struct nvkm_fifo *fifo) { - struct nv04_fifo *fifo = nv04_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_instmem *imem = device->imem; struct nvkm_ramht *ramht = imem->ramht; struct nvkm_memory *ramro = imem->ramro; @@ -425,7 +424,7 @@ nv04_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, NV03_PFIFO_RAMRO, nvkm_memory_addr(ramro) >> 8); nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8); - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->chid->mask); nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff); nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff); @@ -435,6 +434,13 @@ nv04_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, NV03_PFIFO_CACHES, 1); } +int +nv04_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) +{ + /* The last CHID is reserved by HW as a "channel invalid" marker. */ + return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr - 1, &fifo->chid); +} + static int nv04_fifo_chid_nr(struct nvkm_fifo *fifo) { @@ -465,6 +471,7 @@ nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, static const struct nvkm_fifo_func nv04_fifo = { .chid_nr = nv04_fifo_chid_nr, + .chid_ctor = nv04_fifo_chid_ctor, .init = nv04_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h index 3f23bcde4a54..879c686675d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h @@ -19,5 +19,4 @@ struct nv04_fifo { int nv04_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, int nr, const struct nv04_fifo_ramfc *, struct nvkm_fifo **); -void nv04_fifo_init(struct nvkm_fifo *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index f07304e4b8c5..bc25520cb39b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -56,6 +56,7 @@ nv10_fifo_chid_nr(struct nvkm_fifo *fifo) static const struct nvkm_fifo_func nv10_fifo = { .chid_nr = nv10_fifo_chid_nr, + .chid_ctor = nv04_fifo_chid_ctor, .init = nv04_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index 858c8ba158c9..dd254d88d008 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "chan.h" +#include "chid.h" #include "nv04.h" #include "channv04.h" @@ -56,10 +57,9 @@ nv17_chan = { }; static void -nv17_fifo_init(struct nvkm_fifo *base) +nv17_fifo_init(struct nvkm_fifo *fifo) { - struct nv04_fifo *fifo = nv04_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_instmem *imem = device->imem; struct nvkm_ramht *ramht = imem->ramht; struct nvkm_memory *ramro = imem->ramro; @@ -75,7 +75,7 @@ nv17_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8 | 0x00010000); - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->chid->mask); nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff); nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff); @@ -88,6 +88,7 @@ nv17_fifo_init(struct nvkm_fifo *base) static const struct nvkm_fifo_func nv17_fifo = { .chid_nr = nv10_fifo_chid_nr, + .chid_ctor = nv04_fifo_chid_ctor, .init = nv17_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index 30f924e3da3c..c87d995e4fd1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "chan.h" +#include "chid.h" #include "nv04.h" #include "channv04.h" @@ -65,10 +66,9 @@ nv40_chan = { }; static void -nv40_fifo_init(struct nvkm_fifo *base) +nv40_fifo_init(struct nvkm_fifo *fifo) { - struct nv04_fifo *fifo = nv04_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_fb *fb = device->fb; struct nvkm_instmem *imem = device->imem; struct nvkm_ramht *ramht = imem->ramht; @@ -106,7 +106,7 @@ nv40_fifo_init(struct nvkm_fifo *base) break; } - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->chid->mask); nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff); nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff); @@ -119,6 +119,7 @@ nv40_fifo_init(struct nvkm_fifo *base) static const struct nvkm_fifo_func nv40_fifo = { .chid_nr = nv10_fifo_chid_nr, + .chid_ctor = nv04_fifo_chid_ctor, .init = nv40_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 101015a1a7e9..13c514acc9d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "chan.h" +#include "chid.h" #include "nv50.h" #include "channv50.h" @@ -88,6 +89,13 @@ nv50_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002500, 0x00000001); } +int +nv50_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) +{ + /* CHID 0 is unusable (some kind of PIO channel?), 127 is "channel invalid". */ + return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 1, nr - 2, &fifo->chid); +} + int nv50_fifo_chid_nr(struct nvkm_fifo *fifo) { @@ -144,6 +152,7 @@ nv50_fifo = { .dtor = nv50_fifo_dtor, .oneinit = nv50_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, + .chid_ctor = nv50_fifo_chid_ctor, .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index ba3dbc86435e..80280841cf81 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -21,6 +21,7 @@ struct nvkm_fifo_func { int (*oneinit)(struct nvkm_fifo *); int (*chid_nr)(struct nvkm_fifo *); + int (*chid_ctor)(struct nvkm_fifo *, int nr); int (*info)(struct nvkm_fifo *, u64 mthd, u64 *data); void (*init)(struct nvkm_fifo *); @@ -86,6 +87,8 @@ struct nvkm_fifo_func { int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_fifo *); +int nv04_fifo_chid_ctor(struct nvkm_fifo *, int); +void nv04_fifo_init(struct nvkm_fifo *); void nv04_fifo_intr(struct nvkm_fifo *); int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *nv04_fifo_id_engine(struct nvkm_fifo *, int); @@ -96,9 +99,11 @@ extern const struct nvkm_cgrp_func nv04_cgrp; int nv10_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_nr(struct nvkm_fifo *); +int nv50_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_chan_func g84_chan; +int gf100_fifo_chid_ctor(struct nvkm_fifo *, int); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); int gk104_fifo_chid_nr(struct nvkm_fifo *); @@ -109,6 +114,7 @@ void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int); +int gk110_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_cgrp_func gk110_cgrp; extern const struct nvkm_chan_func gk110_chan; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 274096316a1b..fbc67b84a8b1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -442,6 +442,7 @@ tu102_fifo = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, + .chid_ctor = gk110_fifo_chid_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, -- cgit v1.2.3 From 1c488ba96e59ce84bf1cfd321bf27252f4598bec Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:23 +1000 Subject: drm/nouveau/fifo: add runq Creates an nvkm_runq for each PBDMA, these will be associated with the relevant runlist(s) later. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 16 +++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 25 +++++++++--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 20 ++++------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 8 +++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 8 ++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 7 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 11 +++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c | 45 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h | 24 ++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 3 +- 17 files changed, 153 insertions(+), 27 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index b688121f1a91..895eb262345e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -40,6 +40,8 @@ struct nvkm_fifo { struct nvkm_chid *chid; struct nvkm_chid *cgid; + struct list_head runqs; + DECLARE_BITMAP(mask, NVKM_FIFO_CHID_NR); int nr; struct list_head chan; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index c985736bff2c..447001db070e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -2,6 +2,7 @@ nvkm-y += nvkm/engine/fifo/base.o nvkm-y += nvkm/engine/fifo/chan.o nvkm-y += nvkm/engine/fifo/chid.o +nvkm-y += nvkm/engine/fifo/runq.o nvkm-y += nvkm/engine/fifo/nv04.o nvkm-y += nvkm/engine/fifo/nv10.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index e6b0653625f5..806ca8986eb5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -24,6 +24,7 @@ #include "priv.h" #include "chan.h" #include "chid.h" +#include "runq.h" #include #include @@ -235,7 +236,7 @@ static int nvkm_fifo_oneinit(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); - int ret; + int ret, nr, i; /* Initialise CHID/CGID allocator(s) on GPUs where they aren't per-runlist. */ if (fifo->func->chid_nr) { @@ -244,6 +245,14 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) return ret; } + /* Create runqueues for each PBDMA. */ + if (fifo->func->runq_nr) { + for (nr = fifo->func->runq_nr(fifo), i = 0; i < nr; i++) { + if (!nvkm_runq_new(fifo, i)) + return -ENOMEM; + } + } + if (fifo->func->oneinit) return fifo->func->oneinit(fifo); @@ -260,8 +269,12 @@ static void * nvkm_fifo_dtor(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + struct nvkm_runq *runq, *rtmp; void *data = fifo; + list_for_each_entry_safe(runq, rtmp, &fifo->runqs, head) + nvkm_runq_del(runq); + nvkm_chid_unref(&fifo->cgid); nvkm_chid_unref(&fifo->chid); @@ -292,6 +305,7 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, int ret, nr; fifo->func = func; + INIT_LIST_HEAD(&fifo->runqs); spin_lock_init(&fifo->lock); mutex_init(&fifo->mutex); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index d8eeca818637..14d8bc3b5956 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -23,6 +23,7 @@ */ #include "chan.h" #include "chid.h" +#include "runq.h" #include "gf100.h" #include "changf100.h" @@ -100,6 +101,10 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit) nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); } +static const struct nvkm_runq_func +gf100_runq = { +}; + void gf100_fifo_runlist_commit(struct gf100_fifo *fifo) { @@ -625,6 +630,18 @@ gf100_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */ } +int +gf100_fifo_runq_nr(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + u32 save; + + /* Determine number of PBDMAs by checking valid enable bits. */ + save = nvkm_mask(device, 0x000204, 0xffffffff, 0xffffffff); + save = nvkm_mask(device, 0x000204, 0xffffffff, save); + return hweight32(save); +} + int gf100_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) { @@ -640,11 +657,7 @@ gf100_fifo_oneinit(struct nvkm_fifo *base) struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); int ret; - /* Determine number of PBDMAs by checking valid enable bits. */ - nvkm_wr32(device, 0x002204, 0xffffffff); - fifo->pbdma_nr = hweight32(nvkm_rd32(device, 0x002204)); - nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr); - + fifo->pbdma_nr = fifo->base.func->runq_nr(&fifo->base); ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, false, &fifo->runlist.mem[0]); @@ -689,6 +702,7 @@ gf100_fifo = { .oneinit = gf100_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = gf100_fifo_chid_ctor, + .runq_nr = gf100_fifo_runq_nr, .init = gf100_fifo_init, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, @@ -697,6 +711,7 @@ gf100_fifo = { .id_engine = gf100_fifo_id_engine, .uevent_init = gf100_fifo_uevent_init, .uevent_fini = gf100_fifo_uevent_fini, + .runq = &gf100_runq, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan, .oclass = &gf100_fifo_gpfifo_oclass }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index c4fa4fc68d46..efebdcdbeefc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -23,6 +23,7 @@ */ #include "chan.h" #include "chid.h" +#include "runq.h" #include "gk104.h" #include "cgrp.h" @@ -168,6 +169,10 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { {} }; +const struct nvkm_runq_func +gk104_runq = { +}; + void gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, struct nvkm_memory *mem, int nr) @@ -275,18 +280,8 @@ gk104_fifo_pbdma_init(struct gk104_fifo *fifo) nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1); } -int -gk104_fifo_pbdma_nr(struct gk104_fifo *fifo) -{ - struct nvkm_device *device = fifo->base.engine.subdev.device; - /* Determine number of PBDMAs by checking valid enable bits. */ - nvkm_wr32(device, 0x000204, 0xffffffff); - return hweight32(nvkm_rd32(device, 0x000204)); -} - const struct gk104_fifo_pbdma_func gk104_fifo_pbdma = { - .nr = gk104_fifo_pbdma_nr, .init = gk104_fifo_pbdma_init, }; @@ -1076,8 +1071,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) int pbid, ret, i, j; u32 *map; - fifo->pbdma_nr = fifo->func->pbdma->nr(fifo); - nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr); + fifo->pbdma_nr = fifo->func->runq_nr(&fifo->base); /* Read PBDMA->runlist(s) mapping from HW. */ if (!(map = kcalloc(fifo->pbdma_nr, sizeof(*map), GFP_KERNEL))) @@ -1195,6 +1189,7 @@ gk104_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = gk104_fifo_chid_nr, .chid_ctor = gf100_fifo_chid_ctor, + .runq_nr = gf100_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -1213,6 +1208,7 @@ gk104_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk104_fifo_runlist, .pbdma = &gk104_fifo_pbdma, + .runq = &gk104_runq, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index af6a004a6267..636091c7fcee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -82,7 +82,6 @@ void gk104_fifo_uevent_fini(struct nvkm_fifo *fifo); void gk104_fifo_uevent_init(struct nvkm_fifo *fifo); extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma; -int gk104_fifo_pbdma_nr(struct gk104_fifo *); void gk104_fifo_pbdma_init(struct gk104_fifo *); extern const struct nvkm_enum gk104_fifo_fault_access[]; extern const struct nvkm_enum gk104_fifo_fault_engine[]; @@ -106,7 +105,6 @@ extern const struct nvkm_enum gm107_fifo_fault_engine[]; extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; extern const struct gk104_fifo_pbdma_func gm200_fifo_pbdma; -int gm200_fifo_pbdma_nr(struct gk104_fifo *); extern const struct nvkm_enum gp100_fifo_fault_engine[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index b23d50d1b351..d6d86ad47ecb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -75,6 +75,7 @@ gk110_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = gk104_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, + .runq_nr = gf100_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -93,6 +94,7 @@ gk110_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .pbdma = &gk104_fifo_pbdma, + .runq = &gk104_runq, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 1dd937bdbbae..d81593722fa1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#include "runq.h" #include "gk104.h" #include "changk104.h" @@ -38,11 +39,14 @@ gk208_fifo_pbdma_init_timeout(struct gk104_fifo *fifo) const struct gk104_fifo_pbdma_func gk208_fifo_pbdma = { - .nr = gk104_fifo_pbdma_nr, .init = gk104_fifo_pbdma_init, .init_timeout = gk208_fifo_pbdma_init_timeout, }; +const struct nvkm_runq_func +gk208_runq = { +}; + static int gk208_fifo_chid_nr(struct nvkm_fifo *fifo) { @@ -55,6 +59,7 @@ gk208_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = gk208_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, + .runq_nr = gf100_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -73,6 +78,7 @@ gk208_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .pbdma = &gk208_fifo_pbdma, + .runq = &gk208_runq, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index d2e78d2a868a..11227cf55941 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -30,6 +30,7 @@ gk20a_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, + .runq_nr = gf100_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -48,6 +49,7 @@ gk20a_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .pbdma = &gk208_fifo_pbdma, + .runq = &gk208_runq, .cgrp = {{ }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 32ef88a90d1e..2dc89d3a0d0c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -115,6 +115,7 @@ gm107_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = gm107_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, + .runq_nr = gf100_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -133,6 +134,7 @@ gm107_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gk208_fifo_pbdma, + .runq = &gk208_runq, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 74891833926e..f24551c701e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -27,15 +27,13 @@ #include int -gm200_fifo_pbdma_nr(struct gk104_fifo *fifo) +gm200_fifo_runq_nr(struct nvkm_fifo *fifo) { - struct nvkm_device *device = fifo->base.engine.subdev.device; - return nvkm_rd32(device, 0x002004) & 0x000000ff; + return nvkm_rd32(fifo->engine.subdev.device, 0x002004) & 0x000000ff; } const struct gk104_fifo_pbdma_func gm200_fifo_pbdma = { - .nr = gm200_fifo_pbdma_nr, .init = gk104_fifo_pbdma_init, .init_timeout = gk208_fifo_pbdma_init_timeout, }; @@ -52,6 +50,7 @@ gm200_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, + .runq_nr = gm200_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -70,6 +69,7 @@ gm200_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .runq = &gk208_runq, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index c1ad59d1223b..60bc5d314324 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -87,6 +87,7 @@ gp100_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, + .runq_nr = gm200_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -105,6 +106,7 @@ gp100_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .runq = &gk208_runq, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 9e876bd871bb..f7db1b4db0dc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -21,6 +21,7 @@ */ #include "chan.h" #include "cgrp.h" +#include "runq.h" #include "gk104.h" #include "changk104.h" @@ -33,6 +34,10 @@ static const struct nvkm_chan_func gv100_chan = { }; +const struct nvkm_runq_func +gv100_runq = { +}; + void gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan, struct nvkm_memory *memory, u32 offset) @@ -302,6 +307,7 @@ gv100_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, + .runq_nr = gm200_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -319,6 +325,7 @@ gv100_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gv100_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .runq = &gv100_runq, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan, .ctor = gv100_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 80280841cf81..daa594669985 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -22,6 +22,7 @@ struct nvkm_fifo_func { int (*oneinit)(struct nvkm_fifo *); int (*chid_nr)(struct nvkm_fifo *); int (*chid_ctor)(struct nvkm_fifo *, int nr); + int (*runq_nr)(struct nvkm_fifo *); int (*info)(struct nvkm_fifo *, u64 mthd, u64 *data); void (*init)(struct nvkm_fifo *); @@ -61,11 +62,12 @@ struct nvkm_fifo_func { } *runlist; const struct gk104_fifo_pbdma_func { - int (*nr)(struct gk104_fifo *); void (*init)(struct gk104_fifo *); void (*init_timeout)(struct gk104_fifo *); } *pbdma; + const struct nvkm_runq_func *runq; + struct nvkm_fifo_func_cgrp { struct nvkm_sclass user; const struct nvkm_cgrp_func *func; @@ -104,6 +106,7 @@ int nv50_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_chan_func g84_chan; int gf100_fifo_chid_ctor(struct nvkm_fifo *, int); +int gf100_fifo_runq_nr(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); int gk104_fifo_chid_nr(struct nvkm_fifo *); @@ -113,19 +116,25 @@ void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int); +extern const struct nvkm_runq_func gk104_runq; int gk110_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_cgrp_func gk110_cgrp; extern const struct nvkm_chan_func gk110_chan; +extern const struct nvkm_runq_func gk208_runq; + void gm107_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); extern const struct nvkm_fifo_func_mmu_fault gm107_fifo_mmu_fault; extern const struct nvkm_chan_func gm107_chan; int gm200_fifo_chid_nr(struct nvkm_fifo *); +int gm200_fifo_runq_nr(struct nvkm_fifo *); void gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); +extern const struct nvkm_runq_func gv100_runq; + extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault; int nvkm_uchan_new(struct nvkm_fifo *, struct nvkm_cgrp *, const struct nvkm_oclass *, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c new file mode 100644 index 000000000000..33bcf5fb3ef0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c @@ -0,0 +1,45 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "runq.h" +#include "priv.h" + +void +nvkm_runq_del(struct nvkm_runq *runq) +{ + list_del(&runq->head); + kfree(runq); +} + +struct nvkm_runq * +nvkm_runq_new(struct nvkm_fifo *fifo, int pbid) +{ + struct nvkm_runq *runq; + + if (!(runq = kzalloc(sizeof(*runq), GFP_KERNEL))) + return NULL; + + runq->func = fifo->func->runq; + runq->fifo = fifo; + runq->id = pbid; + list_add_tail(&runq->head, &fifo->runqs); + return runq; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h new file mode 100644 index 000000000000..1832a14488c3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_RUNQ_H__ +#define __NVKM_RUNQ_H__ +#include + +struct nvkm_runq { + const struct nvkm_runq_func { + } *func; + struct nvkm_fifo *fifo; + int id; + + struct list_head head; +}; + +struct nvkm_runq *nvkm_runq_new(struct nvkm_fifo *, int pbid); +void nvkm_runq_del(struct nvkm_runq *); + +#define nvkm_runq_foreach_cond(runq,fifo,cond) nvkm_list_foreach(runq, &(fifo)->runqs, head, (cond)) + +#define RUNQ_PRINT(r,l,p,f,a...) \ + nvkm_printk__(&(r)->fifo->engine.subdev, NV_DBG_##l, p, "PBDMA%d:"f, (r)->id, ##a) +#define RUNQ_ERROR(r,f,a...) RUNQ_PRINT((r), ERROR, err, " "f"\n", ##a) +#define RUNQ_DEBUG(r,f,a...) RUNQ_PRINT((r), DEBUG, info, " "f"\n", ##a) +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index fbc67b84a8b1..6d0431610235 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -99,7 +99,6 @@ tu102_fifo_pbdma_init(struct gk104_fifo *fifo) static const struct gk104_fifo_pbdma_func tu102_fifo_pbdma = { - .nr = gm200_fifo_pbdma_nr, .init = tu102_fifo_pbdma_init, .init_timeout = gk208_fifo_pbdma_init_timeout, }; @@ -443,6 +442,7 @@ tu102_fifo = { .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, + .runq_nr = gm200_fifo_runq_nr, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -460,6 +460,7 @@ tu102_fifo = { .recover_chan = tu102_fifo_recover_chan, .runlist = &tu102_fifo_runlist, .pbdma = &tu102_fifo_pbdma, + .runq = &gv100_runq, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan, .ctor = tu102_fifo_gpfifo_new }, }; -- cgit v1.2.3 From d94470e9d150aaf0fff26f09852da22ae951956f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:24 +1000 Subject: drm/nouveau/fifo: add common runlist/engine topology Creates an nvkm_runl for each runlist on the GPU, and an nvkm_engn for each engine that is reachable from a runlist. - basically what gk104- already does, but extended to all chips - adds per-runlist CHID allocators (Ampere) - splits g98/gt2xx out from g84 (different target engines) Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/os.h | 15 +++ drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 14 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 19 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 37 ++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c | 77 ++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 35 +++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 102 +++++++++++++------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 9 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 4 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 4 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 9 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 4 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 9 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 17 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 29 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 4 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 4 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 13 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 17 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h | 5 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 19 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 112 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 55 ++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 9 ++ 26 files changed, 583 insertions(+), 43 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h index e8705216ae4e..4486d9862849 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h @@ -35,6 +35,21 @@ nvkm_blob_dtor(struct nvkm_blob *blob) blob->size = 0; } +#define nvkm_list_find_next(p,h,m,c) ({ \ + typeof(p) _p = NULL; \ + list_for_each_entry_continue(p, (h), m) { \ + if (c) { \ + _p = p; \ + break; \ + } \ + } \ + _p; \ +}) +#define nvkm_list_find(p,h,m,c) \ + (p = container_of((h), typeof(*p), m), nvkm_list_find_next(p, (h), m, (c))) +#define nvkm_list_foreach(p,h,m,c) \ + for (p = nvkm_list_find(p, (h), m, (c)); p; p = nvkm_list_find_next(p, (h), m, (c))) + /*FIXME: remove after */ #define nvkm_fifo_chan nvkm_chan #define nvkm_fifo_chan_func nvkm_chan_func diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 895eb262345e..1e12697beae2 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -41,6 +41,7 @@ struct nvkm_fifo { struct nvkm_chid *cgid; struct list_head runqs; + struct list_head runls; DECLARE_BITMAP(mask, NVKM_FIFO_CHID_NR); int nr; @@ -71,6 +72,7 @@ int nv17_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct int nv40_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int nv50_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int g84_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); +int g98_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int gf100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int gk104_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int gk110_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 532231f1a0f5..4f5921a2aeb0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -1095,7 +1095,7 @@ nv98_chipset = { .volt = { 0x00000001, nv40_volt_new }, .disp = { 0x00000001, g94_disp_new }, .dma = { 0x00000001, nv50_dma_new }, - .fifo = { 0x00000001, g84_fifo_new }, + .fifo = { 0x00000001, g98_fifo_new }, .gr = { 0x00000001, g84_gr_new }, .mspdec = { 0x00000001, g98_mspdec_new }, .msppp = { 0x00000001, g98_msppp_new }, @@ -1161,7 +1161,7 @@ nva3_chipset = { .ce = { 0x00000001, gt215_ce_new }, .disp = { 0x00000001, gt215_disp_new }, .dma = { 0x00000001, nv50_dma_new }, - .fifo = { 0x00000001, g84_fifo_new }, + .fifo = { 0x00000001, g98_fifo_new }, .gr = { 0x00000001, gt215_gr_new }, .mpeg = { 0x00000001, g84_mpeg_new }, .mspdec = { 0x00000001, gt215_mspdec_new }, @@ -1195,7 +1195,7 @@ nva5_chipset = { .ce = { 0x00000001, gt215_ce_new }, .disp = { 0x00000001, gt215_disp_new }, .dma = { 0x00000001, nv50_dma_new }, - .fifo = { 0x00000001, g84_fifo_new }, + .fifo = { 0x00000001, g98_fifo_new }, .gr = { 0x00000001, gt215_gr_new }, .mspdec = { 0x00000001, gt215_mspdec_new }, .msppp = { 0x00000001, gt215_msppp_new }, @@ -1228,7 +1228,7 @@ nva8_chipset = { .ce = { 0x00000001, gt215_ce_new }, .disp = { 0x00000001, gt215_disp_new }, .dma = { 0x00000001, nv50_dma_new }, - .fifo = { 0x00000001, g84_fifo_new }, + .fifo = { 0x00000001, g98_fifo_new }, .gr = { 0x00000001, gt215_gr_new }, .mspdec = { 0x00000001, gt215_mspdec_new }, .msppp = { 0x00000001, gt215_msppp_new }, @@ -1259,7 +1259,7 @@ nvaa_chipset = { .volt = { 0x00000001, nv40_volt_new }, .disp = { 0x00000001, mcp77_disp_new }, .dma = { 0x00000001, nv50_dma_new }, - .fifo = { 0x00000001, g84_fifo_new }, + .fifo = { 0x00000001, g98_fifo_new }, .gr = { 0x00000001, gt200_gr_new }, .mspdec = { 0x00000001, g98_mspdec_new }, .msppp = { 0x00000001, g98_msppp_new }, @@ -1291,7 +1291,7 @@ nvac_chipset = { .volt = { 0x00000001, nv40_volt_new }, .disp = { 0x00000001, mcp77_disp_new }, .dma = { 0x00000001, nv50_dma_new }, - .fifo = { 0x00000001, g84_fifo_new }, + .fifo = { 0x00000001, g98_fifo_new }, .gr = { 0x00000001, mcp79_gr_new }, .mspdec = { 0x00000001, g98_mspdec_new }, .msppp = { 0x00000001, g98_msppp_new }, @@ -1325,7 +1325,7 @@ nvaf_chipset = { .ce = { 0x00000001, gt215_ce_new }, .disp = { 0x00000001, mcp89_disp_new }, .dma = { 0x00000001, nv50_dma_new }, - .fifo = { 0x00000001, g84_fifo_new }, + .fifo = { 0x00000001, g98_fifo_new }, .gr = { 0x00000001, mcp89_gr_new }, .mspdec = { 0x00000001, gt215_mspdec_new }, .msppp = { 0x00000001, gt215_msppp_new }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index 447001db070e..a92a88a72e59 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -2,6 +2,7 @@ nvkm-y += nvkm/engine/fifo/base.o nvkm-y += nvkm/engine/fifo/chan.o nvkm-y += nvkm/engine/fifo/chid.o +nvkm-y += nvkm/engine/fifo/runl.o nvkm-y += nvkm/engine/fifo/runq.o nvkm-y += nvkm/engine/fifo/nv04.o @@ -10,6 +11,7 @@ nvkm-y += nvkm/engine/fifo/nv17.o nvkm-y += nvkm/engine/fifo/nv40.o nvkm-y += nvkm/engine/fifo/nv50.o nvkm-y += nvkm/engine/fifo/g84.o +nvkm-y += nvkm/engine/fifo/g98.o nvkm-y += nvkm/engine/fifo/gf100.o nvkm-y += nvkm/engine/fifo/gk104.o nvkm-y += nvkm/engine/fifo/gk110.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 806ca8986eb5..60d5cbbe4381 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -24,6 +24,7 @@ #include "priv.h" #include "chan.h" #include "chid.h" +#include "runl.h" #include "runq.h" #include @@ -236,6 +237,8 @@ static int nvkm_fifo_oneinit(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + struct nvkm_runl *runl; + struct nvkm_engn *engn; int ret, nr, i; /* Initialise CHID/CGID allocator(s) on GPUs where they aren't per-runlist. */ @@ -253,6 +256,18 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) } } + /* Create runlists. */ + ret = fifo->func->runl_ctor(fifo); + if (ret) + return ret; + + nvkm_runl_foreach(runl, fifo) { + RUNL_DEBUG(runl, ""); + nvkm_runl_foreach_engn(engn, runl) { + ENGN_DEBUG(engn, ""); + } + } + if (fifo->func->oneinit) return fifo->func->oneinit(fifo); @@ -269,9 +284,12 @@ static void * nvkm_fifo_dtor(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + struct nvkm_runl *runl, *runt; struct nvkm_runq *runq, *rtmp; void *data = fifo; + list_for_each_entry_safe(runl, runt, &fifo->runls, head) + nvkm_runl_del(runl); list_for_each_entry_safe(runq, rtmp, &fifo->runqs, head) nvkm_runq_del(runq); @@ -306,6 +324,7 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, fifo->func = func; INIT_LIST_HEAD(&fifo->runqs); + INIT_LIST_HEAD(&fifo->runls); spin_lock_init(&fifo->lock); mutex_init(&fifo->mutex); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index dbb9df6f8eb5..3d242350fdee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "chan.h" +#include "runl.h" #include "nv50.h" #include "channv50.h" @@ -32,21 +33,25 @@ const struct nvkm_chan_func g84_chan = { }; -static void +const struct nvkm_engn_func +g84_engn = { +}; + +void g84_fifo_uevent_fini(struct nvkm_fifo *fifo) { struct nvkm_device *device = fifo->engine.subdev.device; nvkm_mask(device, 0x002140, 0x40000000, 0x00000000); } -static void +void g84_fifo_uevent_init(struct nvkm_fifo *fifo) { struct nvkm_device *device = fifo->engine.subdev.device; nvkm_mask(device, 0x002140, 0x40000000, 0x40000000); } -static struct nvkm_engine * +struct nvkm_engine * g84_fifo_id_engine(struct nvkm_fifo *fifo, int engi) { struct nvkm_device *device = fifo->engine.subdev.device; @@ -92,7 +97,7 @@ g84_fifo_id_engine(struct nvkm_fifo *fifo, int engi) return nvkm_device_engine(fifo->engine.subdev.device, type, 0); } -static int +int g84_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) { switch (engine->subdev.type) { @@ -114,12 +119,33 @@ g84_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) } } +static int +g84_fifo_runl_ctor(struct nvkm_fifo *fifo) +{ + struct nvkm_runl *runl; + + runl = nvkm_runl_new(fifo, 0, 0, 0); + if (IS_ERR(runl)) + return PTR_ERR(runl); + + nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_SW, 0); + nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_DMAOBJ, 0); + nvkm_runl_add(runl, 1, fifo->func->engn, NVKM_ENGINE_GR, 0); + nvkm_runl_add(runl, 2, fifo->func->engn, NVKM_ENGINE_MPEG, 0); + nvkm_runl_add(runl, 3, fifo->func->engn, NVKM_ENGINE_ME, 0); + nvkm_runl_add(runl, 4, fifo->func->engn, NVKM_ENGINE_VP, 0); + nvkm_runl_add(runl, 5, fifo->func->engn, NVKM_ENGINE_CIPHER, 0); + nvkm_runl_add(runl, 6, fifo->func->engn, NVKM_ENGINE_BSP, 0); + return 0; +} + static const struct nvkm_fifo_func g84_fifo = { .dtor = nv50_fifo_dtor, .oneinit = nv50_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = nv50_fifo_chid_ctor, + .runl_ctor = g84_fifo_runl_ctor, .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = g84_fifo_engine_id, @@ -128,6 +154,9 @@ g84_fifo = { .start = nv04_fifo_start, .uevent_init = g84_fifo_uevent_init, .uevent_fini = g84_fifo_uevent_fini, + .runl = &nv50_runl, + .engn = &g84_engn, + .engn_sw = &nv50_engn_sw, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan, .oclass = &g84_fifo_gpfifo_oclass }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c new file mode 100644 index 000000000000..39177ec0eca6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c @@ -0,0 +1,77 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "chan.h" +#include "runl.h" + +#include "nv50.h" +#include "channv50.h" + +#include + +static int +g98_fifo_runl_ctor(struct nvkm_fifo *fifo) +{ + struct nvkm_runl *runl; + + runl = nvkm_runl_new(fifo, 0, 0, 0); + if (IS_ERR(runl)) + return PTR_ERR(runl); + + nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_SW, 0); + nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_DMAOBJ, 0); + nvkm_runl_add(runl, 1, fifo->func->engn, NVKM_ENGINE_GR, 0); + nvkm_runl_add(runl, 2, fifo->func->engn, NVKM_ENGINE_MSPPP, 0); + nvkm_runl_add(runl, 3, fifo->func->engn, NVKM_ENGINE_CE, 0); + nvkm_runl_add(runl, 4, fifo->func->engn, NVKM_ENGINE_MSPDEC, 0); + nvkm_runl_add(runl, 5, fifo->func->engn, NVKM_ENGINE_SEC, 0); + nvkm_runl_add(runl, 6, fifo->func->engn, NVKM_ENGINE_MSVLD, 0); + return 0; +} + +static const struct nvkm_fifo_func +g98_fifo = { + .dtor = nv50_fifo_dtor, + .oneinit = nv50_fifo_oneinit, + .chid_nr = nv50_fifo_chid_nr, + .chid_ctor = nv50_fifo_chid_ctor, + .runl_ctor = g98_fifo_runl_ctor, + .init = nv50_fifo_init, + .intr = nv04_fifo_intr, + .engine_id = g84_fifo_engine_id, + .id_engine = g84_fifo_id_engine, + .pause = nv04_fifo_pause, + .start = nv04_fifo_start, + .uevent_init = g84_fifo_uevent_init, + .uevent_fini = g84_fifo_uevent_fini, + .runl = &nv50_runl, + .engn = &g84_engn, + .engn_sw = &nv50_engn_sw, + .cgrp = {{ }, &nv04_cgrp }, + .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan, .oclass = &g84_fifo_gpfifo_oclass }, +}; + +int +g98_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_fifo **pfifo) +{ + return nv50_fifo_new_(&g98_fifo, device, type, inst, pfifo); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 14d8bc3b5956..43cce02151d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -23,6 +23,7 @@ */ #include "chan.h" #include "chid.h" +#include "runl.h" #include "runq.h" #include "gf100.h" @@ -55,6 +56,14 @@ static const struct nvkm_chan_func gf100_chan = { }; +static const struct nvkm_engn_func +gf100_engn = { +}; + +const struct nvkm_engn_func +gf100_engn_sw = { +}; + static const struct nvkm_bitfield gf100_fifo_pbdma_intr[] = { /* { 0x00008000, "" } seen with null ib push */ @@ -163,6 +172,10 @@ gf100_fifo_runlist_insert(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan) mutex_unlock(&fifo->base.mutex); } +static const struct nvkm_runl_func +gf100_runl = { +}; + static struct nvkm_engine * gf100_fifo_id_engine(struct nvkm_fifo *fifo, int engi) { @@ -630,6 +643,25 @@ gf100_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */ } +static int +gf100_fifo_runl_ctor(struct nvkm_fifo *fifo) +{ + struct nvkm_runl *runl; + + runl = nvkm_runl_new(fifo, 0, 0, 0); + if (IS_ERR(runl)) + return PTR_ERR(runl); + + nvkm_runl_add(runl, 0, fifo->func->engn, NVKM_ENGINE_GR, 0); + nvkm_runl_add(runl, 1, fifo->func->engn, NVKM_ENGINE_MSPDEC, 0); + nvkm_runl_add(runl, 2, fifo->func->engn, NVKM_ENGINE_MSPPP, 0); + nvkm_runl_add(runl, 3, fifo->func->engn, NVKM_ENGINE_MSVLD, 0); + nvkm_runl_add(runl, 4, fifo->func->engn, NVKM_ENGINE_CE, 0); + nvkm_runl_add(runl, 5, fifo->func->engn, NVKM_ENGINE_CE, 1); + nvkm_runl_add(runl, 15, &gf100_engn_sw, NVKM_ENGINE_SW, 0); + return 0; +} + int gf100_fifo_runq_nr(struct nvkm_fifo *fifo) { @@ -703,6 +735,7 @@ gf100_fifo = { .chid_nr = nv50_fifo_chid_nr, .chid_ctor = gf100_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, + .runl_ctor = gf100_fifo_runl_ctor, .init = gf100_fifo_init, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, @@ -711,7 +744,9 @@ gf100_fifo = { .id_engine = gf100_fifo_id_engine, .uevent_init = gf100_fifo_uevent_init, .uevent_fini = gf100_fifo_uevent_fini, + .runl = &gf100_runl, .runq = &gf100_runq, + .engn = &gf100_engn, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan, .oclass = &gf100_fifo_gpfifo_oclass }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index efebdcdbeefc..eaf61c07fafc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -23,6 +23,7 @@ */ #include "chan.h" #include "chid.h" +#include "runl.h" #include "runq.h" #include "gk104.h" @@ -91,6 +92,14 @@ gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, status->chan == &status->next ? "*" : " "); } +const struct nvkm_engn_func +gk104_engn = { +}; + +const struct nvkm_engn_func +gk104_engn_ce = { +}; + void gk104_fifo_uevent_fini(struct nvkm_fifo *fifo) { @@ -169,6 +178,12 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { {} }; +static u32 +gk104_runq_runm(struct nvkm_runq *runq) +{ + return nvkm_rd32(runq->fifo->engine.subdev.device, 0x002390 + (runq->id * 0x04)); +} + const struct nvkm_runq_func gk104_runq = { }; @@ -273,6 +288,10 @@ gk104_fifo_runlist = { .commit = gk104_fifo_runlist_commit, }; +static const struct nvkm_runl_func +gk104_runl = { +}; + void gk104_fifo_pbdma_init(struct gk104_fifo *fifo) { @@ -1054,6 +1073,52 @@ gk104_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002140, 0x7fffffff); } +int +gk104_fifo_runl_ctor(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_top_device *tdev; + struct nvkm_runl *runl; + struct nvkm_runq *runq; + const struct nvkm_engn_func *func; + + nvkm_list_foreach(tdev, &device->top->device, head, tdev->runlist >= 0) { + runl = nvkm_runl_get(fifo, tdev->runlist, tdev->runlist); + if (!runl) { + runl = nvkm_runl_new(fifo, tdev->runlist, tdev->runlist, 0); + if (IS_ERR(runl)) + return PTR_ERR(runl); + + nvkm_runq_foreach_cond(runq, fifo, gk104_runq_runm(runq) & BIT(runl->id)) { + if (WARN_ON(runl->runq_nr == ARRAY_SIZE(runl->runq))) + return -ENOMEM; + + runl->runq[runl->runq_nr++] = runq; + } + + } + + if (tdev->engine < 0) + continue; + + switch (tdev->type) { + case NVKM_ENGINE_CE: + func = fifo->func->engn_ce; + break; + case NVKM_ENGINE_GR: + nvkm_runl_add(runl, 15, &gf100_engn_sw, NVKM_ENGINE_SW, 0); + fallthrough; + default: + func = fifo->func->engn; + break; + } + + nvkm_runl_add(runl, tdev->engine, func, tdev->type, tdev->inst); + } + + return 0; +} + int gk104_fifo_chid_nr(struct nvkm_fifo *fifo) { @@ -1068,48 +1133,19 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) struct nvkm_device *device = subdev->device; struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); struct nvkm_top_device *tdev; - int pbid, ret, i, j; - u32 *map; + int ret, i, j; fifo->pbdma_nr = fifo->func->runq_nr(&fifo->base); - /* Read PBDMA->runlist(s) mapping from HW. */ - if (!(map = kcalloc(fifo->pbdma_nr, sizeof(*map), GFP_KERNEL))) - return -ENOMEM; - - for (i = 0; i < fifo->pbdma_nr; i++) - map[i] = nvkm_rd32(device, 0x002390 + (i * 0x04)); - /* Determine runlist configuration from topology device info. */ list_for_each_entry(tdev, &device->top->device, head) { const int engn = tdev->engine; - char _en[16], *en; if (engn < 0) continue; - /* Determine which PBDMA handles requests for this engine. */ - for (j = 0, pbid = -1; j < fifo->pbdma_nr; j++) { - if (map[j] & BIT(tdev->runlist)) { - pbid = j; - break; - } - } - fifo->engine[engn].engine = nvkm_device_engine(device, tdev->type, tdev->inst); - if (!fifo->engine[engn].engine) { - snprintf(_en, sizeof(_en), "%s, %d", - nvkm_subdev_type[tdev->type], tdev->inst); - en = _en; - } else { - en = fifo->engine[engn].engine->subdev.name; - } - - nvkm_debug(subdev, "engine %2d: runlist %2d pbdma %2d (%s)\n", - tdev->engine, tdev->runlist, pbid, en); - fifo->engine[engn].runl = tdev->runlist; - fifo->engine[engn].pbid = pbid; fifo->engine_nr = max(fifo->engine_nr, engn + 1); fifo->runlist[tdev->runlist].engm |= BIT(engn); fifo->runlist[tdev->runlist].engm_sw |= BIT(engn); @@ -1118,8 +1154,6 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) fifo->runlist_nr = max(fifo->runlist_nr, tdev->runlist + 1); } - kfree(map); - for (i = 0; i < fifo->runlist_nr; i++) { for (j = 0; j < ARRAY_SIZE(fifo->runlist[i].mem); j++) { ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, @@ -1190,6 +1224,7 @@ gk104_fifo = { .chid_nr = gk104_fifo_chid_nr, .chid_ctor = gf100_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -1208,7 +1243,10 @@ gk104_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk104_fifo_runlist, .pbdma = &gk104_fifo_pbdma, + .runl = &gk104_runl, .runq = &gk104_runq, + .engn = &gk104_engn, + .engn_ce = &gk104_engn_ce, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index d6d86ad47ecb..08f5b0684510 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -24,6 +24,7 @@ #include "cgrp.h" #include "chan.h" #include "chid.h" +#include "runl.h" #include "gk104.h" #include "changk104.h" @@ -57,6 +58,10 @@ gk110_fifo_runlist = { .commit = gk104_fifo_runlist_commit, }; +const struct nvkm_runl_func +gk110_runl = { +}; + int gk110_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) { @@ -76,6 +81,7 @@ gk110_fifo = { .chid_nr = gk104_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -94,7 +100,10 @@ gk110_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .pbdma = &gk104_fifo_pbdma, + .runl = &gk110_runl, .runq = &gk104_runq, + .engn = &gk104_engn, + .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index d81593722fa1..c58343b5c49e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -60,6 +60,7 @@ gk208_fifo = { .chid_nr = gk208_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -78,7 +79,10 @@ gk208_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .pbdma = &gk208_fifo_pbdma, + .runl = &gk110_runl, .runq = &gk208_runq, + .engn = &gk104_engn, + .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 11227cf55941..9a1c1ca95121 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -31,6 +31,7 @@ gk20a_fifo = { .chid_nr = nv50_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -49,7 +50,10 @@ gk20a_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .pbdma = &gk208_fifo_pbdma, + .runl = &gk110_runl, .runq = &gk208_runq, + .engn = &gk104_engn, + .engn_ce = &gk104_engn_ce, .cgrp = {{ }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 2dc89d3a0d0c..44dbebf06992 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -23,6 +23,7 @@ */ #include "priv.h" #include "chan.h" +#include "runl.h" #include "gk104.h" #include "changk104.h" @@ -51,6 +52,10 @@ gm107_fifo_runlist = { .commit = gk104_fifo_runlist_commit, }; +const struct nvkm_runl_func +gm107_runl = { +}; + const struct nvkm_enum gm107_fifo_fault_engine[] = { { 0x01, "DISPLAY" }, @@ -116,6 +121,7 @@ gm107_fifo = { .chid_nr = gm107_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -134,7 +140,10 @@ gm107_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gk208_fifo_pbdma, + .runl = &gm107_runl, .runq = &gk208_runq, + .engn = &gk104_engn, + .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index f24551c701e1..e9f3c5f08ca8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -51,6 +51,7 @@ gm200_fifo = { .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -69,7 +70,10 @@ gm200_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .runl = &gm107_runl, .runq = &gk208_runq, + .engn = &gk104_engn, + .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, .chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 60bc5d314324..6fea0a5525df 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#include "runl.h" #include "gk104.h" #include "changk104.h" @@ -28,6 +29,10 @@ #include +static const struct nvkm_runl_func +gp100_runl = { +}; + const struct nvkm_enum gp100_fifo_fault_engine[] = { { 0x01, "DISPLAY" }, @@ -88,6 +93,7 @@ gp100_fifo = { .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -106,7 +112,10 @@ gp100_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .runl = &gp100_runl, .runq = &gk208_runq, + .engn = &gk104_engn, + .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index f7db1b4db0dc..21246a0f319d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -21,6 +21,7 @@ */ #include "chan.h" #include "cgrp.h" +#include "runl.h" #include "runq.h" #include "gk104.h" @@ -34,6 +35,14 @@ static const struct nvkm_chan_func gv100_chan = { }; +const struct nvkm_engn_func +gv100_engn = { +}; + +const struct nvkm_engn_func +gv100_engn_ce = { +}; + const struct nvkm_runq_func gv100_runq = { }; @@ -70,6 +79,10 @@ gv100_fifo_runlist = { .commit = gk104_fifo_runlist_commit, }; +static const struct nvkm_runl_func +gv100_runl = { +}; + const struct nvkm_enum gv100_fifo_fault_gpcclient[] = { { 0x00, "T1_0" }, @@ -308,6 +321,7 @@ gv100_fifo = { .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -325,7 +339,10 @@ gv100_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gv100_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .runl = &gv100_runl, .runq = &gv100_runq, + .engn = &gv100_engn, + .engn_ce = &gv100_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan, .ctor = gv100_fifo_gpfifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 18fa5b933e9e..ce965d6aa874 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -24,6 +24,7 @@ #include "cgrp.h" #include "chan.h" #include "chid.h" +#include "runl.h" #include "nv04.h" #include "channv04.h" @@ -123,6 +124,10 @@ const struct nvkm_cgrp_func nv04_cgrp = { }; +const struct nvkm_engn_func +nv04_engn = { +}; + void nv04_fifo_pause(struct nvkm_fifo *base, unsigned long *pflags) __acquires(fifo->base.lock) @@ -173,6 +178,10 @@ __releases(fifo->base.lock) spin_unlock_irqrestore(&fifo->base.lock, flags); } +const struct nvkm_runl_func +nv04_runl = { +}; + struct nvkm_engine * nv04_fifo_id_engine(struct nvkm_fifo *fifo, int engi) { @@ -434,6 +443,22 @@ nv04_fifo_init(struct nvkm_fifo *fifo) nvkm_wr32(device, NV03_PFIFO_CACHES, 1); } +int +nv04_fifo_runl_ctor(struct nvkm_fifo *fifo) +{ + struct nvkm_runl *runl; + + runl = nvkm_runl_new(fifo, 0, 0, 0); + if (IS_ERR(runl)) + return PTR_ERR(runl); + + nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_SW, 0); + nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_DMAOBJ, 0); + nvkm_runl_add(runl, 1, fifo->func->engn , NVKM_ENGINE_GR, 0); + nvkm_runl_add(runl, 2, fifo->func->engn , NVKM_ENGINE_MPEG, 0); /* NV31- */ + return 0; +} + int nv04_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) { @@ -472,12 +497,16 @@ static const struct nvkm_fifo_func nv04_fifo = { .chid_nr = nv04_fifo_chid_nr, .chid_ctor = nv04_fifo_chid_ctor, + .runl_ctor = nv04_fifo_runl_ctor, .init = nv04_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, + .runl = &nv04_runl, + .engn = &nv04_engn, + .engn_sw = &nv04_engn, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, NV03_CHANNEL_DMA }, &nv04_chan, .oclass = &nv04_fifo_dma_oclass }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index bc25520cb39b..84416440a822 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -57,12 +57,16 @@ static const struct nvkm_fifo_func nv10_fifo = { .chid_nr = nv10_fifo_chid_nr, .chid_ctor = nv04_fifo_chid_ctor, + .runl_ctor = nv04_fifo_runl_ctor, .init = nv04_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, + .runl = &nv04_runl, + .engn = &nv04_engn, + .engn_sw = &nv04_engn, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, NV10_CHANNEL_DMA }, &nv10_chan, .oclass = &nv10_fifo_dma_oclass }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index dd254d88d008..28ae10a78ee4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -89,12 +89,16 @@ static const struct nvkm_fifo_func nv17_fifo = { .chid_nr = nv10_fifo_chid_nr, .chid_ctor = nv04_fifo_chid_ctor, + .runl_ctor = nv04_fifo_runl_ctor, .init = nv17_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, + .runl = &nv04_runl, + .engn = &nv04_engn, + .engn_sw = &nv04_engn, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, NV17_CHANNEL_DMA }, &nv17_chan, .oclass = &nv17_fifo_dma_oclass }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index c87d995e4fd1..492609780c9b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -23,6 +23,7 @@ */ #include "chan.h" #include "chid.h" +#include "runl.h" #include "nv04.h" #include "channv04.h" @@ -65,6 +66,14 @@ static const struct nvkm_chan_func nv40_chan = { }; +static const struct nvkm_engn_func +nv40_engn = { +}; + +static const struct nvkm_engn_func +nv40_engn_sw = { +}; + static void nv40_fifo_init(struct nvkm_fifo *fifo) { @@ -120,12 +129,16 @@ static const struct nvkm_fifo_func nv40_fifo = { .chid_nr = nv10_fifo_chid_nr, .chid_ctor = nv04_fifo_chid_ctor, + .runl_ctor = nv04_fifo_runl_ctor, .init = nv40_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, + .runl = &nv04_runl, + .engn = &nv40_engn, + .engn_sw = &nv40_engn_sw, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, NV40_CHANNEL_DMA }, &nv40_chan, .oclass = &nv40_fifo_dma_oclass }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 13c514acc9d7..e4a7ef5aa461 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -23,6 +23,7 @@ */ #include "chan.h" #include "chid.h" +#include "runl.h" #include "nv50.h" #include "channv50.h" @@ -35,6 +36,14 @@ static const struct nvkm_chan_func nv50_chan = { }; +static const struct nvkm_engn_func +nv50_engn = { +}; + +const struct nvkm_engn_func +nv50_engn_sw = { +}; + static void nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo) { @@ -65,6 +74,10 @@ nv50_fifo_runlist_update(struct nv50_fifo *fifo) mutex_unlock(&fifo->base.mutex); } +const struct nvkm_runl_func +nv50_runl = { +}; + void nv50_fifo_init(struct nvkm_fifo *base) { @@ -153,12 +166,16 @@ nv50_fifo = { .oneinit = nv50_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = nv50_fifo_chid_ctor, + .runl_ctor = nv04_fifo_runl_ctor, .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, + .runl = &nv50_runl, + .engn = &nv50_engn, + .engn_sw = &nv50_engn_sw, .cgrp = {{ }, &nv04_cgrp }, .chan = {{ 0, 0, NV50_CHANNEL_GPFIFO }, &nv50_chan, .oclass = &nv50_fifo_gpfifo_oclass }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h index 0111e7e5a4e3..9a23a84ea7f4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h @@ -17,4 +17,9 @@ void *nv50_fifo_dtor(struct nvkm_fifo *); int nv50_fifo_oneinit(struct nvkm_fifo *); void nv50_fifo_init(struct nvkm_fifo *); void nv50_fifo_runlist_update(struct nv50_fifo *); + +int g84_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); +struct nvkm_engine *g84_fifo_id_engine(struct nvkm_fifo *, int); +void g84_fifo_uevent_init(struct nvkm_fifo *); +void g84_fifo_uevent_fini(struct nvkm_fifo *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index daa594669985..93b8b726214e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -23,6 +23,7 @@ struct nvkm_fifo_func { int (*chid_nr)(struct nvkm_fifo *); int (*chid_ctor)(struct nvkm_fifo *, int nr); int (*runq_nr)(struct nvkm_fifo *); + int (*runl_ctor)(struct nvkm_fifo *); int (*info)(struct nvkm_fifo *, u64 mthd, u64 *data); void (*init)(struct nvkm_fifo *); @@ -66,7 +67,11 @@ struct nvkm_fifo_func { void (*init_timeout)(struct gk104_fifo *); } *pbdma; + const struct nvkm_runl_func *runl; const struct nvkm_runq_func *runq; + const struct nvkm_engn_func *engn; + const struct nvkm_engn_func *engn_sw; + const struct nvkm_engn_func *engn_ce; struct nvkm_fifo_func_cgrp { struct nvkm_sclass user; @@ -90,26 +95,34 @@ int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvk struct nvkm_fifo *); int nv04_fifo_chid_ctor(struct nvkm_fifo *, int); +int nv04_fifo_runl_ctor(struct nvkm_fifo *); void nv04_fifo_init(struct nvkm_fifo *); void nv04_fifo_intr(struct nvkm_fifo *); int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *nv04_fifo_id_engine(struct nvkm_fifo *, int); void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); +extern const struct nvkm_runl_func nv04_runl; +extern const struct nvkm_engn_func nv04_engn; extern const struct nvkm_cgrp_func nv04_cgrp; int nv10_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_ctor(struct nvkm_fifo *, int); +extern const struct nvkm_runl_func nv50_runl; +extern const struct nvkm_engn_func nv50_engn_sw; +extern const struct nvkm_engn_func g84_engn; extern const struct nvkm_chan_func g84_chan; int gf100_fifo_chid_ctor(struct nvkm_fifo *, int); int gf100_fifo_runq_nr(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); +extern const struct nvkm_engn_func gf100_engn_sw; int gk104_fifo_chid_nr(struct nvkm_fifo *); +int gk104_fifo_runl_ctor(struct nvkm_fifo *); void gk104_fifo_intr(struct nvkm_fifo *); extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); @@ -117,8 +130,11 @@ void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int); extern const struct nvkm_runq_func gk104_runq; +extern const struct nvkm_engn_func gk104_engn; +extern const struct nvkm_engn_func gk104_engn_ce; int gk110_fifo_chid_ctor(struct nvkm_fifo *, int); +extern const struct nvkm_runl_func gk110_runl; extern const struct nvkm_cgrp_func gk110_cgrp; extern const struct nvkm_chan_func gk110_chan; @@ -126,6 +142,7 @@ extern const struct nvkm_runq_func gk208_runq; void gm107_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); extern const struct nvkm_fifo_func_mmu_fault gm107_fifo_mmu_fault; +extern const struct nvkm_runl_func gm107_runl; extern const struct nvkm_chan_func gm107_chan; int gm200_fifo_chid_nr(struct nvkm_fifo *); @@ -134,6 +151,8 @@ int gm200_fifo_runq_nr(struct nvkm_fifo *); void gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); extern const struct nvkm_runq_func gv100_runq; +extern const struct nvkm_engn_func gv100_engn; +extern const struct nvkm_engn_func gv100_engn_ce; extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c new file mode 100644 index 000000000000..4d7319674128 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -0,0 +1,112 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "runl.h" +#include "chan.h" +#include "chid.h" +#include "priv.h" + +void +nvkm_runl_del(struct nvkm_runl *runl) +{ + struct nvkm_engn *engn, *engt; + + list_for_each_entry_safe(engn, engt, &runl->engns, head) { + list_del(&engn->head); + kfree(engn); + } + + nvkm_chid_unref(&runl->chid); + nvkm_chid_unref(&runl->cgid); + + list_del(&runl->head); + kfree(runl); +} + +struct nvkm_engn * +nvkm_runl_add(struct nvkm_runl *runl, int engi, const struct nvkm_engn_func *func, + enum nvkm_subdev_type type, int inst) +{ + struct nvkm_device *device = runl->fifo->engine.subdev.device; + struct nvkm_engine *engine; + struct nvkm_engn *engn; + + engine = nvkm_device_engine(device, type, inst); + if (!engine) { + RUNL_DEBUG(runl, "engn %d.%d[%s] not found", engi, inst, nvkm_subdev_type[type]); + return NULL; + } + + if (!(engn = kzalloc(sizeof(*engn), GFP_KERNEL))) + return NULL; + + engn->func = func; + engn->runl = runl; + engn->id = engi; + engn->engine = engine; + list_add_tail(&engn->head, &runl->engns); + return engn; +} + +struct nvkm_runl * +nvkm_runl_get(struct nvkm_fifo *fifo, int runi, u32 addr) +{ + struct nvkm_runl *runl; + + nvkm_runl_foreach(runl, fifo) { + if ((runi >= 0 && runl->id == runi) || (runi < 0 && runl->addr == addr)) + return runl; + } + + return NULL; +} + +struct nvkm_runl * +nvkm_runl_new(struct nvkm_fifo *fifo, int runi, u32 addr, int id_nr) +{ + struct nvkm_subdev *subdev = &fifo->engine.subdev; + struct nvkm_runl *runl; + int ret; + + if (!(runl = kzalloc(sizeof(*runl), GFP_KERNEL))) + return NULL; + + runl->func = fifo->func->runl; + runl->fifo = fifo; + runl->id = runi; + runl->addr = addr; + INIT_LIST_HEAD(&runl->engns); + list_add_tail(&runl->head, &fifo->runls); + + if (!fifo->chid) { + if ((ret = nvkm_chid_new(&nvkm_chan_event, subdev, id_nr, 0, id_nr, &runl->cgid)) || + (ret = nvkm_chid_new(&nvkm_chan_event, subdev, id_nr, 0, id_nr, &runl->chid))) { + RUNL_ERROR(runl, "cgid/chid: %d", ret); + nvkm_runl_del(runl); + return NULL; + } + } else { + runl->cgid = nvkm_chid_ref(fifo->cgid); + runl->chid = nvkm_chid_ref(fifo->chid); + } + + return runl; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h new file mode 100644 index 000000000000..9f27babc8caf --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -0,0 +1,55 @@ +#ifndef __NVKM_RUNL_H__ +#define __NVKM_RUNL_H__ +#include +struct nvkm_cgrp; +struct nvkm_memory; +enum nvkm_subdev_type; + +struct nvkm_engn { + const struct nvkm_engn_func { + } *func; + struct nvkm_runl *runl; + int id; + + struct nvkm_engine *engine; + + struct list_head head; +}; + +#define ENGN_PRINT(e,l,p,f,a...) \ + RUNL_PRINT((e)->runl, l, p, "%02d[%8s]:"f, (e)->id, (e)->engine->subdev.name, ##a) +#define ENGN_DEBUG(e,f,a...) ENGN_PRINT((e), DEBUG, info, " "f"\n", ##a) + +struct nvkm_runl { + const struct nvkm_runl_func { + } *func; + struct nvkm_fifo *fifo; + int id; + u32 addr; + + struct nvkm_chid *cgid; + struct nvkm_chid *chid; + + struct list_head engns; + + struct nvkm_runq *runq[2]; + int runq_nr; + + struct list_head head; +}; + +struct nvkm_runl *nvkm_runl_new(struct nvkm_fifo *, int runi, u32 addr, int id_nr); +struct nvkm_runl *nvkm_runl_get(struct nvkm_fifo *, int runi, u32 addr); +struct nvkm_engn *nvkm_runl_add(struct nvkm_runl *, int engi, const struct nvkm_engn_func *, + enum nvkm_subdev_type, int inst); +void nvkm_runl_del(struct nvkm_runl *); + +#define nvkm_runl_foreach(runl,fifo) list_for_each_entry((runl), &(fifo)->runls, head) +#define nvkm_runl_foreach_engn(engn,runl) list_for_each_entry((engn), &(runl)->engns, head) + +#define RUNL_PRINT(r,l,p,f,a...) \ + nvkm_printk__(&(r)->fifo->engine.subdev, NV_DBG_##l, p, "%06x:"f, (r)->addr, ##a) +#define RUNL_ERROR(r,f,a...) RUNL_PRINT((r), ERROR, err, " "f"\n", ##a) +#define RUNL_DEBUG(r,f,a...) RUNL_PRINT((r), DEBUG, info, " "f"\n", ##a) +#define RUNL_TRACE(r,f,a...) RUNL_PRINT((r), TRACE, info, " "f"\n", ##a) +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 6d0431610235..ff13ae5bb45d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -20,6 +20,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "chan.h" +#include "runl.h" #include "gk104.h" #include "cgrp.h" @@ -60,6 +61,10 @@ tu102_fifo_runlist = { .commit = tu102_fifo_runlist_commit, }; +static const struct nvkm_runl_func +tu102_runl = { +}; + static const struct nvkm_enum tu102_fifo_fault_engine[] = { { 0x01, "DISPLAY" }, @@ -443,6 +448,7 @@ tu102_fifo = { .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, + .runl_ctor = gk104_fifo_runl_ctor, .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, @@ -460,7 +466,10 @@ tu102_fifo = { .recover_chan = tu102_fifo_recover_chan, .runlist = &tu102_fifo_runlist, .pbdma = &tu102_fifo_pbdma, + .runl = &tu102_runl, .runq = &gv100_runq, + .engn = &gv100_engn, + .engn_ce = &gv100_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, .chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan, .ctor = tu102_fifo_gpfifo_new }, }; -- cgit v1.2.3 From 6de125383a5cce5f0d9235a6d3a9ae83dc5d299e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:25 +1000 Subject: drm/nouveau/fifo: expose runlist topology info on all chipsets Previously only available from Kepler onwards. - also fixes the info() queries causing fifo init()/fini() unnecessarily Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nouveau_abi16.c | 26 ++++++------ drivers/gpu/drm/nouveau/nouveau_chan.c | 7 ++-- drivers/gpu/drm/nouveau/nouveau_chan.h | 5 +-- drivers/gpu/drm/nouveau/nouveau_drm.c | 36 ++++++---------- drivers/gpu/drm/nouveau/nvkm/core/engine.c | 12 ++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 49 +++++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 52 ------------------------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 1 - 17 files changed, 81 insertions(+), 116 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 5bee655e7e63..9237ef328b9f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -253,7 +253,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_abi16_chan *chan; struct nvif_device *device; - u64 engine; + u64 engine, runm; int ret; if (unlikely(!abi16)) @@ -263,6 +263,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) return nouveau_abi16_put(abi16, -ENODEV); device = &abi16->device; + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR; /* hack to allow channel engine type specification on kepler */ if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { @@ -276,19 +277,18 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) default: return nouveau_abi16_put(abi16, -ENOSYS); } - } else { - engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR; - } - if (engine != NV_DEVICE_HOST_RUNLIST_ENGINES_CE) - engine = nvif_fifo_runlist(device, engine); - else - engine = nvif_fifo_runlist_ce(device); - init->fb_ctxdma_handle = engine; - init->tt_ctxdma_handle = 0; + init->fb_ctxdma_handle = 0; + init->tt_ctxdma_handle = 0; + } } - if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) + if (engine != NV_DEVICE_HOST_RUNLIST_ENGINES_CE) + runm = nvif_fifo_runlist(device, engine); + else + runm = nvif_fifo_runlist_ce(device); + + if (!runm || init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) return nouveau_abi16_put(abi16, -EINVAL); /* allocate "abi16 channel" data and make up a handle for it */ @@ -300,8 +300,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) list_add(&chan->head, &abi16->channels); /* create channel object and initialise dma and fence management */ - ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle, - init->tt_ctxdma_handle, false, &chan->chan); + ret = nouveau_channel_new(drm, device, false, runm, init->fb_ctxdma_handle, + init->tt_ctxdma_handle, &chan->chan); if (ret) goto done; diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 497d889c20b6..3b5cbb67f15b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -513,14 +513,13 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) int nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, - u32 arg0, u32 arg1, bool priv, - struct nouveau_channel **pchan) + bool priv, u64 runm, u32 vram, u32 gart, struct nouveau_channel **pchan) { struct nouveau_cli *cli = (void *)device->object.client; int ret; /* hack until fencenv50 is fixed, and agp access relaxed */ - ret = nouveau_channel_ind(drm, device, arg0, priv, pchan); + ret = nouveau_channel_ind(drm, device, runm, priv, pchan); if (ret) { NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret); ret = nouveau_channel_dma(drm, device, pchan); @@ -530,7 +529,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, } } - ret = nouveau_channel_init(*pchan, arg0, arg1); + ret = nouveau_channel_init(*pchan, vram, gart); if (ret) { NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret); nouveau_channel_del(pchan); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 195b38c84771..7ffee796a67a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -56,9 +56,8 @@ struct nouveau_channel { int nouveau_channels_init(struct nouveau_drm *); -int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, - u32 arg0, u32 arg1, bool priv, - struct nouveau_channel **); +int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, bool priv, u64 runm, + u32 vram, u32 gart, struct nouveau_channel **); void nouveau_channel_del(struct nouveau_channel **); int nouveau_channel_idle(struct nouveau_channel *); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 9df276bff3c7..1812ffdaae8d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -316,28 +316,19 @@ static void nouveau_accel_ce_init(struct nouveau_drm *drm) { struct nvif_device *device = &drm->client.device; + u64 runm; int ret = 0; /* Allocate channel that has access to a (preferably async) copy * engine, to use for TTM buffer moves. */ - if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { - ret = nouveau_channel_new(drm, device, - nvif_fifo_runlist_ce(device), 0, - true, &drm->cechan); - } else - if (device->info.chipset >= 0xa3 && - device->info.chipset != 0xaa && - device->info.chipset != 0xac) { - /* Prior to Kepler, there's only a single runlist, so all - * engines can be accessed from any channel. - * - * We still want to use a separate channel though. - */ - ret = nouveau_channel_new(drm, device, NvDmaFB, NvDmaTT, false, - &drm->cechan); + runm = nvif_fifo_runlist_ce(device); + if (!runm) { + NV_DEBUG(drm, "no ce runlist\n"); + return; } + ret = nouveau_channel_new(drm, device, false, runm, NvDmaFB, NvDmaTT, &drm->cechan); if (ret) NV_ERROR(drm, "failed to create ce channel, %d\n", ret); } @@ -355,23 +346,20 @@ static void nouveau_accel_gr_init(struct nouveau_drm *drm) { struct nvif_device *device = &drm->client.device; - u32 arg0, arg1; + u64 runm; int ret; if (device->info.family >= NV_DEVICE_INFO_V0_AMPERE) return; /* Allocate channel that has access to the graphics engine. */ - if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { - arg0 = nvif_fifo_runlist(device, NV_DEVICE_HOST_RUNLIST_ENGINES_GR); - arg1 = 1; - } else { - arg0 = NvDmaFB; - arg1 = NvDmaTT; + runm = nvif_fifo_runlist(device, NV_DEVICE_HOST_RUNLIST_ENGINES_GR); + if (!runm) { + NV_DEBUG(drm, "no gr runlist\n"); + return; } - ret = nouveau_channel_new(drm, device, arg0, arg1, false, - &drm->channel); + ret = nouveau_channel_new(drm, device, false, runm, NvDmaFB, NvDmaTT, &drm->channel); if (ret) { NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); nouveau_accel_gr_fini(drm); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c index 558bd10e5518..964615a60997 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c @@ -80,14 +80,10 @@ static int nvkm_engine_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data) { struct nvkm_engine *engine = nvkm_engine(subdev); - if (engine->func->info) { - if (!IS_ERR((engine = nvkm_engine_ref(engine)))) { - int ret = engine->func->info(engine, mthd, data); - nvkm_engine_unref(&engine); - return ret; - } - return PTR_ERR(engine); - } + + if (engine->func->info) + return engine->func->info(engine, mthd, data); + return -ENOSYS; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 60d5cbbe4381..2ccc0b3a3ecd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -221,12 +221,57 @@ static int nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + struct nvkm_runl *runl; + struct nvkm_engn *engn; + int ret; + + ret = nvkm_subdev_oneinit(&fifo->engine.subdev); + if (ret) + return ret; switch (mthd) { case NV_DEVICE_HOST_CHANNELS: *data = fifo->chid ? fifo->chid->nr : 0; return 0; + case NV_DEVICE_HOST_RUNLISTS: + *data = 0; + nvkm_runl_foreach(runl, fifo) + *data |= BIT(runl->id); + return 0; + case NV_DEVICE_HOST_RUNLIST_ENGINES: + runl = nvkm_runl_get(fifo, *data, 0); + if (runl) { + *data = 0; + nvkm_runl_foreach_engn(engn, runl) { +#define CASE(n) case NVKM_ENGINE_##n: *data |= NV_DEVICE_HOST_RUNLIST_ENGINES_##n; break + switch (engn->engine->subdev.type) { + case NVKM_ENGINE_DMAOBJ: + break; + CASE(SW ); + CASE(GR ); + CASE(MPEG ); + CASE(ME ); + CASE(CIPHER); + CASE(BSP ); + CASE(VP ); + CASE(CE ); + CASE(SEC ); + CASE(MSVLD ); + CASE(MSPDEC); + CASE(MSPPP ); + CASE(MSENC ); + CASE(VIC ); + CASE(SEC2 ); + CASE(NVDEC ); + CASE(NVENC ); + default: + WARN_ON(1); + break; + } +#undef CASE + } + return 0; + } + return -EINVAL; default: - if (fifo->func->info) - return fifo->func->info(fifo, mthd, data); break; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index eaf61c07fafc..b41481c984d1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -39,7 +39,6 @@ #include #include -#include static const struct nvkm_chan_func gk104_chan = { @@ -991,56 +990,6 @@ gk104_fifo_fini(struct nvkm_fifo *base) nvkm_mask(device, 0x002140, 0x10000000, 0x10000000); } -int -gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - switch (mthd) { - case NV_DEVICE_HOST_RUNLISTS: - *data = (1ULL << fifo->runlist_nr) - 1; - return 0; - case NV_DEVICE_HOST_RUNLIST_ENGINES: { - if (*data < fifo->runlist_nr) { - unsigned long engm = fifo->runlist[*data].engm; - struct nvkm_engine *engine; - int engn; - *data = 0; - for_each_set_bit(engn, &engm, fifo->engine_nr) { - if ((engine = fifo->engine[engn].engine)) { -#define CASE(n) case NVKM_ENGINE_##n: *data |= NV_DEVICE_HOST_RUNLIST_ENGINES_##n; break - switch (engine->subdev.type) { - CASE(SW ); - CASE(GR ); - CASE(MPEG ); - CASE(ME ); - CASE(CIPHER); - CASE(BSP ); - CASE(VP ); - CASE(CE ); - CASE(SEC ); - CASE(MSVLD ); - CASE(MSPDEC); - CASE(MSPPP ); - CASE(MSENC ); - CASE(VIC ); - CASE(SEC2 ); - CASE(NVDEC ); - CASE(NVENC ); - default: - WARN_ON(1); - break; - } - } - } - return 0; - } - } - return -EINVAL; - default: - return -EINVAL; - } -} - void gk104_fifo_init(struct nvkm_fifo *base) { @@ -1225,7 +1174,6 @@ gk104_fifo = { .chid_ctor = gf100_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 636091c7fcee..403560aefbb7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -75,7 +75,6 @@ void gk104_fifo_intr_runlist(struct gk104_fifo *fifo); void gk104_fifo_intr_engine(struct gk104_fifo *fifo); void *gk104_fifo_dtor(struct nvkm_fifo *base); int gk104_fifo_oneinit(struct nvkm_fifo *); -int gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data); void gk104_fifo_init(struct nvkm_fifo *base); void gk104_fifo_fini(struct nvkm_fifo *base); void gk104_fifo_uevent_fini(struct nvkm_fifo *fifo); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 08f5b0684510..64bdd3fd3ae6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -82,7 +82,6 @@ gk110_fifo = { .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index c58343b5c49e..3e074a976c44 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -61,7 +61,6 @@ gk208_fifo = { .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 9a1c1ca95121..a494dacad37e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -32,7 +32,6 @@ gk20a_fifo = { .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 44dbebf06992..c4a6972ee473 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -122,7 +122,6 @@ gm107_fifo = { .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index e9f3c5f08ca8..bc9893c4d297 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -52,7 +52,6 @@ gm200_fifo = { .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 6fea0a5525df..4ac4afbf3147 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -94,7 +94,6 @@ gp100_fifo = { .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 21246a0f319d..e1069c672438 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -322,7 +322,6 @@ gv100_fifo = { .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 93b8b726214e..b0fa9d1df91d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -25,7 +25,6 @@ struct nvkm_fifo_func { int (*runq_nr)(struct nvkm_fifo *); int (*runl_ctor)(struct nvkm_fifo *); - int (*info)(struct nvkm_fifo *, u64 mthd, u64 *data); void (*init)(struct nvkm_fifo *); void (*fini)(struct nvkm_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index ff13ae5bb45d..e5b9b1fc3866 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -449,7 +449,6 @@ tu102_fifo = { .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, - .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = tu102_fifo_intr, -- cgit v1.2.3 From eb39c613481fd2fe6b2f66ec2ca21f8fdcdd4cac Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:25 +1000 Subject: drm/nouveau/fifo: expose per-runlist CHID information DRM uses this to setup fence-related items. - nouveau_chan.runlist will always be "0" for the moment, not an issue as GPUs prior to ampere have system-wide channel IDs, Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/cl0080.h | 4 ++- drivers/gpu/drm/nouveau/nouveau_chan.c | 47 ++++++++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_chan.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_drm.c | 1 + drivers/gpu/drm/nouveau/nouveau_drv.h | 8 +++-- drivers/gpu/drm/nouveau/nouveau_fence.c | 8 ++--- drivers/gpu/drm/nouveau/nv84_fence.c | 22 +++++++----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 9 +++++ 8 files changed, 80 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h index 59759c4fb62e..8b5a240d57e4 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h @@ -68,7 +68,7 @@ struct nv_device_time_v0 { /* Returns the number of available runlists. */ #define NV_DEVICE_HOST_RUNLISTS NV_DEVICE_HOST(0x00000000) -/* Returns the number of available channels. */ +/* Returns the number of available channels (0 if per-runlist). */ #define NV_DEVICE_HOST_CHANNELS NV_DEVICE_HOST(0x00000001) /* Returns a mask of available engine types on runlist(data). */ @@ -90,4 +90,6 @@ struct nv_device_time_v0 { #define NV_DEVICE_HOST_RUNLIST_ENGINES_SEC2 0x00004000 #define NV_DEVICE_HOST_RUNLIST_ENGINES_NVDEC 0x00008000 #define NV_DEVICE_HOST_RUNLIST_ENGINES_NVENC 0x00010000 +/* Returns the number of available channels on runlist(data). */ +#define NV_DEVICE_HOST_RUNLIST_CHANNELS NV_DEVICE_HOST(0x00000101) #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 3b5cbb67f15b..5b7042d94e80 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -543,6 +543,12 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, return ret; } +void +nouveau_channels_fini(struct nouveau_drm *drm) +{ + kfree(drm->runl); +} + int nouveau_channels_init(struct nouveau_drm *drm) { @@ -550,20 +556,53 @@ nouveau_channels_init(struct nouveau_drm *drm) struct nv_device_info_v1 m; struct { struct nv_device_info_v1_data channels; + struct nv_device_info_v1_data runlists; } v; } args = { .m.version = 1, .m.count = sizeof(args.v) / sizeof(args.v.channels), .v.channels.mthd = NV_DEVICE_HOST_CHANNELS, + .v.runlists.mthd = NV_DEVICE_HOST_RUNLISTS, }; struct nvif_object *device = &drm->client.device.object; - int ret; + int ret, i; ret = nvif_object_mthd(device, NV_DEVICE_V0_INFO, &args, sizeof(args)); - if (ret || args.v.channels.mthd == NV_DEVICE_INFO_INVALID) + if (ret || + args.v.runlists.mthd == NV_DEVICE_INFO_INVALID || !args.v.runlists.data || + args.v.channels.mthd == NV_DEVICE_INFO_INVALID) return -ENODEV; - drm->chan.nr = args.v.channels.data; - drm->chan.context_base = dma_fence_context_alloc(drm->chan.nr); + drm->chan_nr = drm->chan_total = args.v.channels.data; + drm->runl_nr = fls64(args.v.runlists.data); + drm->runl = kcalloc(drm->runl_nr, sizeof(*drm->runl), GFP_KERNEL); + if (!drm->runl) + return -ENOMEM; + + if (drm->chan_nr == 0) { + for (i = 0; i < drm->runl_nr; i++) { + if (!(args.v.runlists.data & BIT(i))) + continue; + + args.v.channels.mthd = NV_DEVICE_HOST_RUNLIST_CHANNELS; + args.v.channels.data = i; + + ret = nvif_object_mthd(device, NV_DEVICE_V0_INFO, &args, sizeof(args)); + if (ret || args.v.channels.mthd == NV_DEVICE_INFO_INVALID) + return -ENODEV; + + drm->runl[i].chan_nr = args.v.channels.data; + drm->runl[i].chan_id_base = drm->chan_total; + drm->runl[i].context_base = dma_fence_context_alloc(drm->runl[i].chan_nr); + + drm->chan_total += drm->runl[i].chan_nr; + } + } else { + drm->runl[0].context_base = dma_fence_context_alloc(drm->chan_nr); + for (i = 1; i < drm->runl_nr; i++) + drm->runl[i].context_base = drm->runl[0].context_base; + + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 7ffee796a67a..40467e8c9668 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -16,6 +16,7 @@ struct nouveau_channel { struct nouveau_drm *drm; struct nouveau_vmm *vmm; + int runlist; int chid; u64 inst; u32 token; @@ -55,6 +56,7 @@ struct nouveau_channel { }; int nouveau_channels_init(struct nouveau_drm *); +void nouveau_channels_fini(struct nouveau_drm *); int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, bool priv, u64 runm, u32 vram, u32 gart, struct nouveau_channel **); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 1812ffdaae8d..4a533b080445 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -424,6 +424,7 @@ nouveau_accel_fini(struct nouveau_drm *drm) nouveau_accel_gr_fini(drm); if (drm->fence) nouveau_fence(drm)->dtor(drm); + nouveau_channels_fini(drm); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 6fb636020f7f..d6dd07bfa64a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -174,10 +174,14 @@ struct nouveau_drm { void *fence; /* Global channel management. */ + int chan_total; /* Number of channels across all runlists. */ + int chan_nr; /* 0 if per-runlist CHIDs. */ + int runl_nr; struct { - int nr; + int chan_nr; + int chan_id_base; u64 context_base; - } chan; + } *runl; /* context for accelerated drm-internal operations */ struct nouveau_channel *cechan; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index c4c8af16af02..ee5e9d40c166 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -77,10 +77,6 @@ nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) fence->ops != &nouveau_fence_ops_uevent) return NULL; - if (fence->context < drm->chan.context_base || - fence->context >= drm->chan.context_base + drm->chan.nr) - return NULL; - return from_fence(fence); } @@ -184,7 +180,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha INIT_LIST_HEAD(&fctx->flip); INIT_LIST_HEAD(&fctx->pending); spin_lock_init(&fctx->lock); - fctx->context = chan->drm->chan.context_base + chan->chid; + fctx->context = chan->drm->runl[chan->runlist].context_base + chan->chid; if (chan == chan->drm->cechan) strcpy(fctx->name, "copy engine channel"); @@ -200,7 +196,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha args.host.version = 0; args.host.type = NVIF_CHAN_EVENT_V0_NON_STALL_INTR; - ret = nvif_event_ctor(&chan->user, "fenceNonStallIntr", chan->chid, + ret = nvif_event_ctor(&chan->user, "fenceNonStallIntr", (chan->runlist << 16) | chan->chid, nouveau_fence_wait_uevent_handler, false, &args.base, sizeof(args), &fctx->event); diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index c3526a8622e3..a01fd934c85e 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -76,12 +76,18 @@ nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) return ret; } +static inline u32 +nv84_fence_chid(struct nouveau_channel *chan) +{ + return chan->drm->runl[chan->runlist].chan_id_base + chan->chid; +} + static int nv84_fence_emit(struct nouveau_fence *fence) { struct nouveau_channel *chan = fence->channel; struct nv84_fence_chan *fctx = chan->fence; - u64 addr = fctx->vma->addr + chan->chid * 16; + u64 addr = fctx->vma->addr + nv84_fence_chid(chan) * 16; return fctx->base.emit32(chan, addr, fence->base.seqno); } @@ -91,7 +97,7 @@ nv84_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *prev, struct nouveau_channel *chan) { struct nv84_fence_chan *fctx = chan->fence; - u64 addr = fctx->vma->addr + prev->chid * 16; + u64 addr = fctx->vma->addr + nv84_fence_chid(prev) * 16; return fctx->base.sync32(chan, addr, fence->base.seqno); } @@ -100,7 +106,7 @@ static u32 nv84_fence_read(struct nouveau_channel *chan) { struct nv84_fence_priv *priv = chan->drm->fence; - return nouveau_bo_rd32(priv->bo, chan->chid * 16/4); + return nouveau_bo_rd32(priv->bo, nv84_fence_chid(chan) * 16/4); } static void @@ -109,7 +115,7 @@ nv84_fence_context_del(struct nouveau_channel *chan) struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_chan *fctx = chan->fence; - nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence); + nouveau_bo_wr32(priv->bo, nv84_fence_chid(chan) * 16 / 4, fctx->base.sequence); mutex_lock(&priv->mutex); nouveau_vma_del(&fctx->vma); mutex_unlock(&priv->mutex); @@ -152,9 +158,9 @@ nv84_fence_suspend(struct nouveau_drm *drm) struct nv84_fence_priv *priv = drm->fence; int i; - priv->suspend = vmalloc(array_size(sizeof(u32), drm->chan.nr)); + priv->suspend = vmalloc(array_size(sizeof(u32), drm->chan_total)); if (priv->suspend) { - for (i = 0; i < drm->chan.nr; i++) + for (i = 0; i < drm->chan_total; i++) priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4); } @@ -168,7 +174,7 @@ nv84_fence_resume(struct nouveau_drm *drm) int i; if (priv->suspend) { - for (i = 0; i < drm->chan.nr; i++) + for (i = 0; i < drm->chan_total; i++) nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]); vfree(priv->suspend); priv->suspend = NULL; @@ -216,7 +222,7 @@ nv84_fence_create(struct nouveau_drm *drm) * will lose CPU/GPU coherency! */ NOUVEAU_GEM_DOMAIN_GART | NOUVEAU_GEM_DOMAIN_COHERENT; - ret = nouveau_bo_new(&drm->client, 16 * drm->chan.nr, 0, + ret = nouveau_bo_new(&drm->client, 16 * drm->chan_total, 0, domain, 0, 0, NULL, NULL, &priv->bo); if (ret == 0) { ret = nouveau_bo_pin(priv->bo, domain, false); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 2ccc0b3a3ecd..0f603d9f00cb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -271,6 +271,15 @@ nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data) return 0; } return -EINVAL; + case NV_DEVICE_HOST_RUNLIST_CHANNELS: + if (!fifo->chid) { + runl = nvkm_runl_get(fifo, *data, 0); + if (runl) { + *data = runl->chid->nr; + return 0; + } + } + return -EINVAL; default: break; } -- cgit v1.2.3 From 468fae7bb0a31094cff900e92a08f02263f793be Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:26 +1000 Subject: drm/nouveau/fifo: add cgrp, have all channels be part of one Engine context tracking will move to nvkm_cgrp in later commits, so we create SW-only channel groups on HW without support for them. - switches to nvkm_chid for TSG/channel ID allocation Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 7 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c | 94 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h | 23 +++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 68 ++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 5 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c | 29 +++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 3 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 9 +++ 13 files changed, 231 insertions(+), 18 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 1e12697beae2..62fe64dab11a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -6,7 +6,6 @@ #include struct nvkm_fault_data; -#define NVKM_FIFO_CHID_NR 4096 #define NVKM_FIFO_ENGN_NR 16 struct nvkm_fifo_engn { @@ -17,13 +16,16 @@ struct nvkm_fifo_engn { struct nvkm_chan { const struct nvkm_chan_func *func; + char name[64]; + struct nvkm_cgrp *cgrp; + + union { int id; int chid; }; /*FIXME: remove later */ struct nvkm_fifo *fifo; u32 engm; struct nvkm_object object; struct list_head head; - u16 chid; struct nvkm_gpuobj *inst; struct nvkm_gpuobj *push; struct nvkm_vmm *vmm; @@ -43,7 +45,6 @@ struct nvkm_fifo { struct list_head runqs; struct list_head runls; - DECLARE_BITMAP(mask, NVKM_FIFO_CHID_NR); int nr; struct list_head chan; spinlock_t lock; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index a92a88a72e59..eb82da7e7d87 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -1,5 +1,6 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/engine/fifo/base.o +nvkm-y += nvkm/engine/fifo/cgrp.o nvkm-y += nvkm/engine/fifo/chan.o nvkm-y += nvkm/engine/fifo/chid.o nvkm-y += nvkm/engine/fifo/runl.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 0f603d9f00cb..3e62eacc48ad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -389,10 +389,7 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, INIT_LIST_HEAD(&fifo->chan); nr = func->chid_nr(fifo); - if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR)) - fifo->nr = NVKM_FIFO_CHID_NR; - else - fifo->nr = nr; + fifo->nr = nr; if (func->uevent_init) { ret = nvkm_event_init(&nvkm_fifo_uevent_func, &fifo->engine.subdev, 1, 1, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c new file mode 100644 index 000000000000..e6ac178db8b5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c @@ -0,0 +1,94 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "cgrp.h" +#include "chan.h" +#include "chid.h" +#include "runl.h" +#include "priv.h" + +#include + +static void +nvkm_cgrp_del(struct kref *kref) +{ + struct nvkm_cgrp *cgrp = container_of(kref, typeof(*cgrp), kref); + struct nvkm_runl *runl = cgrp->runl; + + if (runl->cgid) + nvkm_chid_put(runl->cgid, cgrp->id, &cgrp->lock); + + nvkm_vmm_unref(&cgrp->vmm); + kfree(cgrp); +} + +void +nvkm_cgrp_unref(struct nvkm_cgrp **pcgrp) +{ + struct nvkm_cgrp *cgrp = *pcgrp; + + if (!cgrp) + return; + + kref_put(&cgrp->kref, nvkm_cgrp_del); + *pcgrp = NULL; +} + +struct nvkm_cgrp * +nvkm_cgrp_ref(struct nvkm_cgrp *cgrp) +{ + if (cgrp) + kref_get(&cgrp->kref); + + return cgrp; +} + +int +nvkm_cgrp_new(struct nvkm_runl *runl, const char *name, struct nvkm_vmm *vmm, bool hw, + struct nvkm_cgrp **pcgrp) +{ + struct nvkm_cgrp *cgrp; + + if (!(cgrp = *pcgrp = kmalloc(sizeof(*cgrp), GFP_KERNEL))) + return -ENOMEM; + + cgrp->func = runl->fifo->func->cgrp.func; + strscpy(cgrp->name, name, sizeof(cgrp->name)); + cgrp->runl = runl; + cgrp->vmm = nvkm_vmm_ref(vmm); + cgrp->hw = hw; + cgrp->id = -1; + kref_init(&cgrp->kref); + cgrp->chans = NULL; + cgrp->chan_nr = 0; + spin_lock_init(&cgrp->lock); + + if (runl->cgid) { + cgrp->id = nvkm_chid_get(runl->cgid, cgrp); + if (cgrp->id < 0) { + RUNL_ERROR(runl, "!cgids"); + nvkm_cgrp_unref(pcgrp); + return -ENOSPC; + } + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h index 9a677a1acf9b..d0510df9286a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h @@ -2,13 +2,34 @@ #ifndef __NVKM_CGRP_H__ #define __NVKM_CGRP_H__ #include +struct nvkm_chan; struct nvkm_cgrp { const struct nvkm_cgrp_func { } *func; + char name[64]; + struct nvkm_runl *runl; + struct nvkm_vmm *vmm; + bool hw; int id; + struct kref kref; + + struct nvkm_chan *chans; + int chan_nr; + + spinlock_t lock; /* protects irq handler channel (group) lookup */ + struct list_head head; struct list_head chan; - int chan_nr; }; + +int nvkm_cgrp_new(struct nvkm_runl *, const char *name, struct nvkm_vmm *, bool hw, + struct nvkm_cgrp **); +struct nvkm_cgrp *nvkm_cgrp_ref(struct nvkm_cgrp *); +void nvkm_cgrp_unref(struct nvkm_cgrp **); + +#define CGRP_PRCLI(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a) +#define CGRP_PRINT(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:"f, (c)->id, ##a) +#define CGRP_ERROR(c,f,a...) CGRP_PRCLI((c), ERROR, err, " "f"\n", ##a) +#define CGRP_TRACE(c,f,a...) CGRP_PRINT((c), TRACE, info, " "f"\n", ##a) #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 464c956aaca9..e2178a8f78a7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "chan.h" +#include "chid.h" +#include "cgrp.h" +#include "runl.h" #include "priv.h" #include @@ -312,6 +315,11 @@ nvkm_chan_del(struct nvkm_chan **pchan) if (!chan) return; + if (chan->cgrp) { + nvkm_chid_put(chan->cgrp->runl->chid, chan->id, &chan->cgrp->lock); + nvkm_cgrp_unref(&chan->cgrp); + } + chan = nvkm_object_dtor(&chan->object); kfree(chan); } @@ -326,7 +334,6 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object) spin_lock_irqsave(&fifo->lock, flags); if (!list_empty(&chan->head)) { - __clear_bit(chan->chid, fifo->mask); list_del(&chan->head); } spin_unlock_irqrestore(&fifo->lock, flags); @@ -363,9 +370,22 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, struct nvkm_client *client = oclass->client; struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_dmaobj *dmaobj; + struct nvkm_cgrp *cgrp = NULL; + struct nvkm_runl *runl; + struct nvkm_engn *engn = NULL; + struct nvkm_vmm *vmm = NULL; unsigned long flags; int ret; + nvkm_runl_foreach(runl, fifo) { + engn = nvkm_runl_find_engn(engn, runl, engm & BIT(engn->id)); + if (engn) + break; + } + + if (!engn) + return -EINVAL; + /*FIXME: temp kludge to ease transition, remove later */ if (!(func = kmalloc(sizeof(*func), GFP_KERNEL))) return -ENOMEM; @@ -383,12 +403,38 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, func->submit_token = fn->submit_token; chan->func = func; + chan->id = -1; nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); chan->fifo = fifo; chan->engm = engm; INIT_LIST_HEAD(&chan->head); + /* Join channel group. + * + * GK110 and newer support channel groups (aka TSGs), where individual channels + * share a timeslice, and, engine context(s). + * + * As such, engine contexts are tracked in nvkm_cgrp and we need them even when + * channels aren't in an API channel group, and on HW that doesn't support TSGs. + */ + if (!cgrp) { + ret = nvkm_cgrp_new(runl, chan->name, vmm, fifo->func->cgrp.force, &chan->cgrp); + if (ret) { + RUNL_DEBUG(runl, "cgrp %d", ret); + return ret; + } + + cgrp = chan->cgrp; + } else { + if (cgrp->runl != runl || cgrp->vmm != vmm) { + RUNL_DEBUG(runl, "cgrp %d %d", cgrp->runl != runl, cgrp->vmm != vmm); + return -EINVAL; + } + + chan->cgrp = nvkm_cgrp_ref(cgrp); + } + /* instance memory */ ret = nvkm_gpuobj_new(device, size, align, zero, NULL, &chan->inst); if (ret) @@ -422,15 +468,23 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, chan->vmm = nvkm_vmm_ref(vmm); } - /* allocate channel id */ - spin_lock_irqsave(&fifo->lock, flags); - chan->chid = find_first_zero_bit(fifo->mask, NVKM_FIFO_CHID_NR); - if (chan->chid >= NVKM_FIFO_CHID_NR) { - spin_unlock_irqrestore(&fifo->lock, flags); + /* Allocate channel ID. */ + if (runl->cgid) { + chan->id = chan->cgrp->id; + runl->chid->data[chan->id] = chan; + set_bit(chan->id, runl->chid->used); + goto temp_hack_until_no_chid_eq_cgid_req; + } + + chan->id = nvkm_chid_get(runl->chid, chan); + if (chan->id < 0) { + RUNL_ERROR(runl, "!chids"); return -ENOSPC; } + +temp_hack_until_no_chid_eq_cgid_req: + spin_lock_irqsave(&fifo->lock, flags); list_add(&chan->head, &fifo->chan); - __set_bit(chan->chid, fifo->mask); spin_unlock_irqrestore(&fifo->lock, flags); /* determine address of this channel's user registers */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index a9c0e02b6f9f..0f1added5c24 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -27,5 +27,10 @@ int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, const struct nvkm_oclass *, struct nvkm_fifo_chan *); void nvkm_chan_del(struct nvkm_chan **); +#define CHAN_PRCLI(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a) +#define CHAN_PRINT(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:"f, (c)->id, ##a) +#define CHAN_ERROR(c,f,a...) CHAN_PRCLI((c), ERROR, err, " "f"\n", ##a) +#define CHAN_TRACE(c,f,a...) CHAN_PRINT((c), TRACE, info, " "f"\n", ##a) + int nvkm_fifo_chan_child_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c index 7c582bce7e24..23944d95efd5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c @@ -21,6 +21,35 @@ */ #include "chid.h" +void +nvkm_chid_put(struct nvkm_chid *chid, int id, spinlock_t *data_lock) +{ + if (id >= 0) { + spin_lock_irq(&chid->lock); + spin_lock(data_lock); + chid->data[id] = NULL; + spin_unlock(data_lock); + clear_bit(id, chid->used); + spin_unlock_irq(&chid->lock); + } +} + +int +nvkm_chid_get(struct nvkm_chid *chid, void *data) +{ + int id = -1, cid; + + spin_lock_irq(&chid->lock); + cid = find_first_zero_bit(chid->used, chid->nr); + if (cid < chid->nr) { + set_bit(cid, chid->used); + chid->data[cid] = data; + id = cid; + } + spin_unlock_irq(&chid->lock); + return id; +} + static void nvkm_chid_del(struct kref *kref) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h index d359828dde80..2a42efb18401 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h @@ -20,4 +20,6 @@ int nvkm_chid_new(const struct nvkm_event_func *, struct nvkm_subdev *, int nr, int first, int count, struct nvkm_chid **pchid); struct nvkm_chid *nvkm_chid_ref(struct nvkm_chid *); void nvkm_chid_unref(struct nvkm_chid **); +int nvkm_chid_get(struct nvkm_chid *, void *data); +void nvkm_chid_put(struct nvkm_chid *, int id, spinlock_t *data_lock); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index ce965d6aa874..52fe9d5a5a4a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -489,7 +489,6 @@ nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, if (ret) return ret; - set_bit(nr - 1, fifo->base.mask); /* inactive channel */ return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index e4a7ef5aa461..4fcf49dbfd90 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -155,8 +155,6 @@ nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, if (ret) return ret; - set_bit(0, fifo->base.mask); /* PIO channel */ - set_bit(127, fifo->base.mask); /* inactive channel */ return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 4d7319674128..1a15b0a9ab7c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -38,6 +38,7 @@ nvkm_runl_del(struct nvkm_runl *runl) nvkm_chid_unref(&runl->cgid); list_del(&runl->head); + mutex_destroy(&runl->mutex); kfree(runl); } @@ -94,6 +95,8 @@ nvkm_runl_new(struct nvkm_fifo *fifo, int runi, u32 addr, int id_nr) runl->id = runi; runl->addr = addr; INIT_LIST_HEAD(&runl->engns); + INIT_LIST_HEAD(&runl->cgrps); + mutex_init(&runl->mutex); list_add_tail(&runl->head, &fifo->runls); if (!fifo->chid) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index 9f27babc8caf..cb0de870a118 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -35,6 +35,11 @@ struct nvkm_runl { struct nvkm_runq *runq[2]; int runq_nr; + struct list_head cgrps; + int cgrp_nr; + int chan_nr; + struct mutex mutex; + struct list_head head; }; @@ -44,8 +49,12 @@ struct nvkm_engn *nvkm_runl_add(struct nvkm_runl *, int engi, const struct nvkm_ enum nvkm_subdev_type, int inst); void nvkm_runl_del(struct nvkm_runl *); +#define nvkm_runl_find_engn(engn,runl,cond) nvkm_list_find(engn, &(runl)->engns, head, (cond)) + #define nvkm_runl_foreach(runl,fifo) list_for_each_entry((runl), &(fifo)->runls, head) #define nvkm_runl_foreach_engn(engn,runl) list_for_each_entry((engn), &(runl)->engns, head) +#define nvkm_runl_foreach_engn_cond(engn,runl,cond) \ + nvkm_list_foreach(engn, &(runl)->engns, head, (cond)) #define RUNL_PRINT(r,l,p,f,a...) \ nvkm_printk__(&(r)->fifo->engine.subdev, NV_DBG_##l, p, "%06x:"f, (r)->addr, ##a) -- cgit v1.2.3 From 0fc72ee9d8d665484ecae652d114f577313c4cc6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:26 +1000 Subject: drm/nouveau/fifo: use runlist engine info to lookup engine classes Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 46 --------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 47 ---------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 10 ----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 19 --------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 3 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 40 +++++++++++++++--- 22 files changed, 35 insertions(+), 146 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 62fe64dab11a..446d058f558a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -22,7 +22,6 @@ struct nvkm_chan { union { int id; int chid; }; /*FIXME: remove later */ struct nvkm_fifo *fifo; - u32 engm; struct nvkm_object object; struct list_head head; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index e2178a8f78a7..5fabf7373079 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -216,50 +216,6 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, return 0; } -static int -nvkm_fifo_chan_child_get(struct nvkm_object *object, int index, - struct nvkm_oclass *oclass) -{ - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - struct nvkm_fifo *fifo = chan->fifo; - struct nvkm_engine *engine; - u32 engm = chan->engm; - int engi, ret, c; - - for (; c = 0, engi = __ffs(engm), engm; engm &= ~(1ULL << engi)) { - if (!(engine = fifo->func->id_engine(fifo, engi))) - continue; - oclass->engine = engine; - oclass->base.oclass = 0; - - if (engine->func->fifo.sclass) { - ret = engine->func->fifo.sclass(oclass, index); - if (oclass->base.oclass) { - if (!oclass->base.ctor) - oclass->base.ctor = nvkm_object_new; - oclass->ctor = nvkm_fifo_chan_child_new; - return 0; - } - - index -= ret; - continue; - } - - while (engine->func->sclass[c].oclass) { - if (c++ == index) { - oclass->base = engine->func->sclass[index]; - if (!oclass->base.ctor) - oclass->base.ctor = nvkm_object_new; - oclass->ctor = nvkm_fifo_chan_child_new; - return 0; - } - } - index -= c; - } - - return -EINVAL; -} - static int nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) { @@ -355,7 +311,6 @@ nvkm_fifo_chan_func = { .init = nvkm_fifo_chan_init, .fini = nvkm_fifo_chan_fini, .map = nvkm_fifo_chan_map, - .sclass = nvkm_fifo_chan_child_get, .uevent = nvkm_fifo_chan_uevent, }; @@ -407,7 +362,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); chan->fifo = fifo; - chan->engm = engm; INIT_LIST_HEAD(&chan->head); /* Join channel group. diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 3d242350fdee..122929b7d74f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -51,52 +51,6 @@ g84_fifo_uevent_init(struct nvkm_fifo *fifo) nvkm_mask(device, 0x002140, 0x40000000, 0x40000000); } -struct nvkm_engine * -g84_fifo_id_engine(struct nvkm_fifo *fifo, int engi) -{ - struct nvkm_device *device = fifo->engine.subdev.device; - struct nvkm_engine *engine; - enum nvkm_subdev_type type; - - switch (engi) { - case G84_FIFO_ENGN_SW : type = NVKM_ENGINE_SW; break; - case G84_FIFO_ENGN_GR : type = NVKM_ENGINE_GR; break; - case G84_FIFO_ENGN_MPEG : - if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSPPP, 0))) - return engine; - type = NVKM_ENGINE_MPEG; - break; - case G84_FIFO_ENGN_ME : - if ((engine = nvkm_device_engine(device, NVKM_ENGINE_CE, 0))) - return engine; - type = NVKM_ENGINE_ME; - break; - case G84_FIFO_ENGN_VP : - if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSPDEC, 0))) - return engine; - type = NVKM_ENGINE_VP; - break; - case G84_FIFO_ENGN_CIPHER: - if ((engine = nvkm_device_engine(device, NVKM_ENGINE_VIC, 0))) - return engine; - if ((engine = nvkm_device_engine(device, NVKM_ENGINE_SEC, 0))) - return engine; - type = NVKM_ENGINE_CIPHER; - break; - case G84_FIFO_ENGN_BSP : - if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSVLD, 0))) - return engine; - type = NVKM_ENGINE_BSP; - break; - case G84_FIFO_ENGN_DMA : type = NVKM_ENGINE_DMAOBJ; break; - default: - WARN_ON(1); - return NULL; - } - - return nvkm_device_engine(fifo->engine.subdev.device, type, 0); -} - int g84_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) { @@ -149,7 +103,6 @@ g84_fifo = { .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = g84_fifo_engine_id, - .id_engine = g84_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .uevent_init = g84_fifo_uevent_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c index 39177ec0eca6..118a773412fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c @@ -57,7 +57,6 @@ g98_fifo = { .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = g84_fifo_engine_id, - .id_engine = g84_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .uevent_init = g84_fifo_uevent_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 43cce02151d7..3d169f3ef512 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -741,7 +741,6 @@ gf100_fifo = { .intr = gf100_fifo_intr, .mmu_fault = &gf100_fifo_mmu_fault, .engine_id = gf100_fifo_engine_id, - .id_engine = gf100_fifo_id_engine, .uevent_init = gf100_fifo_uevent_init, .uevent_fini = gf100_fifo_uevent_fini, .runl = &gf100_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index b41481c984d1..9d66aafc2dd3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -303,15 +303,6 @@ gk104_fifo_pbdma = { .init = gk104_fifo_pbdma_init, }; -struct nvkm_engine * -gk104_fifo_id_engine(struct nvkm_fifo *base, int engi) -{ - if (engi == GK104_FIFO_ENGN_SW) - return nvkm_device_engine(base->engine.subdev.device, NVKM_ENGINE_SW, 0); - - return gk104_fifo(base)->engine[engi].engine; -} - int gk104_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) { @@ -1185,7 +1176,6 @@ gk104_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 64bdd3fd3ae6..ed3aa170d429 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -93,7 +93,6 @@ gk110_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 3e074a976c44..7219dc92f451 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -72,7 +72,6 @@ gk208_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index a494dacad37e..9dfa93d914e0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -43,7 +43,6 @@ gk20a_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index c4a6972ee473..4b67fe1ed81a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -133,7 +133,6 @@ gm107_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index bc9893c4d297..5c81f8b8d6c0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -63,7 +63,6 @@ gm200_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 4ac4afbf3147..d90ba4170d98 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -105,7 +105,6 @@ gp100_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index e1069c672438..c2b32688cbd1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -332,7 +332,6 @@ gv100_fifo = { .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 52fe9d5a5a4a..120eb8b7611f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -182,24 +182,6 @@ const struct nvkm_runl_func nv04_runl = { }; -struct nvkm_engine * -nv04_fifo_id_engine(struct nvkm_fifo *fifo, int engi) -{ - enum nvkm_subdev_type type; - - switch (engi) { - case NV04_FIFO_ENGN_SW : type = NVKM_ENGINE_SW; break; - case NV04_FIFO_ENGN_GR : type = NVKM_ENGINE_GR; break; - case NV04_FIFO_ENGN_MPEG: type = NVKM_ENGINE_MPEG; break; - case NV04_FIFO_ENGN_DMA : type = NVKM_ENGINE_DMAOBJ; break; - default: - WARN_ON(1); - return NULL; - } - - return nvkm_device_engine(fifo->engine.subdev.device, type, 0); -} - int nv04_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) { @@ -500,7 +482,6 @@ nv04_fifo = { .init = nv04_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, - .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv04_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index 84416440a822..0f7c88ae5a1c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -61,7 +61,6 @@ nv10_fifo = { .init = nv04_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, - .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv04_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index 28ae10a78ee4..59b752986ac1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -93,7 +93,6 @@ nv17_fifo = { .init = nv17_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, - .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv04_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index 492609780c9b..d0fc6c528825 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -133,7 +133,6 @@ nv40_fifo = { .init = nv40_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, - .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv04_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 4fcf49dbfd90..46013aea97d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -168,7 +168,6 @@ nv50_fifo = { .init = nv50_fifo_init, .intr = nv04_fifo_intr, .engine_id = nv04_fifo_engine_id, - .id_engine = nv04_fifo_id_engine, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv50_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h index 9a23a84ea7f4..b8f7201ba7f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h @@ -19,7 +19,6 @@ void nv50_fifo_init(struct nvkm_fifo *); void nv50_fifo_runlist_update(struct nv50_fifo *); int g84_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); -struct nvkm_engine *g84_fifo_id_engine(struct nvkm_fifo *, int); void g84_fifo_uevent_init(struct nvkm_fifo *); void g84_fifo_uevent_fini(struct nvkm_fifo *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index b0fa9d1df91d..1b0a3027f297 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -44,7 +44,6 @@ struct nvkm_fifo_func { } fault; int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *); - struct nvkm_engine *(*id_engine)(struct nvkm_fifo *, int engi); void (*pause)(struct nvkm_fifo *, unsigned long *); void (*start)(struct nvkm_fifo *, unsigned long *); void (*uevent_init)(struct nvkm_fifo *); @@ -98,7 +97,6 @@ int nv04_fifo_runl_ctor(struct nvkm_fifo *); void nv04_fifo_init(struct nvkm_fifo *); void nv04_fifo_intr(struct nvkm_fifo *); int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); -struct nvkm_engine *nv04_fifo_id_engine(struct nvkm_fifo *, int); void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); extern const struct nvkm_runl_func nv04_runl; @@ -127,7 +125,6 @@ extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); -struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int); extern const struct nvkm_runq_func gk104_runq; extern const struct nvkm_engn_func gk104_engn; extern const struct nvkm_engn_func gk104_engn_ce; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index e5b9b1fc3866..f2c90c7dda7d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -459,7 +459,6 @@ tu102_fifo = { .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .id_engine = gk104_fifo_id_engine, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = tu102_fifo_recover_chan, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index 42b49043deef..6f920e0e1008 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -22,6 +22,7 @@ #define nvkm_uchan(p) container_of((p), struct nvkm_uchan, object) #include "cgrp.h" #include "chan.h" +#include "runl.h" #include @@ -89,14 +90,43 @@ static int nvkm_uchan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass) { struct nvkm_chan *chan = nvkm_uchan(object)->chan; + struct nvkm_engn *engn; int ret; - ret = chan->object.func->sclass(&chan->object, index, oclass); - if (ret) - return ret; + nvkm_runl_foreach_engn(engn, chan->cgrp->runl) { + struct nvkm_engine *engine = engn->engine; + int c = 0; + + oclass->engine = engine; + oclass->base.oclass = 0; + + if (engine->func->fifo.sclass) { + ret = engine->func->fifo.sclass(oclass, index); + if (oclass->base.oclass) { + if (!oclass->base.ctor) + oclass->base.ctor = nvkm_object_new; + oclass->ctor = nvkm_uchan_object_new; + return 0; + } + + index -= ret; + continue; + } + + while (engine->func->sclass[c].oclass) { + if (c++ == index) { + oclass->base = engine->func->sclass[index]; + if (!oclass->base.ctor) + oclass->base.ctor = nvkm_object_new; + oclass->ctor = nvkm_uchan_object_new; + return 0; + } + } + + index -= c; + } - oclass->ctor = nvkm_uchan_object_new; - return 0; + return -EINVAL; } static int -- cgit v1.2.3 From 2fc71a0566f63ac3cd43d7cf2d5efbbab6293c5f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:26 +1000 Subject: drm/nouveau/fifo: use explicit intr interfaces More control, and shallower call-chain to get to the point. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 27 ++++++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 21 ++++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 53 ++++++++++++------------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 3 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 34 ++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 8 ++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 28 +++++++------ drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c | 2 +- 17 files changed, 105 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 3e62eacc48ad..d93e71870d8d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -193,19 +193,16 @@ nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, const struct nvkm_dev return c; } -static void -nvkm_fifo_intr(struct nvkm_engine *engine) -{ - struct nvkm_fifo *fifo = nvkm_fifo(engine); - fifo->func->intr(fifo); -} - static int nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + + nvkm_inth_block(&fifo->engine.subdev.inth); + if (fifo->func->fini) fifo->func->fini(fifo); + return 0; } @@ -213,7 +210,10 @@ static int nvkm_fifo_init(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + fifo->func->init(fifo); + + nvkm_inth_allow(&fifo->engine.subdev.inth); return 0; } @@ -290,6 +290,8 @@ nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data) static int nvkm_fifo_oneinit(struct nvkm_engine *engine) { + struct nvkm_subdev *subdev = &engine->subdev; + struct nvkm_device *device = subdev->device; struct nvkm_fifo *fifo = nvkm_fifo(engine); struct nvkm_runl *runl; struct nvkm_engn *engn; @@ -322,6 +324,16 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) } } + /* Register interrupt handler. */ + if (fifo->func->intr) { + ret = nvkm_inth_add(&device->mc->intr, NVKM_INTR_SUBDEV, NVKM_INTR_PRIO_NORMAL, + subdev, fifo->func->intr, &subdev->inth); + if (ret) { + nvkm_error(subdev, "intr %d\n", ret); + return ret; + } + } + if (fifo->func->oneinit) return fifo->func->oneinit(fifo); @@ -366,7 +378,6 @@ nvkm_fifo = { .info = nvkm_fifo_info, .init = nvkm_fifo_init, .fini = nvkm_fifo_fini, - .intr = nvkm_fifo_intr, .base.sclass = nvkm_fifo_class_get, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 3d169f3ef512..1a7ec75ce893 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -525,11 +526,11 @@ gf100_fifo_intr_engine(struct gf100_fifo *fifo) } } -static void -gf100_fifo_intr(struct nvkm_fifo *base) +static irqreturn_t +gf100_fifo_intr(struct nvkm_inth *inth) { - struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth); + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 mask = nvkm_rd32(device, 0x002140); u32 stat = nvkm_rd32(device, 0x002100) & mask; @@ -542,7 +543,7 @@ gf100_fifo_intr(struct nvkm_fifo *base) } if (stat & 0x00000100) { - gf100_fifo_intr_sched(fifo); + gf100_fifo_intr_sched(gf100_fifo(fifo)); nvkm_wr32(device, 0x002100, 0x00000100); stat &= ~0x00000100; } @@ -565,7 +566,7 @@ gf100_fifo_intr(struct nvkm_fifo *base) u32 mask = nvkm_rd32(device, 0x00259c); while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_mmu_fault_unit(&fifo->base, unit); + gf100_fifo_intr_mmu_fault_unit(fifo, unit); nvkm_wr32(device, 0x00259c, (1 << unit)); mask &= ~(1 << unit); } @@ -576,7 +577,7 @@ gf100_fifo_intr(struct nvkm_fifo *base) u32 mask = nvkm_rd32(device, 0x0025a0); while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_pbdma(fifo, unit); + gf100_fifo_intr_pbdma(gf100_fifo(fifo), unit); nvkm_wr32(device, 0x0025a0, (1 << unit)); mask &= ~(1 << unit); } @@ -584,12 +585,12 @@ gf100_fifo_intr(struct nvkm_fifo *base) } if (stat & 0x40000000) { - gf100_fifo_intr_runlist(fifo); + gf100_fifo_intr_runlist(gf100_fifo(fifo)); stat &= ~0x40000000; } if (stat & 0x80000000) { - gf100_fifo_intr_engine(fifo); + gf100_fifo_intr_engine(gf100_fifo(fifo)); stat &= ~0x80000000; } @@ -598,6 +599,8 @@ gf100_fifo_intr(struct nvkm_fifo *base) nvkm_mask(device, 0x002140, stat, 0x00000000); nvkm_wr32(device, 0x002100, stat); } + + return IRQ_HANDLED; } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 9d66aafc2dd3..07fa79194870 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -720,7 +721,7 @@ gk104_fifo_mmu_fault = { }; static const struct nvkm_enum -gk104_fifo_bind_reason[] = { +gk104_fifo_intr_bind_reason[] = { { 0x01, "BIND_NOT_UNBOUND" }, { 0x02, "SNOOP_WITHOUT_BAR1" }, { 0x03, "UNBIND_WHILE_RUNNING" }, @@ -731,14 +732,12 @@ gk104_fifo_bind_reason[] = { }; void -gk104_fifo_intr_bind(struct gk104_fifo *fifo) +gk104_fifo_intr_bind(struct nvkm_fifo *fifo) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 intr = nvkm_rd32(device, 0x00252c); + struct nvkm_subdev *subdev = &fifo->engine.subdev; + u32 intr = nvkm_rd32(subdev->device, 0x00252c); u32 code = intr & 0x000000ff; - const struct nvkm_enum *en = - nvkm_enum_find(gk104_fifo_bind_reason, code); + const struct nvkm_enum *en = nvkm_enum_find(gk104_fifo_intr_bind_reason, code); nvkm_error(subdev, "BIND_ERROR %02x [%s]\n", code, en ? en->name : ""); } @@ -802,21 +801,22 @@ gk104_fifo_intr_sched(struct gk104_fifo *fifo) } void -gk104_fifo_intr_chsw(struct gk104_fifo *fifo) +gk104_fifo_intr_chsw(struct nvkm_fifo *fifo) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x00256c); + nvkm_error(subdev, "CHSW_ERROR %08x\n", stat); nvkm_wr32(device, 0x00256c, stat); } -void -gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo) +static void +gk104_fifo_intr_dropped_fault(struct nvkm_fifo *fifo) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 stat = nvkm_rd32(device, 0x00259c); + struct nvkm_subdev *subdev = &fifo->engine.subdev; + u32 stat = nvkm_rd32(subdev->device, 0x00259c); + nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat); } @@ -879,11 +879,11 @@ gk104_fifo_intr_engine(struct gk104_fifo *fifo) nvkm_fifo_uevent(&fifo->base); } -void -gk104_fifo_intr(struct nvkm_fifo *base) +irqreturn_t +gk104_fifo_intr(struct nvkm_inth *inth) { - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth); + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 mask = nvkm_rd32(device, 0x002140); u32 stat = nvkm_rd32(device, 0x002100) & mask; @@ -901,7 +901,7 @@ gk104_fifo_intr(struct nvkm_fifo *base) } if (stat & 0x00000100) { - gk104_fifo_intr_sched(fifo); + gk104_fifo_intr_sched(gk104_fifo(fifo)); nvkm_wr32(device, 0x002100, 0x00000100); stat &= ~0x00000100; } @@ -934,7 +934,7 @@ gk104_fifo_intr(struct nvkm_fifo *base) u32 mask = nvkm_rd32(device, 0x00259c); while (mask) { u32 unit = __ffs(mask); - fifo->func->intr_mmu_fault_unit(&fifo->base, unit); + fifo->func->intr_mmu_fault_unit(fifo, unit); nvkm_wr32(device, 0x00259c, (1 << unit)); mask &= ~(1 << unit); } @@ -945,8 +945,8 @@ gk104_fifo_intr(struct nvkm_fifo *base) u32 mask = nvkm_rd32(device, 0x0025a0); while (mask) { u32 unit = __ffs(mask); - gk104_fifo_intr_pbdma_0(fifo, unit); - gk104_fifo_intr_pbdma_1(fifo, unit); + gk104_fifo_intr_pbdma_0(gk104_fifo(fifo), unit); + gk104_fifo_intr_pbdma_1(gk104_fifo(fifo), unit); nvkm_wr32(device, 0x0025a0, (1 << unit)); mask &= ~(1 << unit); } @@ -954,13 +954,13 @@ gk104_fifo_intr(struct nvkm_fifo *base) } if (stat & 0x40000000) { - gk104_fifo_intr_runlist(fifo); + gk104_fifo_intr_runlist(gk104_fifo(fifo)); stat &= ~0x40000000; } if (stat & 0x80000000) { nvkm_wr32(device, 0x002100, 0x80000000); - gk104_fifo_intr_engine(fifo); + gk104_fifo_intr_engine(gk104_fifo(fifo)); stat &= ~0x80000000; } @@ -969,16 +969,15 @@ gk104_fifo_intr(struct nvkm_fifo *base) nvkm_mask(device, 0x002140, stat, 0x00000000); nvkm_wr32(device, 0x002100, stat); } + + return IRQ_HANDLED; } void gk104_fifo_fini(struct nvkm_fifo *base) { struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; flush_work(&fifo->recover.work); - /* allow mmu fault interrupts, even when we're not using fifo */ - nvkm_mask(device, 0x002140, 0x10000000, 0x10000000); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 403560aefbb7..23328a8c19b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -66,9 +66,6 @@ void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_update(struct gk104_fifo *, int runl); void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, struct gk104_fifo_engine_status *status); -void gk104_fifo_intr_bind(struct gk104_fifo *fifo); -void gk104_fifo_intr_chsw(struct gk104_fifo *fifo); -void gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo); void gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit); void gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit); void gk104_fifo_intr_runlist(struct gk104_fifo *fifo); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 120eb8b7611f..4f3fed0fcb50 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -236,9 +237,9 @@ nv04_fifo_swmthd(struct nvkm_device *device, u32 chid, u32 addr, u32 data) } static void -nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get) +nv04_fifo_intr_cache_error(struct nvkm_fifo *fifo, u32 chid, u32 get) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_fifo_chan *chan; unsigned long flags; @@ -263,12 +264,12 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get) if (!(pull0 & 0x00000100) || !nv04_fifo_swmthd(device, chid, mthd, data)) { - chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); + chan = nvkm_fifo_chan_chid(fifo, chid, &flags); nvkm_error(subdev, "CACHE_ERROR - " "ch %d [%s] subc %d mthd %04x data %08x\n", chid, chan ? chan->object.client->name : "unknown", (mthd >> 13) & 7, mthd & 0x1ffc, data); - nvkm_fifo_chan_put(&fifo->base, flags, &chan); + nvkm_fifo_chan_put(fifo, flags, &chan); } nvkm_wr32(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0); @@ -287,9 +288,9 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get) } static void -nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid) +nv04_fifo_intr_dma_pusher(struct nvkm_fifo *fifo, u32 chid) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 dma_get = nvkm_rd32(device, 0x003244); u32 dma_put = nvkm_rd32(device, 0x003240); @@ -299,7 +300,7 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid) unsigned long flags; const char *name; - chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); + chan = nvkm_fifo_chan_chid(fifo, chid, &flags); name = chan ? chan->object.client->name : "unknown"; if (device->card_type == NV_50) { u32 ho_get = nvkm_rd32(device, 0x003328); @@ -331,18 +332,18 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid) if (dma_get != dma_put) nvkm_wr32(device, 0x003244, dma_put); } - nvkm_fifo_chan_put(&fifo->base, flags, &chan); + nvkm_fifo_chan_put(fifo, flags, &chan); nvkm_wr32(device, 0x003228, 0x00000000); nvkm_wr32(device, 0x003220, 0x00000001); nvkm_wr32(device, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); } -void -nv04_fifo_intr(struct nvkm_fifo *base) +irqreturn_t +nv04_fifo_intr(struct nvkm_inth *inth) { - struct nv04_fifo *fifo = nv04_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth); + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 mask = nvkm_rd32(device, NV03_PFIFO_INTR_EN_0); u32 stat = nvkm_rd32(device, NV03_PFIFO_INTR_0) & mask; @@ -351,16 +352,16 @@ nv04_fifo_intr(struct nvkm_fifo *base) reassign = nvkm_rd32(device, NV03_PFIFO_CACHES) & 1; nvkm_wr32(device, NV03_PFIFO_CACHES, 0); - chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.chid->mask; + chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->chid->mask; get = nvkm_rd32(device, NV03_PFIFO_CACHE1_GET); if (stat & NV_PFIFO_INTR_CACHE_ERROR) { - nv04_fifo_cache_error(fifo, chid, get); + nv04_fifo_intr_cache_error(fifo, chid, get); stat &= ~NV_PFIFO_INTR_CACHE_ERROR; } if (stat & NV_PFIFO_INTR_DMA_PUSHER) { - nv04_fifo_dma_pusher(fifo, chid); + nv04_fifo_intr_dma_pusher(fifo, chid); stat &= ~NV_PFIFO_INTR_DMA_PUSHER; } @@ -383,7 +384,7 @@ nv04_fifo_intr(struct nvkm_fifo *base) if (stat & 0x40000000) { nvkm_wr32(device, 0x002100, 0x40000000); - nvkm_fifo_uevent(&fifo->base); + nvkm_fifo_uevent(fifo); stat &= ~0x40000000; } } @@ -395,6 +396,7 @@ nv04_fifo_intr(struct nvkm_fifo *base) } nvkm_wr32(device, NV03_PFIFO_CACHES, reassign); + return IRQ_HANDLED; } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 1b0a3027f297..f314f107f2eb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -28,7 +28,7 @@ struct nvkm_fifo_func { void (*init)(struct nvkm_fifo *); void (*fini)(struct nvkm_fifo *); - void (*intr)(struct nvkm_fifo *); + irqreturn_t (*intr)(struct nvkm_inth *); void (*intr_mmu_fault_unit)(struct nvkm_fifo *, int unit); const struct nvkm_fifo_func_mmu_fault { @@ -95,7 +95,7 @@ int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvk int nv04_fifo_chid_ctor(struct nvkm_fifo *, int); int nv04_fifo_runl_ctor(struct nvkm_fifo *); void nv04_fifo_init(struct nvkm_fifo *); -void nv04_fifo_intr(struct nvkm_fifo *); +irqreturn_t nv04_fifo_intr(struct nvkm_inth *); int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); @@ -120,7 +120,9 @@ extern const struct nvkm_engn_func gf100_engn_sw; int gk104_fifo_chid_nr(struct nvkm_fifo *); int gk104_fifo_runl_ctor(struct nvkm_fifo *); -void gk104_fifo_intr(struct nvkm_fifo *); +irqreturn_t gk104_fifo_intr(struct nvkm_inth *); +void gk104_fifo_intr_chsw(struct nvkm_fifo *); +void gk104_fifo_intr_bind(struct nvkm_fifo *); extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); void gk104_fifo_recover_chan(struct nvkm_fifo *, int); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index f2c90c7dda7d..ae399c6a192d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -367,21 +368,20 @@ tu102_fifo_intr_ctxsw_timeout(struct gk104_fifo *fifo) } static void -tu102_fifo_intr_sched(struct gk104_fifo *fifo) +tu102_fifo_intr_sched(struct nvkm_fifo *fifo) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 intr = nvkm_rd32(device, 0x00254c); + struct nvkm_subdev *subdev = &fifo->engine.subdev; + u32 intr = nvkm_rd32(subdev->device, 0x00254c); u32 code = intr & 0x000000ff; nvkm_error(subdev, "SCHED_ERROR %02x\n", code); } -static void -tu102_fifo_intr(struct nvkm_fifo *base) +static irqreturn_t +tu102_fifo_intr(struct nvkm_inth *inth) { - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth); + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 mask = nvkm_rd32(device, 0x002140); u32 stat = nvkm_rd32(device, 0x002100) & mask; @@ -393,7 +393,7 @@ tu102_fifo_intr(struct nvkm_fifo *base) } if (stat & 0x00000002) { - tu102_fifo_intr_ctxsw_timeout(fifo); + tu102_fifo_intr_ctxsw_timeout(gk104_fifo(fifo)); stat &= ~0x00000002; } @@ -415,8 +415,8 @@ tu102_fifo_intr(struct nvkm_fifo *base) while (mask) { u32 unit = __ffs(mask); - gk104_fifo_intr_pbdma_0(fifo, unit); - gk104_fifo_intr_pbdma_1(fifo, unit); + gk104_fifo_intr_pbdma_0(gk104_fifo(fifo), unit); + gk104_fifo_intr_pbdma_1(gk104_fifo(fifo), unit); nvkm_wr32(device, 0x0025a0, (1 << unit)); mask &= ~(1 << unit); } @@ -424,13 +424,13 @@ tu102_fifo_intr(struct nvkm_fifo *base) } if (stat & 0x40000000) { - gk104_fifo_intr_runlist(fifo); + gk104_fifo_intr_runlist(gk104_fifo(fifo)); stat &= ~0x40000000; } if (stat & 0x80000000) { nvkm_wr32(device, 0x002100, 0x80000000); - gk104_fifo_intr_engine(fifo); + gk104_fifo_intr_engine(gk104_fifo(fifo)); stat &= ~0x80000000; } @@ -439,6 +439,8 @@ tu102_fifo_intr(struct nvkm_fifo *base) nvkm_mask(device, 0x002140, stat, 0x00000000); nvkm_wr32(device, 0x002100, stat); } + + return IRQ_HANDLED; } static const struct nvkm_fifo_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c index 9feb7d167d23..f4ee99137b1f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c @@ -41,7 +41,7 @@ g84_mc_intrs[] = { { NVKM_ENGINE_BSP , 0, 0, 0x00008000, true }, { NVKM_ENGINE_CIPHER, 0, 0, 0x00004000, true }, { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true }, { NVKM_SUBDEV_FB , 0, 0, 0x0002d101, true }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c index b0b328044e55..f42684809f08 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c @@ -41,7 +41,7 @@ g98_mc_intrs[] = { { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true }, { NVKM_ENGINE_SEC , 0, 0, 0x00004000, true }, { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true }, { NVKM_SUBDEV_FB , 0, 0, 0x0002d101, true }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c index d5dba44235cf..5118e413d053 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c @@ -42,7 +42,7 @@ gf100_mc_intrs[] = { { NVKM_ENGINE_MSPDEC , 0, 0, 0x00020000, true }, { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true }, { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_ENGINE_CE , 1, 0, 0x00000040, true }, { NVKM_ENGINE_CE , 0, 0, 0x00000020, true }, { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c index 023dfda735cd..9d482f358138 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c @@ -33,7 +33,7 @@ gk104_mc_reset[] = { const struct nvkm_intr_data gk104_mc_intrs[] = { { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_SUBDEV_PRIVRING, 0, 0, 0x40000000, true }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, { NVKM_SUBDEV_FB , 0, 0, 0x08002000, true }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c index bffde40bb237..7606bed2ff6f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c @@ -26,7 +26,7 @@ const struct nvkm_intr_data gp100_mc_intrs[] = { { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_SUBDEV_FAULT , 0, 0, 0x00000200, true }, { NVKM_SUBDEV_PRIVRING, 0, 0, 0x40000000, true }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c index 41e17a470388..3d61836e42a3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c @@ -41,7 +41,7 @@ gt215_mc_intrs[] = { { NVKM_ENGINE_MSPDEC, 0, 0, 0x00020000, true }, { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true }, { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true }, { NVKM_SUBDEV_FB , 0, 0, 0x00429101, true }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c index 04809caf36d6..8482a5550e5f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c @@ -62,7 +62,7 @@ static const struct nvkm_intr_data nv04_mc_intrs[] = { { NVKM_ENGINE_DISP , 0, 0, 0x01010000, true }, { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true }, {} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c index 6a3e2f4753ef..6d6278f434a4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c @@ -27,7 +27,7 @@ static const struct nvkm_intr_data nv11_mc_intrs[] = { { NVKM_ENGINE_DISP , 0, 0, 0x03010000, true }, { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true }, {} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c index 2edc1cb0e379..dbad7c111ceb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c @@ -35,7 +35,7 @@ const struct nvkm_intr_data nv17_mc_intrs[] = { { NVKM_ENGINE_DISP , 0, 0, 0x03010000, true }, { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c index a42d20206e37..d41099d35690 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c @@ -27,7 +27,7 @@ static const struct nvkm_intr_data nv50_mc_intrs[] = { { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, - { NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true }, + { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true }, { NVKM_SUBDEV_FB , 0, 0, 0x00001101, true }, { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true }, -- cgit v1.2.3 From d67f3b96462922713e77cddb9d6f4965606918fc Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:27 +1000 Subject: drm/nouveau/fifo: tidy up non-stall intr handling - removes a layer of indirection in the intr handling - prevents non-stall ctrl racing with unknown intrs Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 7 ++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 34 ++----------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 3 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 33 ++++++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 59 ++++++++++++++-------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 27 ++-------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 3 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 7 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 7 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 3 ++ 20 files changed, 93 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 446d058f558a..d3412c916290 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -44,13 +44,16 @@ struct nvkm_fifo { struct list_head runqs; struct list_head runls; + struct { +#define NVKM_FIFO_NONSTALL_EVENT BIT(0) + struct nvkm_event event; + } nonstall; + int nr; struct list_head chan; spinlock_t lock; struct mutex mutex; -#define NVKM_FIFO_EVENT_NON_STALL_INTR BIT(0) - struct nvkm_event uevent; /* async user trigger */ #define NVKM_FIFO_EVENT_KILLED BIT(0) struct nvkm_event kevent; /* channel killed */ }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index d93e71870d8d..d2a9e891939f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -129,32 +129,6 @@ static const struct nvkm_event_func nvkm_fifo_kevent_func = { }; -static void -nvkm_fifo_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); - fifo->func->uevent_fini(fifo); -} - -static void -nvkm_fifo_uevent_init(struct nvkm_event *event, int type, int index) -{ - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); - fifo->func->uevent_init(fifo); -} - -static const struct nvkm_event_func -nvkm_fifo_uevent_func = { - .init = nvkm_fifo_uevent_init, - .fini = nvkm_fifo_uevent_fini, -}; - -void -nvkm_fifo_uevent(struct nvkm_fifo *fifo) -{ - nvkm_event_ntfy(&fifo->uevent, 0, NVKM_FIFO_EVENT_NON_STALL_INTR); -} - static int nvkm_fifo_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) @@ -365,7 +339,7 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) if (fifo->func->dtor) data = fifo->func->dtor(fifo); nvkm_event_fini(&fifo->kevent); - nvkm_event_fini(&fifo->uevent); + nvkm_event_fini(&fifo->nonstall.event); mutex_destroy(&fifo->mutex); return data; } @@ -402,9 +376,9 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, nr = func->chid_nr(fifo); fifo->nr = nr; - if (func->uevent_init) { - ret = nvkm_event_init(&nvkm_fifo_uevent_func, &fifo->engine.subdev, 1, 1, - &fifo->uevent); + if (func->nonstall) { + ret = nvkm_event_init(func->nonstall, &fifo->engine.subdev, 1, 1, + &fifo->nonstall.event); if (ret) return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 5fabf7373079..ea8148bad45e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -223,9 +223,6 @@ nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct n union nvif_chan_event_args *args = argv; switch (args->v0.type) { - case NVIF_CHAN_EVENT_V0_NON_STALL_INTR: - return nvkm_uevent_add(uevent, &chan->fifo->uevent, 0, - NVKM_FIFO_EVENT_NON_STALL_INTR, NULL); case NVIF_CHAN_EVENT_V0_KILLED: return nvkm_uevent_add(uevent, &chan->fifo->kevent, chan->chid, NVKM_FIFO_EVENT_KILLED, NULL); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 122929b7d74f..afaa2dea4ef8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -37,20 +37,34 @@ const struct nvkm_engn_func g84_engn = { }; -void -g84_fifo_uevent_fini(struct nvkm_fifo *fifo) +static void +g84_fifo_nonstall_block(struct nvkm_event *event, int type, int index) { - struct nvkm_device *device = fifo->engine.subdev.device; - nvkm_mask(device, 0x002140, 0x40000000, 0x00000000); + struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x40000000, 0x00000000); + spin_unlock_irqrestore(&fifo->lock, flags); } -void -g84_fifo_uevent_init(struct nvkm_fifo *fifo) +static void +g84_fifo_nonstall_allow(struct nvkm_event *event, int type, int index) { - struct nvkm_device *device = fifo->engine.subdev.device; - nvkm_mask(device, 0x002140, 0x40000000, 0x40000000); + struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x40000000, 0x40000000); + spin_unlock_irqrestore(&fifo->lock, flags); } +const struct nvkm_event_func +g84_fifo_nonstall = { + .init = g84_fifo_nonstall_allow, + .fini = g84_fifo_nonstall_block, +}; + int g84_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) { @@ -105,8 +119,7 @@ g84_fifo = { .engine_id = g84_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, - .uevent_init = g84_fifo_uevent_init, - .uevent_fini = g84_fifo_uevent_fini, + .nonstall = &g84_fifo_nonstall, .runl = &nv50_runl, .engn = &g84_engn, .engn_sw = &nv50_engn_sw, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c index 118a773412fc..a912e1ba4339 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c @@ -59,8 +59,7 @@ g98_fifo = { .engine_id = g84_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, - .uevent_init = g84_fifo_uevent_init, - .uevent_fini = g84_fifo_uevent_fini, + .nonstall = &g84_fifo_nonstall, .runl = &nv50_runl, .engn = &g84_engn, .engn_sw = &nv50_engn_sw, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 1a7ec75ce893..3d091604fd0a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -39,20 +39,6 @@ #include -static void -gf100_fifo_uevent_init(struct nvkm_fifo *fifo) -{ - struct nvkm_device *device = fifo->engine.subdev.device; - nvkm_mask(device, 0x002140, 0x80000000, 0x80000000); -} - -static void -gf100_fifo_uevent_fini(struct nvkm_fifo *fifo) -{ - struct nvkm_device *device = fifo->engine.subdev.device; - nvkm_mask(device, 0x002140, 0x80000000, 0x00000000); -} - static const struct nvkm_chan_func gf100_chan = { }; @@ -177,6 +163,34 @@ static const struct nvkm_runl_func gf100_runl = { }; +static void +gf100_fifo_nonstall_allow(struct nvkm_event *event, int type, int index) +{ + struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x80000000, 0x80000000); + spin_unlock_irqrestore(&fifo->lock, flags); +} + +void +gf100_fifo_nonstall_block(struct nvkm_event *event, int type, int index) +{ + struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x80000000, 0x00000000); + spin_unlock_irqrestore(&fifo->lock, flags); +} + +const struct nvkm_event_func +gf100_fifo_nonstall = { + .init = gf100_fifo_nonstall_allow, + .fini = gf100_fifo_nonstall_block, +}; + static struct nvkm_engine * gf100_fifo_id_engine(struct nvkm_fifo *fifo, int engi) { @@ -490,9 +504,9 @@ gf100_fifo_intr_runlist(struct gf100_fifo *fifo) } static void -gf100_fifo_intr_engine_unit(struct gf100_fifo *fifo, int engn) +gf100_fifo_intr_engine_unit(struct nvkm_fifo *fifo, int engn) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 intr = nvkm_rd32(device, 0x0025a8 + (engn * 0x04)); u32 inte = nvkm_rd32(device, 0x002628); @@ -503,12 +517,11 @@ gf100_fifo_intr_engine_unit(struct gf100_fifo *fifo, int engn) for (unkn = 0; unkn < 8; unkn++) { u32 ints = (intr >> (unkn * 0x04)) & inte; if (ints & 0x1) { - nvkm_fifo_uevent(&fifo->base); + nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT); ints &= ~1; } if (ints) { - nvkm_error(subdev, "ENGINE %d %d %01x", - engn, unkn, ints); + nvkm_error(subdev, "ENGINE %d %d %01x", engn, unkn, ints); nvkm_mask(device, 0x002628, ints, 0); } } @@ -519,9 +532,10 @@ gf100_fifo_intr_engine(struct gf100_fifo *fifo) { struct nvkm_device *device = fifo->base.engine.subdev.device; u32 mask = nvkm_rd32(device, 0x0025a4); + while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_engine_unit(fifo, unit); + gf100_fifo_intr_engine_unit(&fifo->base, unit); mask &= ~(1 << unit); } } @@ -596,7 +610,9 @@ gf100_fifo_intr(struct nvkm_inth *inth) if (stat) { nvkm_error(subdev, "INTR %08x\n", stat); + spin_lock(&fifo->lock); nvkm_mask(device, 0x002140, stat, 0x00000000); + spin_unlock(&fifo->lock); nvkm_wr32(device, 0x002100, stat); } @@ -744,8 +760,7 @@ gf100_fifo = { .intr = gf100_fifo_intr, .mmu_fault = &gf100_fifo_mmu_fault, .engine_id = gf100_fifo_engine_id, - .uevent_init = gf100_fifo_uevent_init, - .uevent_fini = gf100_fifo_uevent_fini, + .nonstall = &gf100_fifo_nonstall, .runl = &gf100_runl, .runq = &gf100_runq, .engn = &gf100_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 07fa79194870..9c25a27eeb2e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -100,20 +100,6 @@ const struct nvkm_engn_func gk104_engn_ce = { }; -void -gk104_fifo_uevent_fini(struct nvkm_fifo *fifo) -{ - struct nvkm_device *device = fifo->engine.subdev.device; - nvkm_mask(device, 0x002140, 0x80000000, 0x00000000); -} - -void -gk104_fifo_uevent_init(struct nvkm_fifo *fifo) -{ - struct nvkm_device *device = fifo->engine.subdev.device; - nvkm_mask(device, 0x002140, 0x80000000, 0x80000000); -} - static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = { { 0x00000001, "HCE_RE_ILLEGAL_OP" }, { 0x00000002, "HCE_RE_ALIGNB" }, @@ -873,12 +859,6 @@ gk104_fifo_intr_runlist(struct gk104_fifo *fifo) } } -void -gk104_fifo_intr_engine(struct gk104_fifo *fifo) -{ - nvkm_fifo_uevent(&fifo->base); -} - irqreturn_t gk104_fifo_intr(struct nvkm_inth *inth) { @@ -960,13 +940,15 @@ gk104_fifo_intr(struct nvkm_inth *inth) if (stat & 0x80000000) { nvkm_wr32(device, 0x002100, 0x80000000); - gk104_fifo_intr_engine(gk104_fifo(fifo)); + nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT); stat &= ~0x80000000; } if (stat) { nvkm_error(subdev, "INTR %08x\n", stat); + spin_lock(&fifo->lock); nvkm_mask(device, 0x002140, stat, 0x00000000); + spin_unlock(&fifo->lock); nvkm_wr32(device, 0x002100, stat); } @@ -1175,11 +1157,10 @@ gk104_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk104_fifo_runlist, .pbdma = &gk104_fifo_pbdma, + .nonstall = &gf100_fifo_nonstall, .runl = &gk104_runl, .runq = &gk104_runq, .engn = &gk104_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 23328a8c19b3..8d72eaa55568 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -69,13 +69,10 @@ void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, void gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit); void gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit); void gk104_fifo_intr_runlist(struct gk104_fifo *fifo); -void gk104_fifo_intr_engine(struct gk104_fifo *fifo); void *gk104_fifo_dtor(struct nvkm_fifo *base); int gk104_fifo_oneinit(struct nvkm_fifo *); void gk104_fifo_init(struct nvkm_fifo *base); void gk104_fifo_fini(struct nvkm_fifo *base); -void gk104_fifo_uevent_fini(struct nvkm_fifo *fifo); -void gk104_fifo_uevent_init(struct nvkm_fifo *fifo); extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma; void gk104_fifo_pbdma_init(struct gk104_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index ed3aa170d429..9350fbcf0db9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -93,11 +93,10 @@ gk110_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .pbdma = &gk104_fifo_pbdma, + .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk104_runq, .engn = &gk104_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 7219dc92f451..d50f32c530a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -72,10 +72,9 @@ gk208_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, + .nonstall = &gf100_fifo_nonstall, .pbdma = &gk208_fifo_pbdma, .runl = &gk110_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 9dfa93d914e0..add5e1a8de0a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -43,11 +43,10 @@ gk20a_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .pbdma = &gk208_fifo_pbdma, + .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk208_runq, .engn = &gk104_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 4b67fe1ed81a..50c6bec03f92 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -133,11 +133,10 @@ gm107_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gk208_fifo_pbdma, + .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, .runq = &gk208_runq, .engn = &gk104_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 5c81f8b8d6c0..497b0e9c7c32 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -63,11 +63,10 @@ gm200_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, .runq = &gk208_runq, .engn = &gk104_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index d90ba4170d98..3fa8c0a1d191 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -105,11 +105,10 @@ gp100_fifo = { .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .nonstall = &gf100_fifo_nonstall, .runl = &gp100_runl, .runq = &gk208_runq, .engn = &gk104_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index c2b32688cbd1..a715dbdcd27e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -332,11 +332,10 @@ gv100_fifo = { .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .runlist = &gv100_fifo_runlist, .pbdma = &gm200_fifo_pbdma, + .nonstall = &gf100_fifo_nonstall, .runl = &gv100_runl, .runq = &gv100_runq, .engn = &gv100_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 4f3fed0fcb50..b899127cfd72 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -384,7 +384,7 @@ nv04_fifo_intr(struct nvkm_inth *inth) if (stat & 0x40000000) { nvkm_wr32(device, 0x002100, 0x40000000); - nvkm_fifo_uevent(fifo); + nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT); stat &= ~0x40000000; } } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h index b8f7201ba7f5..db5fb45a3aa5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h @@ -19,6 +19,4 @@ void nv50_fifo_init(struct nvkm_fifo *); void nv50_fifo_runlist_update(struct nv50_fifo *); int g84_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); -void g84_fifo_uevent_init(struct nvkm_fifo *); -void g84_fifo_uevent_fini(struct nvkm_fifo *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index f314f107f2eb..d9cb4967b799 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -8,7 +8,6 @@ struct nvkm_memory; struct gk104_fifo; struct gk104_fifo_chan; -void nvkm_fifo_uevent(struct nvkm_fifo *); void nvkm_fifo_kevent(struct nvkm_fifo *, int chid); void nvkm_fifo_recover_chan(struct nvkm_fifo *, int chid); @@ -46,8 +45,6 @@ struct nvkm_fifo_func { int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *); void (*pause)(struct nvkm_fifo *, unsigned long *); void (*start)(struct nvkm_fifo *, unsigned long *); - void (*uevent_init)(struct nvkm_fifo *); - void (*uevent_fini)(struct nvkm_fifo *); void (*recover_chan)(struct nvkm_fifo *, int chid); const struct gk104_fifo_runlist_func { @@ -65,6 +62,8 @@ struct nvkm_fifo_func { void (*init_timeout)(struct gk104_fifo *); } *pbdma; + const struct nvkm_event_func *nonstall; + const struct nvkm_runl_func *runl; const struct nvkm_runq_func *runq; const struct nvkm_engn_func *engn; @@ -110,12 +109,14 @@ int nv50_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_runl_func nv50_runl; extern const struct nvkm_engn_func nv50_engn_sw; +extern const struct nvkm_event_func g84_fifo_nonstall; extern const struct nvkm_engn_func g84_engn; extern const struct nvkm_chan_func g84_chan; int gf100_fifo_chid_ctor(struct nvkm_fifo *, int); int gf100_fifo_runq_nr(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); +extern const struct nvkm_event_func gf100_fifo_nonstall; extern const struct nvkm_engn_func gf100_engn_sw; int gk104_fifo_chid_nr(struct nvkm_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index ae399c6a192d..6551376cbdd4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -430,13 +430,15 @@ tu102_fifo_intr(struct nvkm_inth *inth) if (stat & 0x80000000) { nvkm_wr32(device, 0x002100, 0x80000000); - gk104_fifo_intr_engine(gk104_fifo(fifo)); + nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT); stat &= ~0x80000000; } if (stat) { nvkm_error(subdev, "INTR %08x\n", stat); + spin_lock(&fifo->lock); nvkm_mask(device, 0x002140, stat, 0x00000000); + spin_unlock(&fifo->lock); nvkm_wr32(device, 0x002100, stat); } @@ -461,11 +463,10 @@ tu102_fifo = { .fault.hubclient = gv100_fifo_fault_hubclient, .fault.gpcclient = gv100_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, - .uevent_init = gk104_fifo_uevent_init, - .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = tu102_fifo_recover_chan, .runlist = &tu102_fifo_runlist, .pbdma = &tu102_fifo_pbdma, + .nonstall = &gf100_fifo_nonstall, .runl = &tu102_runl, .runq = &gv100_runq, .engn = &gv100_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index 6f920e0e1008..c4f404840806 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -39,6 +39,7 @@ static int nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) { struct nvkm_chan *chan = nvkm_uchan(object)->chan; + struct nvkm_runl *runl = chan->cgrp->runl; union nvif_chan_event_args *args = argv; if (!uevent) @@ -48,6 +49,8 @@ nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_ switch (args->v0.type) { case NVIF_CHAN_EVENT_V0_NON_STALL_INTR: + return nvkm_uevent_add(uevent, &runl->fifo->nonstall.event, 0, + NVKM_FIFO_NONSTALL_EVENT, NULL); case NVIF_CHAN_EVENT_V0_KILLED: return chan->object.func->uevent(&chan->object, argv, argc, uevent); default: -- cgit v1.2.3 From 965c41d9116c713fe80191606096aa384761c8c3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 3 Oct 2022 13:19:08 +1000 Subject: drm/nouveau/fifo: tidy global PBDMA init Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 9 +++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 22 +++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 20 +++++++++----------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 4 +++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 18 ++++++++---------- 14 files changed, 52 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index d2a9e891939f..a6cec417012f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -184,6 +184,15 @@ static int nvkm_fifo_init(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + struct nvkm_runq *runq; + u32 mask = 0; + + if (fifo->func->init_pbdmas) { + nvkm_runq_foreach(runq, fifo) + mask |= BIT(runq->id); + + fifo->func->init_pbdmas(fifo, mask); + } fifo->func->init(fifo); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 3d091604fd0a..d2b616b97f94 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -627,18 +627,16 @@ gf100_fifo_fini(struct nvkm_fifo *base) } static void -gf100_fifo_init(struct nvkm_fifo *base) +gf100_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) { - struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; - int i; + struct nvkm_device *device = fifo->engine.subdev.device; /* Enable PBDMAs. */ - nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1); - nvkm_wr32(device, 0x002204, (1 << fifo->pbdma_nr) - 1); + nvkm_wr32(device, 0x000204, mask); + nvkm_wr32(device, 0x002204, mask); /* Assign engines to PBDMAs. */ - if (fifo->pbdma_nr >= 3) { + if ((mask & 7) == 7) { nvkm_wr32(device, 0x002208, ~(1 << 0)); /* PGRAPH */ nvkm_wr32(device, 0x00220c, ~(1 << 1)); /* PVP */ nvkm_wr32(device, 0x002210, ~(1 << 1)); /* PMSPP */ @@ -647,6 +645,15 @@ gf100_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x00221c, ~(1 << 1)); /* PCE1 */ } +} + +static void +gf100_fifo_init(struct nvkm_fifo *base) +{ + struct gf100_fifo *fifo = gf100_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + int i; + /* PBDMA[n] */ for (i = 0; i < fifo->pbdma_nr; i++) { nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); @@ -756,6 +763,7 @@ gf100_fifo = { .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gf100_fifo_runl_ctor, .init = gf100_fifo_init, + .init_pbdmas = gf100_fifo_init_pbdmas, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, .mmu_fault = &gf100_fifo_mmu_fault, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 9c25a27eeb2e..14c604a03f70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -278,16 +278,8 @@ static const struct nvkm_runl_func gk104_runl = { }; -void -gk104_fifo_pbdma_init(struct gk104_fifo *fifo) -{ - struct nvkm_device *device = fifo->base.engine.subdev.device; - nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1); -} - const struct gk104_fifo_pbdma_func gk104_fifo_pbdma = { - .init = gk104_fifo_pbdma_init, }; int @@ -962,6 +954,14 @@ gk104_fifo_fini(struct nvkm_fifo *base) flush_work(&fifo->recover.work); } +void +gk104_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + + nvkm_wr32(device, 0x000204, mask); +} + void gk104_fifo_init(struct nvkm_fifo *base) { @@ -969,9 +969,6 @@ gk104_fifo_init(struct nvkm_fifo *base) struct nvkm_device *device = fifo->base.engine.subdev.device; int i; - /* Enable PBDMAs. */ - fifo->func->pbdma->init(fifo); - /* PBDMA[n] */ for (i = 0; i < fifo->pbdma_nr; i++) { nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); @@ -1147,6 +1144,7 @@ gk104_fifo = { .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = gk104_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 8d72eaa55568..953177b90e9b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -75,7 +75,6 @@ void gk104_fifo_init(struct nvkm_fifo *base); void gk104_fifo_fini(struct nvkm_fifo *base); extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma; -void gk104_fifo_pbdma_init(struct gk104_fifo *); extern const struct nvkm_enum gk104_fifo_fault_access[]; extern const struct nvkm_enum gk104_fifo_fault_engine[]; extern const struct nvkm_enum gk104_fifo_fault_reason[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 9350fbcf0db9..85705008e0f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -83,6 +83,7 @@ gk110_fifo = { .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = gk104_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index d50f32c530a5..5224723ce424 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -39,7 +39,6 @@ gk208_fifo_pbdma_init_timeout(struct gk104_fifo *fifo) const struct gk104_fifo_pbdma_func gk208_fifo_pbdma = { - .init = gk104_fifo_pbdma_init, .init_timeout = gk208_fifo_pbdma_init_timeout, }; @@ -62,6 +61,7 @@ gk208_fifo = { .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = gk104_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index add5e1a8de0a..8ce3bb39f651 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -33,6 +33,7 @@ gk20a_fifo = { .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = gk104_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 50c6bec03f92..9a608c02c668 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -123,6 +123,7 @@ gm107_fifo = { .runq_nr = gf100_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = gk104_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 497b0e9c7c32..1ecfbea3680a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -34,7 +34,6 @@ gm200_fifo_runq_nr(struct nvkm_fifo *fifo) const struct gk104_fifo_pbdma_func gm200_fifo_pbdma = { - .init = gk104_fifo_pbdma_init, .init_timeout = gk208_fifo_pbdma_init_timeout, }; @@ -53,6 +52,7 @@ gm200_fifo = { .runq_nr = gm200_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = gk104_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 3fa8c0a1d191..1e9c5ea9cd13 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -95,6 +95,7 @@ gp100_fifo = { .runq_nr = gm200_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = gk104_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gp100_fifo_intr_mmu_fault_unit, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index a715dbdcd27e..cc9ddc65e881 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -323,6 +323,7 @@ gv100_fifo = { .runq_nr = gm200_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = gk104_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .mmu_fault = &gv100_fifo_mmu_fault, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index d9cb4967b799..8657e5c84c64 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -25,6 +25,8 @@ struct nvkm_fifo_func { int (*runl_ctor)(struct nvkm_fifo *); void (*init)(struct nvkm_fifo *); + void (*init_pbdmas)(struct nvkm_fifo *, u32 mask); + void (*fini)(struct nvkm_fifo *); irqreturn_t (*intr)(struct nvkm_inth *); @@ -58,7 +60,6 @@ struct nvkm_fifo_func { } *runlist; const struct gk104_fifo_pbdma_func { - void (*init)(struct gk104_fifo *); void (*init_timeout)(struct gk104_fifo *); } *pbdma; @@ -121,6 +122,7 @@ extern const struct nvkm_engn_func gf100_engn_sw; int gk104_fifo_chid_nr(struct nvkm_fifo *); int gk104_fifo_runl_ctor(struct nvkm_fifo *); +void gk104_fifo_init_pbdmas(struct nvkm_fifo *, u32); irqreturn_t gk104_fifo_intr(struct nvkm_inth *); void gk104_fifo_intr_chsw(struct nvkm_fifo *); void gk104_fifo_intr_bind(struct nvkm_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h index 1832a14488c3..3089d9a8e70e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h @@ -15,6 +15,7 @@ struct nvkm_runq { struct nvkm_runq *nvkm_runq_new(struct nvkm_fifo *, int pbid); void nvkm_runq_del(struct nvkm_runq *); +#define nvkm_runq_foreach(runq,fifo) list_for_each_entry((runq), &(fifo)->runqs, head) #define nvkm_runq_foreach_cond(runq,fifo,cond) nvkm_list_foreach(runq, &(fifo)->runqs, head, (cond)) #define RUNQ_PRINT(r,l,p,f,a...) \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 6551376cbdd4..aa933231ec60 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -94,18 +94,8 @@ tu102_fifo_fault_engine[] = { {} }; -static void -tu102_fifo_pbdma_init(struct gk104_fifo *fifo) -{ - struct nvkm_device *device = fifo->base.engine.subdev.device; - const u32 mask = (1 << fifo->pbdma_nr) - 1; - /*XXX: this is a bit of a guess at this point in time. */ - nvkm_mask(device, 0xb65000, 0x80000fff, 0x80000000 | mask); -} - static const struct gk104_fifo_pbdma_func tu102_fifo_pbdma = { - .init = tu102_fifo_pbdma_init, .init_timeout = gk208_fifo_pbdma_init_timeout, }; @@ -445,6 +435,13 @@ tu102_fifo_intr(struct nvkm_inth *inth) return IRQ_HANDLED; } +static void +tu102_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) +{ + /* Not directly related to PBDMAs, but, enables doorbell to function. */ + nvkm_mask(fifo->engine.subdev.device, 0xb65000, 0x80000000, 0x80000000); +} + static const struct nvkm_fifo_func tu102_fifo = { .dtor = gk104_fifo_dtor, @@ -454,6 +451,7 @@ tu102_fifo = { .runq_nr = gm200_fifo_runq_nr, .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, + .init_pbdmas = tu102_fifo_init_pbdmas, .fini = gk104_fifo_fini, .intr = tu102_fifo_intr, .mmu_fault = &tu102_fifo_mmu_fault, -- cgit v1.2.3 From 324176e7c8b9f53b1dbf93981a00667121f61902 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 3 Oct 2022 13:20:07 +1000 Subject: drm/nouveau/fifo: program NV_PFIFO_FB_TIMEOUT on init NVGPU and RM both program this value. Fixes a bunch of random hangs running parallel piglit. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index d2b616b97f94..3c2f6ce62286 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -645,6 +645,7 @@ gf100_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) nvkm_wr32(device, 0x00221c, ~(1 << 1)); /* PCE1 */ } + nvkm_mask(device, 0x002a04, 0xbfffffff, 0xbfffffff); } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 14c604a03f70..07fd5b938184 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -960,6 +960,7 @@ gk104_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) struct nvkm_device *device = fifo->engine.subdev.device; nvkm_wr32(device, 0x000204, mask); + nvkm_mask(device, 0x002a04, 0xbfffffff, 0xbfffffff); } void -- cgit v1.2.3 From 87c860243149bd7f69ba76a2becfa480efa44974 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:28 +1000 Subject: drm/nouveau/fifo: move PBDMA init to runq - bumps pbdma timeout to value RM uses on newer HW - bumps fb timeout to max from boot default - one/both of these greatly improves stability on // piglit runs Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 3 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 21 +++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 2 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 36 ++++++++---------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 6 ---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 15 +++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 6 ---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 8 +++--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 6 ---- 15 files changed, 36 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index a6cec417012f..e51fb10a04f7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -192,6 +192,9 @@ nvkm_fifo_init(struct nvkm_engine *engine) mask |= BIT(runq->id); fifo->func->init_pbdmas(fifo, mask); + + nvkm_runq_foreach(runq, fifo) + runq->func->init(runq); } fifo->func->init(fifo); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 3c2f6ce62286..7deb88ec8a9f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -97,8 +97,19 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit) nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); } +void +gf100_runq_init(struct nvkm_runq *runq) +{ + struct nvkm_device *device = runq->fifo->engine.subdev.device; + + nvkm_mask(device, 0x04013c + (runq->id * 0x2000), 0x10000100, 0x00000000); + nvkm_wr32(device, 0x040108 + (runq->id * 0x2000), 0xffffffff); /* INTR */ + nvkm_wr32(device, 0x04010c + (runq->id * 0x2000), 0xfffffeff); /* INTREN */ +} + static const struct nvkm_runq_func gf100_runq = { + .init = gf100_runq_init, }; void @@ -653,14 +664,6 @@ gf100_fifo_init(struct nvkm_fifo *base) { struct gf100_fifo *fifo = gf100_fifo(base); struct nvkm_device *device = fifo->base.engine.subdev.device; - int i; - - /* PBDMA[n] */ - for (i = 0; i < fifo->pbdma_nr; i++) { - nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ - } nvkm_mask(device, 0x002200, 0x00000001, 0x00000001); nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); @@ -716,8 +719,6 @@ gf100_fifo_oneinit(struct nvkm_fifo *base) struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); int ret; - fifo->pbdma_nr = fifo->base.func->runq_nr(&fifo->base); - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, false, &fifo->runlist.mem[0]); if (ret) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h index b8642490eb2f..82b8467545a8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -17,8 +17,6 @@ struct gf100_fifo { u64 mask; } recover; - int pbdma_nr; - struct { struct nvkm_memory *mem[2]; int active; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 07fd5b938184..8b6bc79843c7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -164,6 +164,17 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { {} }; +void +gk104_runq_init(struct nvkm_runq *runq) +{ + struct nvkm_device *device = runq->fifo->engine.subdev.device; + + gf100_runq_init(runq); + + nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), 0xffffffff); /* HCE.INTR */ + nvkm_wr32(device, 0x04014c + (runq->id * 0x2000), 0xffffffff); /* HCE.INTREN */ +} + static u32 gk104_runq_runm(struct nvkm_runq *runq) { @@ -172,6 +183,7 @@ gk104_runq_runm(struct nvkm_runq *runq) const struct nvkm_runq_func gk104_runq = { + .init = gk104_runq_init, }; void @@ -278,10 +290,6 @@ static const struct nvkm_runl_func gk104_runl = { }; -const struct gk104_fifo_pbdma_func -gk104_fifo_pbdma = { -}; - int gk104_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) { @@ -968,26 +976,9 @@ gk104_fifo_init(struct nvkm_fifo *base) { struct gk104_fifo *fifo = gk104_fifo(base); struct nvkm_device *device = fifo->base.engine.subdev.device; - int i; - - /* PBDMA[n] */ - for (i = 0; i < fifo->pbdma_nr; i++) { - nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ - } - - /* PBDMA[n].HCE */ - for (i = 0; i < fifo->pbdma_nr; i++) { - nvkm_wr32(device, 0x040148 + (i * 0x2000), 0xffffffff); /* INTR */ - nvkm_wr32(device, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */ - } nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); - if (fifo->func->pbdma->init_timeout) - fifo->func->pbdma->init_timeout(fifo); - nvkm_wr32(device, 0x002100, 0xffffffff); nvkm_wr32(device, 0x002140, 0x7fffffff); } @@ -1054,8 +1045,6 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) struct nvkm_top_device *tdev; int ret, i, j; - fifo->pbdma_nr = fifo->func->runq_nr(&fifo->base); - /* Determine runlist configuration from topology device info. */ list_for_each_entry(tdev, &device->top->device, head) { const int engn = tdev->engine; @@ -1158,7 +1147,6 @@ gk104_fifo = { .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk104_fifo_runlist, - .pbdma = &gk104_fifo_pbdma, .nonstall = &gf100_fifo_nonstall, .runl = &gk104_runl, .runq = &gk104_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 953177b90e9b..99ae200b2f89 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -21,8 +21,6 @@ struct gk104_fifo { u32 runm; } recover; - int pbdma_nr; - struct { struct nvkm_engine *engine; int runl; @@ -74,7 +72,6 @@ int gk104_fifo_oneinit(struct nvkm_fifo *); void gk104_fifo_init(struct nvkm_fifo *base); void gk104_fifo_fini(struct nvkm_fifo *base); -extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma; extern const struct nvkm_enum gk104_fifo_fault_access[]; extern const struct nvkm_enum gk104_fifo_fault_engine[]; extern const struct nvkm_enum gk104_fifo_fault_reason[]; @@ -90,14 +87,11 @@ extern const struct gk104_fifo_runlist_func gk110_fifo_runlist; void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, struct nvkm_memory *, u32); -extern const struct gk104_fifo_pbdma_func gk208_fifo_pbdma; void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *); extern const struct nvkm_enum gm107_fifo_fault_engine[]; extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; -extern const struct gk104_fifo_pbdma_func gm200_fifo_pbdma; - extern const struct nvkm_enum gp100_fifo_fault_engine[]; extern const struct nvkm_enum gv100_fifo_fault_access[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 85705008e0f2..4143a07e3808 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -96,7 +96,6 @@ gk110_fifo = { .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, - .pbdma = &gk104_fifo_pbdma, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk104_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 5224723ce424..0b48fb1b3da4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -28,22 +28,16 @@ #include void -gk208_fifo_pbdma_init_timeout(struct gk104_fifo *fifo) +gk208_runq_init(struct nvkm_runq *runq) { - struct nvkm_device *device = fifo->base.engine.subdev.device; - int i; + gk104_runq_init(runq); - for (i = 0; i < fifo->pbdma_nr; i++) - nvkm_wr32(device, 0x04012c + (i * 0x2000), 0x0000ffff); + nvkm_wr32(runq->fifo->engine.subdev.device, 0x04012c + (runq->id * 0x2000), 0x000f4240); } -const struct gk104_fifo_pbdma_func -gk208_fifo_pbdma = { - .init_timeout = gk208_fifo_pbdma_init_timeout, -}; - const struct nvkm_runq_func gk208_runq = { + .init = gk208_runq_init, }; static int @@ -75,7 +69,6 @@ gk208_fifo = { .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .nonstall = &gf100_fifo_nonstall, - .pbdma = &gk208_fifo_pbdma, .runl = &gk110_runl, .runq = &gk208_runq, .engn = &gk104_engn, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 8ce3bb39f651..3d3db802b824 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -46,7 +46,6 @@ gk20a_fifo = { .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, - .pbdma = &gk208_fifo_pbdma, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 9a608c02c668..a85f30768b74 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -136,7 +136,6 @@ gm107_fifo = { .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, - .pbdma = &gk208_fifo_pbdma, .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 1ecfbea3680a..131e4ae61590 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -32,11 +32,6 @@ gm200_fifo_runq_nr(struct nvkm_fifo *fifo) return nvkm_rd32(fifo->engine.subdev.device, 0x002004) & 0x000000ff; } -const struct gk104_fifo_pbdma_func -gm200_fifo_pbdma = { - .init_timeout = gk208_fifo_pbdma_init_timeout, -}; - int gm200_fifo_chid_nr(struct nvkm_fifo *fifo) { @@ -65,7 +60,6 @@ gm200_fifo = { .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, - .pbdma = &gm200_fifo_pbdma, .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 1e9c5ea9cd13..b05ede6dd392 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -108,7 +108,6 @@ gp100_fifo = { .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, - .pbdma = &gm200_fifo_pbdma, .nonstall = &gf100_fifo_nonstall, .runl = &gp100_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index cc9ddc65e881..251d5e5826db 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -45,6 +45,7 @@ gv100_engn_ce = { const struct nvkm_runq_func gv100_runq = { + .init = gk208_runq_init, }; void @@ -335,7 +336,6 @@ gv100_fifo = { .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gv100_fifo_runlist, - .pbdma = &gm200_fifo_pbdma, .nonstall = &gf100_fifo_nonstall, .runl = &gv100_runl, .runq = &gv100_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 8657e5c84c64..c30d7ac07803 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -5,6 +5,7 @@ #include struct nvkm_cgrp; struct nvkm_memory; +struct nvkm_runq; struct gk104_fifo; struct gk104_fifo_chan; @@ -59,10 +60,6 @@ struct nvkm_fifo_func { struct nvkm_memory *, int entries); } *runlist; - const struct gk104_fifo_pbdma_func { - void (*init_timeout)(struct gk104_fifo *); - } *pbdma; - const struct nvkm_event_func *nonstall; const struct nvkm_runl_func *runl; @@ -118,6 +115,7 @@ int gf100_fifo_chid_ctor(struct nvkm_fifo *, int); int gf100_fifo_runq_nr(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); extern const struct nvkm_event_func gf100_fifo_nonstall; +void gf100_runq_init(struct nvkm_runq *); extern const struct nvkm_engn_func gf100_engn_sw; int gk104_fifo_chid_nr(struct nvkm_fifo *); @@ -131,6 +129,7 @@ void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); extern const struct nvkm_runq_func gk104_runq; +void gk104_runq_init(struct nvkm_runq *); extern const struct nvkm_engn_func gk104_engn; extern const struct nvkm_engn_func gk104_engn_ce; @@ -140,6 +139,7 @@ extern const struct nvkm_cgrp_func gk110_cgrp; extern const struct nvkm_chan_func gk110_chan; extern const struct nvkm_runq_func gk208_runq; +void gk208_runq_init(struct nvkm_runq *); void gm107_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); extern const struct nvkm_fifo_func_mmu_fault gm107_fifo_mmu_fault; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h index 3089d9a8e70e..e4909161c9bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h @@ -5,6 +5,7 @@ struct nvkm_runq { const struct nvkm_runq_func { + void (*init)(struct nvkm_runq *); } *func; struct nvkm_fifo *fifo; int id; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index aa933231ec60..5fcc4ebb9f5b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -94,11 +94,6 @@ tu102_fifo_fault_engine[] = { {} }; -static const struct gk104_fifo_pbdma_func -tu102_fifo_pbdma = { - .init_timeout = gk208_fifo_pbdma_init_timeout, -}; - static void tu102_fifo_recover_work(struct work_struct *w) { @@ -463,7 +458,6 @@ tu102_fifo = { .engine_id = gk104_fifo_engine_id, .recover_chan = tu102_fifo_recover_chan, .runlist = &tu102_fifo_runlist, - .pbdma = &tu102_fifo_pbdma, .nonstall = &gf100_fifo_nonstall, .runl = &tu102_runl, .runq = &gv100_runq, -- cgit v1.2.3 From 923f1ff5274ce3072df55e5e3bbaa7db457fc35d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:29 +1000 Subject: drm/nouveau/fifo: move PBDMA intr to runq - merges gf100/gk104- NV_PFIFO_INTR_0_PBDMA and NV_PPBDMA_INTR_0 code Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 65 ++++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 92 ++++++++---------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 3 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 6 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h | 3 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 13 +--- 8 files changed, 84 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 7deb88ec8a9f..177ae02e78ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -30,7 +30,6 @@ #include "changf100.h" #include -#include #include #include #include @@ -52,27 +51,28 @@ gf100_engn_sw = { }; static const struct nvkm_bitfield -gf100_fifo_pbdma_intr[] = { +gf100_runq_intr_0_names[] = { /* { 0x00008000, "" } seen with null ib push */ { 0x00200000, "ILLEGAL_MTHD" }, { 0x00800000, "EMPTY_SUBC" }, {} }; -static void -gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit) +bool +gf100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &runq->fifo->engine.subdev; struct nvkm_device *device = subdev->device; - u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000)); - u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000)); - u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000)); - u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f; + u32 mask = nvkm_rd32(device, 0x04010c + (runq->id * 0x2000)); + u32 stat = nvkm_rd32(device, 0x040108 + (runq->id * 0x2000)) & mask; + u32 addr = nvkm_rd32(device, 0x0400c0 + (runq->id * 0x2000)); + u32 data = nvkm_rd32(device, 0x0400c4 + (runq->id * 0x2000)); + u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & runq->fifo->chid->mask; u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00003ffc); - struct nvkm_fifo_chan *chan; - unsigned long flags; u32 show = stat; + struct nvkm_chan *chan; + unsigned long flags; char msg[128]; if (stat & 0x00800000) { @@ -83,18 +83,19 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit) } if (show) { - nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show); - chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); + nvkm_snprintbf(msg, sizeof(msg), runq->func->intr_0_names, show); + chan = nvkm_fifo_chan_chid(runq->fifo, chid, &flags); nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] " "subc %d mthd %04x data %08x\n", - unit, show, msg, chid, chan ? chan->inst->addr : 0, + runq->id, show, msg, chid, chan ? chan->inst->addr : 0, chan ? chan->object.client->name : "unknown", subc, mthd, data); - nvkm_fifo_chan_put(&fifo->base, flags, &chan); + nvkm_fifo_chan_put(runq->fifo, flags, &chan); } - nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008); - nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); + nvkm_wr32(device, 0x0400c0 + (runq->id * 0x2000), 0x80600008); + nvkm_wr32(device, 0x040108 + (runq->id * 0x2000), stat); + return true; } void @@ -110,6 +111,8 @@ gf100_runq_init(struct nvkm_runq *runq) static const struct nvkm_runq_func gf100_runq = { .init = gf100_runq_init, + .intr = gf100_runq_intr, + .intr_0_names = gf100_runq_intr_0_names, }; void @@ -495,6 +498,24 @@ gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) nvkm_fifo_fault(fifo, &info); } +bool +gf100_fifo_intr_pbdma(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_runq *runq; + u32 mask = nvkm_rd32(device, 0x0025a0); + bool handled = false; + + nvkm_runq_foreach_cond(runq, fifo, mask & BIT(runq->id)) { + if (runq->func->intr(runq, NULL)) + handled = true; + + nvkm_wr32(device, 0x0025a0, BIT(runq->id)); + } + + return handled; +} + static void gf100_fifo_intr_runlist(struct gf100_fifo *fifo) { @@ -599,14 +620,8 @@ gf100_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x20000000) { - u32 mask = nvkm_rd32(device, 0x0025a0); - while (mask) { - u32 unit = __ffs(mask); - gf100_fifo_intr_pbdma(gf100_fifo(fifo), unit); - nvkm_wr32(device, 0x0025a0, (1 << unit)); - mask &= ~(1 << unit); - } - stat &= ~0x20000000; + if (gf100_fifo_intr_pbdma(fifo)) + stat &= ~0x20000000; } if (stat & 0x40000000) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 8b6bc79843c7..6295389bfbea 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -37,7 +37,6 @@ #include #include #include -#include #include @@ -100,7 +99,8 @@ const struct nvkm_engn_func gk104_engn_ce = { }; -static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = { +static const struct nvkm_bitfield +gk104_runq_intr_1_names[] = { { 0x00000001, "HCE_RE_ILLEGAL_OP" }, { 0x00000002, "HCE_RE_ALIGNB" }, { 0x00000004, "HCE_PRIV" }, @@ -109,28 +109,30 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = { {} }; -void -gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit) +static bool +gk104_runq_intr_1(struct nvkm_runq *runq) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &runq->fifo->engine.subdev; struct nvkm_device *device = subdev->device; - u32 mask = nvkm_rd32(device, 0x04014c + (unit * 0x2000)); - u32 stat = nvkm_rd32(device, 0x040148 + (unit * 0x2000)) & mask; - u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff; + u32 mask = nvkm_rd32(device, 0x04014c + (runq->id * 0x2000)); + u32 stat = nvkm_rd32(device, 0x040148 + (runq->id * 0x2000)) & mask; + u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & 0xfff; char msg[128]; if (stat) { - nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_1, stat); + nvkm_snprintbf(msg, sizeof(msg), gk104_runq_intr_1_names, stat); nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n", - unit, stat, msg, chid, - nvkm_rd32(device, 0x040150 + (unit * 0x2000)), - nvkm_rd32(device, 0x040154 + (unit * 0x2000))); + runq->id, stat, msg, chid, + nvkm_rd32(device, 0x040150 + (runq->id * 0x2000)), + nvkm_rd32(device, 0x040154 + (runq->id * 0x2000))); } - nvkm_wr32(device, 0x040148 + (unit * 0x2000), stat); + nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), stat); + return true; } -static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { +const struct nvkm_bitfield +gk104_runq_intr_0_names[] = { { 0x00000001, "MEMREQ" }, { 0x00000002, "MEMACK_TIMEOUT" }, { 0x00000004, "MEMACK_EXTRA" }, @@ -164,6 +166,15 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { {} }; +bool +gk104_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null) +{ + bool intr0 = gf100_runq_intr(runq, NULL); + bool intr1 = gk104_runq_intr_1(runq); + + return intr0 || intr1; +} + void gk104_runq_init(struct nvkm_runq *runq) { @@ -184,6 +195,8 @@ gk104_runq_runm(struct nvkm_runq *runq) const struct nvkm_runq_func gk104_runq = { .init = gk104_runq_init, + .intr = gk104_runq_intr, + .intr_0_names = gk104_runq_intr_0_names, }; void @@ -806,46 +819,6 @@ gk104_fifo_intr_dropped_fault(struct nvkm_fifo *fifo) nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat); } -void -gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 mask = nvkm_rd32(device, 0x04010c + (unit * 0x2000)); - u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000)) & mask; - u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000)); - u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000)); - u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff; - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00003ffc); - u32 show = stat; - struct nvkm_fifo_chan *chan; - unsigned long flags; - char msg[128]; - - if (stat & 0x00800000) { - if (device->sw) { - if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data)) - show &= ~0x00800000; - } - } - - nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008); - - if (show) { - nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_0, show); - chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); - nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] " - "subc %d mthd %04x data %08x\n", - unit, show, msg, chid, chan ? chan->inst->addr : 0, - chan ? chan->object.client->name : "unknown", - subc, mthd, data); - nvkm_fifo_chan_put(&fifo->base, flags, &chan); - } - - nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); -} - void gk104_fifo_intr_runlist(struct gk104_fifo *fifo) { @@ -922,15 +895,8 @@ gk104_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x20000000) { - u32 mask = nvkm_rd32(device, 0x0025a0); - while (mask) { - u32 unit = __ffs(mask); - gk104_fifo_intr_pbdma_0(gk104_fifo(fifo), unit); - gk104_fifo_intr_pbdma_1(gk104_fifo(fifo), unit); - nvkm_wr32(device, 0x0025a0, (1 << unit)); - mask &= ~(1 << unit); - } - stat &= ~0x20000000; + if (gf100_fifo_intr_pbdma(fifo)) + stat &= ~0x20000000; } if (stat & 0x40000000) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 99ae200b2f89..f7e6c26a2a45 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -5,7 +5,6 @@ #include "priv.h" struct nvkm_fifo_cgrp; -#include #include #define gk104_fifo_func nvkm_fifo_func @@ -64,8 +63,6 @@ void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_update(struct gk104_fifo *, int runl); void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, struct gk104_fifo_engine_status *status); -void gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit); -void gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit); void gk104_fifo_intr_runlist(struct gk104_fifo *fifo); void *gk104_fifo_dtor(struct nvkm_fifo *base); int gk104_fifo_oneinit(struct nvkm_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 0b48fb1b3da4..87601c35581c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -38,6 +38,8 @@ gk208_runq_init(struct nvkm_runq *runq) const struct nvkm_runq_func gk208_runq = { .init = gk208_runq_init, + .intr = gk104_runq_intr, + .intr_0_names = gk104_runq_intr_0_names, }; static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 251d5e5826db..dc1586e2ab72 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -46,6 +46,8 @@ gv100_engn_ce = { const struct nvkm_runq_func gv100_runq = { .init = gk208_runq_init, + .intr = gk104_runq_intr, + .intr_0_names = gk104_runq_intr_0_names, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index c30d7ac07803..00f23c39978e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -3,8 +3,10 @@ #define __NVKM_FIFO_PRIV_H__ #define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine) #include +#include struct nvkm_cgrp; struct nvkm_memory; +struct nvkm_runl; struct nvkm_runq; struct gk104_fifo; struct gk104_fifo_chan; @@ -113,9 +115,11 @@ extern const struct nvkm_chan_func g84_chan; int gf100_fifo_chid_ctor(struct nvkm_fifo *, int); int gf100_fifo_runq_nr(struct nvkm_fifo *); +bool gf100_fifo_intr_pbdma(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); extern const struct nvkm_event_func gf100_fifo_nonstall; void gf100_runq_init(struct nvkm_runq *); +bool gf100_runq_intr(struct nvkm_runq *, struct nvkm_runl *); extern const struct nvkm_engn_func gf100_engn_sw; int gk104_fifo_chid_nr(struct nvkm_fifo *); @@ -130,6 +134,8 @@ void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); extern const struct nvkm_runq_func gk104_runq; void gk104_runq_init(struct nvkm_runq *); +bool gk104_runq_intr(struct nvkm_runq *, struct nvkm_runl *); +extern const struct nvkm_bitfield gk104_runq_intr_0_names[]; extern const struct nvkm_engn_func gk104_engn; extern const struct nvkm_engn_func gk104_engn_ce; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h index e4909161c9bc..f939d3500cb6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h @@ -2,10 +2,13 @@ #ifndef __NVKM_RUNQ_H__ #define __NVKM_RUNQ_H__ #include +struct nvkm_runl; struct nvkm_runq { const struct nvkm_runq_func { void (*init)(struct nvkm_runq *); + bool (*intr)(struct nvkm_runq *, struct nvkm_runl *); + const struct nvkm_bitfield *intr_0_names; } *func; struct nvkm_fifo *fifo; int id; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 5fcc4ebb9f5b..2d14795b9842 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -395,17 +395,8 @@ tu102_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x20000000) { - u32 mask = nvkm_rd32(device, 0x0025a0); - - while (mask) { - u32 unit = __ffs(mask); - - gk104_fifo_intr_pbdma_0(gk104_fifo(fifo), unit); - gk104_fifo_intr_pbdma_1(gk104_fifo(fifo), unit); - nvkm_wr32(device, 0x0025a0, (1 << unit)); - mask &= ~(1 << unit); - } - stat &= ~0x20000000; + if (gf100_fifo_intr_pbdma(fifo)) + stat &= ~0x20000000; } if (stat & 0x40000000) { -- cgit v1.2.3 From e43c872c03a9ad56f5cbc52149b4454601aa6904 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:29 +1000 Subject: drm/nouveau/fifo: merge mmu fault handlers together After updating GF100 implementation from the GK104/TU102 ones, and using the new runlist/engine topology info, all three handlers become (almost) identical. - there's a temporary kludge to call through to the HW-specific recovery - engine fault mapping info determined at load time, not on every fault Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 110 ++++++++++++------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 137 ++++------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 14 --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 5 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 5 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 5 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 32 +++--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 5 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 40 +++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 22 ++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 18 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 23 +++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 100 ++--------------- 14 files changed, 183 insertions(+), 335 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 177ae02e78ee..7fc4c37b407f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -295,7 +295,7 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, } static const struct nvkm_enum -gf100_fifo_fault_engine[] = { +gf100_fifo_mmu_fault_engine[] = { { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR }, { 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, @@ -312,7 +312,7 @@ gf100_fifo_fault_engine[] = { }; static const struct nvkm_enum -gf100_fifo_fault_reason[] = { +gf100_fifo_mmu_fault_reason[] = { { 0x00, "PT_NOT_PRESENT" }, { 0x01, "PT_TOO_SHORT" }, { 0x02, "PAGE_NOT_PRESENT" }, @@ -326,7 +326,7 @@ gf100_fifo_fault_reason[] = { }; static const struct nvkm_enum -gf100_fifo_fault_hubclient[] = { +gf100_fifo_mmu_fault_hubclient[] = { { 0x01, "PCOPY0" }, { 0x02, "PCOPY1" }, { 0x04, "DISPATCH" }, @@ -345,7 +345,7 @@ gf100_fifo_fault_hubclient[] = { }; static const struct nvkm_enum -gf100_fifo_fault_gpcclient[] = { +gf100_fifo_mmu_fault_gpcclient[] = { { 0x01, "TEX" }, { 0x0c, "ESETUP" }, { 0x0e, "CTXCTL" }, @@ -353,29 +353,48 @@ gf100_fifo_fault_gpcclient[] = { {} }; -static void -gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) +const struct nvkm_enum +gf100_fifo_mmu_fault_access[] = { + { 0x00, "READ" }, + { 0x01, "WRITE" }, + {} +}; + +void +gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *info) { - struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; - const struct nvkm_enum *er, *eu, *ec; + const struct nvkm_enum *er, *ee, *ec, *ea; struct nvkm_engine *engine = NULL; struct nvkm_fifo_chan *chan; + struct nvkm_runl *runl; + struct nvkm_engn *engn; unsigned long flags; - char gpcid[8] = ""; + char ct[8] = "HUB/"; - er = nvkm_enum_find(gf100_fifo_fault_reason, info->reason); - eu = nvkm_enum_find(gf100_fifo_fault_engine, info->engine); + /* Lookup engine by MMU fault ID. */ + nvkm_runl_foreach(runl, fifo) { + engn = nvkm_runl_find_engn(engn, runl, engn->fault == info->engine); + if (engn) { + engine = engn->engine; + break; + } + } + + er = nvkm_enum_find(fifo->func->mmu_fault->reason, info->reason); + ee = nvkm_enum_find(fifo->func->mmu_fault->engine, info->engine); if (info->hub) { - ec = nvkm_enum_find(gf100_fifo_fault_hubclient, info->client); + ec = nvkm_enum_find(fifo->func->mmu_fault->hubclient, info->client); } else { - ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, info->client); - snprintf(gpcid, sizeof(gpcid), "GPC%d/", info->gpc); + ec = nvkm_enum_find(fifo->func->mmu_fault->gpcclient, info->client); + snprintf(ct, sizeof(ct), "GPC%d/", info->gpc); } + ea = nvkm_enum_find(fifo->func->mmu_fault->access, info->access); - if (eu && eu->data2) { - switch (eu->data2) { + /* Handle BAR faults. */ + if (ee && ee->data2) { + switch (ee->data2) { case NVKM_SUBDEV_BAR: nvkm_bar_bar1_reset(device); break; @@ -386,30 +405,39 @@ gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); break; default: - engine = nvkm_device_engine(device, eu->data2, eu->inst); break; } } - chan = nvkm_fifo_chan_inst(&fifo->base, info->inst, &flags); + chan = nvkm_fifo_chan_inst(fifo, info->inst, &flags); nvkm_error(subdev, - "%s fault at %010llx engine %02x [%s] client %02x [%s%s] " - "reason %02x [%s] on channel %d [%010llx %s]\n", - info->access ? "write" : "read", info->addr, - info->engine, eu ? eu->name : "", - info->client, gpcid, ec ? ec->name : "", - info->reason, er ? er->name : "", chan ? chan->chid : -1, - info->inst, chan ? chan->object.client->name : "unknown"); - + "fault %02x [%s] at %016llx engine %02x [%s] client %02x " + "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n", + info->access, ea ? ea->name : "", info->addr, + info->engine, ee ? ee->name : engine ? engine->subdev.name : "", + info->client, ct, ec ? ec->name : "", + info->reason, er ? er->name : "", + chan ? chan->id : -1, info->inst, chan ? chan->name : "unknown"); + + /* Handle host/engine faults. */ + if (fifo->func->recover_chan && chan) + fifo->func->recover_chan(fifo, chan->id); + else if (engine && chan) - gf100_fifo_recover(fifo, engine, (void *)chan); - nvkm_fifo_chan_put(&fifo->base, flags, &chan); + gf100_fifo_recover(gf100_fifo(fifo), engine, (void *)chan); + + nvkm_fifo_chan_put(fifo, flags, &chan); } static const struct nvkm_fifo_func_mmu_fault gf100_fifo_mmu_fault = { - .recover = gf100_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gf100_fifo_mmu_fault_access, + .engine = gf100_fifo_mmu_fault_engine, + .reason = gf100_fifo_mmu_fault_reason, + .hubclient = gf100_fifo_mmu_fault_hubclient, + .gpcclient = gf100_fifo_mmu_fault_gpcclient, }; static const struct nvkm_enum @@ -498,6 +526,19 @@ gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) nvkm_fifo_fault(fifo, &info); } +void +gf100_fifo_intr_mmu_fault(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + unsigned long mask = nvkm_rd32(device, 0x00259c); + int unit; + + for_each_set_bit(unit, &mask, 32) { + fifo->func->intr_mmu_fault_unit(fifo, unit); + nvkm_wr32(device, 0x00259c, BIT(unit)); + } +} + bool gf100_fifo_intr_pbdma(struct nvkm_fifo *fifo) { @@ -609,13 +650,7 @@ gf100_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x10000000) { - u32 mask = nvkm_rd32(device, 0x00259c); - while (mask) { - u32 unit = __ffs(mask); - gf100_fifo_intr_mmu_fault_unit(fifo, unit); - nvkm_wr32(device, 0x00259c, (1 << unit)); - mask &= ~(1 << unit); - } + gf100_fifo_intr_mmu_fault(fifo); stat &= ~0x10000000; } @@ -783,6 +818,7 @@ gf100_fifo = { .init_pbdmas = gf100_fifo_init_pbdmas, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, + .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gf100_fifo_mmu_fault, .engine_id = gf100_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 6295389bfbea..de8e3a17d79e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -30,10 +30,8 @@ #include "cgrp.h" #include "changk104.h" -#include #include #include -#include #include #include #include @@ -474,7 +472,7 @@ gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn) if (!status.faulted && engine) { mmui = nvkm_top_fault_id(device, engine->subdev.type, engine->subdev.inst); if (mmui < 0) { - const struct nvkm_enum *en = fifo->func->fault.engine; + const struct nvkm_enum *en = fifo->func->mmu_fault->engine; for (; en && en->name; en++) { if (en->data2 == engine->subdev.type && en->inst == engine->subdev.inst) { @@ -512,15 +510,8 @@ gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn) schedule_work(&fifo->recover.work); } -const struct nvkm_enum -gk104_fifo_fault_access[] = { - { 0x0, "READ" }, - { 0x1, "WRITE" }, - {} -}; - -const struct nvkm_enum -gk104_fifo_fault_engine[] = { +static const struct nvkm_enum +gk104_fifo_mmu_fault_engine[] = { { 0x00, "GR", NULL, NVKM_ENGINE_GR }, { 0x01, "DISPLAY" }, { 0x02, "CAPTURE" }, @@ -528,14 +519,14 @@ gk104_fifo_fault_engine[] = { { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, { 0x06, "SCHED" }, - { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO }, - { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO }, - { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO }, - { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO }, - { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO }, - { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO }, - { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO }, - { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO }, + { 0x07, "HOST0" }, + { 0x08, "HOST1" }, + { 0x09, "HOST2" }, + { 0x0a, "HOST3" }, + { 0x0b, "HOST4" }, + { 0x0c, "HOST5" }, + { 0x0d, "HOST6" }, + { 0x0e, "HOST7" }, { 0x0f, "HOSTSR" }, { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD }, { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP }, @@ -551,7 +542,7 @@ gk104_fifo_fault_engine[] = { }; const struct nvkm_enum -gk104_fifo_fault_reason[] = { +gk104_fifo_mmu_fault_reason[] = { { 0x00, "PDE" }, { 0x01, "PDE_SIZE" }, { 0x02, "PTE" }, @@ -572,7 +563,7 @@ gk104_fifo_fault_reason[] = { }; const struct nvkm_enum -gk104_fifo_fault_hubclient[] = { +gk104_fifo_mmu_fault_hubclient[] = { { 0x00, "VIP" }, { 0x01, "CE0" }, { 0x02, "CE1" }, @@ -609,7 +600,7 @@ gk104_fifo_fault_hubclient[] = { }; const struct nvkm_enum -gk104_fifo_fault_gpcclient[] = { +gk104_fifo_mmu_fault_gpcclient[] = { { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" }, { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" }, { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" }, @@ -634,89 +625,14 @@ gk104_fifo_fault_gpcclient[] = { {} }; -void -gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const struct nvkm_enum *er, *ee, *ec, *ea; - struct nvkm_engine *engine = NULL; - struct nvkm_fifo_chan *chan; - unsigned long flags; - const char *en = ""; - char ct[8] = "HUB/"; - - er = nvkm_enum_find(fifo->func->fault.reason, info->reason); - ee = nvkm_enum_find(fifo->func->fault.engine, info->engine); - if (info->hub) { - ec = nvkm_enum_find(fifo->func->fault.hubclient, info->client); - } else { - ec = nvkm_enum_find(fifo->func->fault.gpcclient, info->client); - snprintf(ct, sizeof(ct), "GPC%d/", info->gpc); - } - ea = nvkm_enum_find(fifo->func->fault.access, info->access); - - if (ee && ee->data2) { - switch (ee->data2) { - case NVKM_SUBDEV_BAR: - nvkm_bar_bar1_reset(device); - break; - case NVKM_SUBDEV_INSTMEM: - nvkm_bar_bar2_reset(device); - break; - case NVKM_ENGINE_IFB: - nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); - break; - default: - engine = nvkm_device_engine(device, ee->data2, 0); - break; - } - } - - if (ee == NULL) { - struct nvkm_subdev *subdev = nvkm_top_fault(device, info->engine); - if (subdev) { - if (subdev->func == &nvkm_engine) - engine = container_of(subdev, typeof(*engine), subdev); - en = engine->subdev.name; - } - } else { - en = ee->name; - } - - spin_lock_irqsave(&fifo->base.lock, flags); - chan = nvkm_fifo_chan_inst_locked(&fifo->base, info->inst); - - nvkm_error(subdev, - "fault %02x [%s] at %016llx engine %02x [%s] client %02x " - "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n", - info->access, ea ? ea->name : "", info->addr, - info->engine, ee ? ee->name : en, - info->client, ct, ec ? ec->name : "", - info->reason, er ? er->name : "", chan ? chan->chid : -1, - info->inst, chan ? chan->object.client->name : "unknown"); - - /* Kill the channel that caused the fault. */ - if (chan) - gk104_fifo_recover_chan(&fifo->base, chan->chid); - - /* Channel recovery will probably have already done this for the - * correct engine(s), but just in case we can't find the channel - * information... - */ - if (engine) { - int engn = fifo->base.func->engine_id(&fifo->base, engine); - if (engn >= 0 && engn != GK104_FIFO_ENGN_SW) - gk104_fifo_recover_engn(fifo, engn); - } - - spin_unlock_irqrestore(&fifo->base.lock, flags); -} - const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault = { - .recover = gk104_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gf100_fifo_mmu_fault_access, + .engine = gk104_fifo_mmu_fault_engine, + .reason = gk104_fifo_mmu_fault_reason, + .hubclient = gk104_fifo_mmu_fault_hubclient, + .gpcclient = gk104_fifo_mmu_fault_gpcclient, }; static const struct nvkm_enum @@ -884,13 +800,7 @@ gk104_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x10000000) { - u32 mask = nvkm_rd32(device, 0x00259c); - while (mask) { - u32 unit = __ffs(mask); - fifo->func->intr_mmu_fault_unit(fifo, unit); - nvkm_wr32(device, 0x00259c, (1 << unit)); - mask &= ~(1 << unit); - } + gf100_fifo_intr_mmu_fault(fifo); stat &= ~0x10000000; } @@ -1105,11 +1015,6 @@ gk104_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gk104_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gk104_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk104_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index f7e6c26a2a45..13f1efcc9e24 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -69,11 +69,6 @@ int gk104_fifo_oneinit(struct nvkm_fifo *); void gk104_fifo_init(struct nvkm_fifo *base); void gk104_fifo_fini(struct nvkm_fifo *base); -extern const struct nvkm_enum gk104_fifo_fault_access[]; -extern const struct nvkm_enum gk104_fifo_fault_engine[]; -extern const struct nvkm_enum gk104_fifo_fault_reason[]; -extern const struct nvkm_enum gk104_fifo_fault_hubclient[]; -extern const struct nvkm_enum gk104_fifo_fault_gpcclient[]; extern const struct gk104_fifo_runlist_func gk104_fifo_runlist; void gk104_fifo_runlist_chan(struct gk104_fifo_chan *, struct nvkm_memory *, u32); @@ -84,17 +79,8 @@ extern const struct gk104_fifo_runlist_func gk110_fifo_runlist; void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, struct nvkm_memory *, u32); -void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *); - -extern const struct nvkm_enum gm107_fifo_fault_engine[]; extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; -extern const struct nvkm_enum gp100_fifo_fault_engine[]; - -extern const struct nvkm_enum gv100_fifo_fault_access[]; -extern const struct nvkm_enum gv100_fifo_fault_reason[]; -extern const struct nvkm_enum gv100_fifo_fault_hubclient[]; -extern const struct nvkm_enum gv100_fifo_fault_gpcclient[]; void gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, struct nvkm_memory *, u32); void gv100_fifo_runlist_chan(struct gk104_fifo_chan *, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 4143a07e3808..5271f5504854 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -88,11 +88,6 @@ gk110_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gk104_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gk104_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 87601c35581c..ab813aa6d1a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -62,11 +62,6 @@ gk208_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gk104_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gk104_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 3d3db802b824..0d633b805331 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -38,11 +38,6 @@ gk20a_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .mmu_fault = &gk104_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gk104_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index a85f30768b74..ecf4e6d94866 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -56,22 +56,22 @@ const struct nvkm_runl_func gm107_runl = { }; -const struct nvkm_enum -gm107_fifo_fault_engine[] = { +static const struct nvkm_enum +gm107_fifo_mmu_fault_engine[] = { { 0x01, "DISPLAY" }, { 0x02, "CAPTURE" }, { 0x03, "IFB", NULL, NVKM_ENGINE_IFB }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, { 0x06, "SCHED" }, - { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO }, - { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO }, - { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO }, - { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO }, - { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO }, - { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO }, - { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO }, - { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO }, + { 0x07, "HOST0" }, + { 0x08, "HOST1" }, + { 0x09, "HOST2" }, + { 0x0a, "HOST3" }, + { 0x0b, "HOST4" }, + { 0x0c, "HOST5" }, + { 0x0d, "HOST6" }, + { 0x0e, "HOST7" }, { 0x0f, "HOSTSR" }, { 0x13, "PERF" }, { 0x17, "PMU" }, @@ -81,7 +81,12 @@ gm107_fifo_fault_engine[] = { const struct nvkm_fifo_func_mmu_fault gm107_fifo_mmu_fault = { - .recover = gk104_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gf100_fifo_mmu_fault_access, + .engine = gm107_fifo_mmu_fault_engine, + .reason = gk104_fifo_mmu_fault_reason, + .hubclient = gk104_fifo_mmu_fault_hubclient, + .gpcclient = gk104_fifo_mmu_fault_gpcclient, }; void @@ -128,11 +133,6 @@ gm107_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, .mmu_fault = &gm107_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gm107_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 131e4ae61590..6fa96a4c3e23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -52,11 +52,6 @@ gm200_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, .mmu_fault = &gm107_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gm107_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index b05ede6dd392..0ca14b08ca3a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -33,23 +33,23 @@ static const struct nvkm_runl_func gp100_runl = { }; -const struct nvkm_enum -gp100_fifo_fault_engine[] = { +static const struct nvkm_enum +gp100_fifo_mmu_fault_engine[] = { { 0x01, "DISPLAY" }, { 0x03, "IFB", NULL, NVKM_ENGINE_IFB }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, - { 0x06, "HOST0", NULL, NVKM_ENGINE_FIFO }, - { 0x07, "HOST1", NULL, NVKM_ENGINE_FIFO }, - { 0x08, "HOST2", NULL, NVKM_ENGINE_FIFO }, - { 0x09, "HOST3", NULL, NVKM_ENGINE_FIFO }, - { 0x0a, "HOST4", NULL, NVKM_ENGINE_FIFO }, - { 0x0b, "HOST5", NULL, NVKM_ENGINE_FIFO }, - { 0x0c, "HOST6", NULL, NVKM_ENGINE_FIFO }, - { 0x0d, "HOST7", NULL, NVKM_ENGINE_FIFO }, - { 0x0e, "HOST8", NULL, NVKM_ENGINE_FIFO }, - { 0x0f, "HOST9", NULL, NVKM_ENGINE_FIFO }, - { 0x10, "HOST10", NULL, NVKM_ENGINE_FIFO }, + { 0x06, "HOST0" }, + { 0x07, "HOST1" }, + { 0x08, "HOST2" }, + { 0x09, "HOST3" }, + { 0x0a, "HOST4" }, + { 0x0b, "HOST5" }, + { 0x0c, "HOST6" }, + { 0x0d, "HOST7" }, + { 0x0e, "HOST8" }, + { 0x0f, "HOST9" }, + { 0x10, "HOST10" }, { 0x13, "PERF" }, { 0x17, "PMU" }, { 0x18, "PTP" }, @@ -59,10 +59,15 @@ gp100_fifo_fault_engine[] = { static const struct nvkm_fifo_func_mmu_fault gp100_fifo_mmu_fault = { - .recover = gk104_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gf100_fifo_mmu_fault_access, + .engine = gp100_fifo_mmu_fault_engine, + .reason = gk104_fifo_mmu_fault_reason, + .hubclient = gk104_fifo_mmu_fault_hubclient, + .gpcclient = gk104_fifo_mmu_fault_gpcclient, }; -void +static void gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) { struct nvkm_device *device = fifo->engine.subdev.device; @@ -100,11 +105,6 @@ gp100_fifo = { .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gp100_fifo_intr_mmu_fault_unit, .mmu_fault = &gp100_fifo_mmu_fault, - .fault.access = gk104_fifo_fault_access, - .fault.engine = gp100_fifo_fault_engine, - .fault.reason = gk104_fifo_fault_reason, - .fault.hubclient = gk104_fifo_fault_hubclient, - .fault.gpcclient = gk104_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index dc1586e2ab72..49d7c9e7fb8a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -87,7 +87,7 @@ gv100_runl = { }; const struct nvkm_enum -gv100_fifo_fault_gpcclient[] = { +gv100_fifo_mmu_fault_gpcclient[] = { { 0x00, "T1_0" }, { 0x01, "T1_1" }, { 0x02, "T1_2" }, @@ -189,7 +189,7 @@ gv100_fifo_fault_gpcclient[] = { }; const struct nvkm_enum -gv100_fifo_fault_hubclient[] = { +gv100_fifo_mmu_fault_hubclient[] = { { 0x00, "VIP" }, { 0x01, "CE0" }, { 0x02, "CE1" }, @@ -251,7 +251,7 @@ gv100_fifo_fault_hubclient[] = { }; const struct nvkm_enum -gv100_fifo_fault_reason[] = { +gv100_fifo_mmu_fault_reason[] = { { 0x00, "PDE" }, { 0x01, "PDE_SIZE" }, { 0x02, "PTE" }, @@ -272,7 +272,7 @@ gv100_fifo_fault_reason[] = { }; static const struct nvkm_enum -gv100_fifo_fault_engine[] = { +gv100_fifo_mmu_fault_engine[] = { { 0x01, "DISPLAY" }, { 0x03, "PTP" }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, @@ -299,7 +299,7 @@ gv100_fifo_fault_engine[] = { }; const struct nvkm_enum -gv100_fifo_fault_access[] = { +gv100_fifo_mmu_fault_access[] = { { 0x0, "VIRT_READ" }, { 0x1, "VIRT_WRITE" }, { 0x2, "VIRT_ATOMIC" }, @@ -314,7 +314,12 @@ gv100_fifo_fault_access[] = { static const struct nvkm_fifo_func_mmu_fault gv100_fifo_mmu_fault = { - .recover = gk104_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gv100_fifo_mmu_fault_access, + .engine = gv100_fifo_mmu_fault_engine, + .reason = gv100_fifo_mmu_fault_reason, + .hubclient = gv100_fifo_mmu_fault_hubclient, + .gpcclient = gv100_fifo_mmu_fault_gpcclient, }; static const struct nvkm_fifo_func @@ -330,11 +335,6 @@ gv100_fifo = { .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .mmu_fault = &gv100_fifo_mmu_fault, - .fault.access = gv100_fifo_fault_access, - .fault.engine = gv100_fifo_fault_engine, - .fault.reason = gv100_fifo_fault_reason, - .fault.hubclient = gv100_fifo_fault_hubclient, - .fault.gpcclient = gv100_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = gk104_fifo_recover_chan, .runlist = &gv100_fifo_runlist, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 00f23c39978e..19c6e706f33e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -37,15 +37,12 @@ struct nvkm_fifo_func { const struct nvkm_fifo_func_mmu_fault { void (*recover)(struct nvkm_fifo *, struct nvkm_fault_data *); - } *mmu_fault; - - struct { const struct nvkm_enum *access; const struct nvkm_enum *engine; const struct nvkm_enum *reason; const struct nvkm_enum *hubclient; const struct nvkm_enum *gpcclient; - } fault; + } *mmu_fault; int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *); void (*pause)(struct nvkm_fifo *, unsigned long *); @@ -116,7 +113,10 @@ extern const struct nvkm_chan_func g84_chan; int gf100_fifo_chid_ctor(struct nvkm_fifo *, int); int gf100_fifo_runq_nr(struct nvkm_fifo *); bool gf100_fifo_intr_pbdma(struct nvkm_fifo *); +void gf100_fifo_intr_mmu_fault(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); +void gf100_fifo_mmu_fault_recover(struct nvkm_fifo *, struct nvkm_fault_data *); +extern const struct nvkm_enum gf100_fifo_mmu_fault_access[]; extern const struct nvkm_event_func gf100_fifo_nonstall; void gf100_runq_init(struct nvkm_runq *); bool gf100_runq_intr(struct nvkm_runq *, struct nvkm_runl *); @@ -129,7 +129,9 @@ irqreturn_t gk104_fifo_intr(struct nvkm_inth *); void gk104_fifo_intr_chsw(struct nvkm_fifo *); void gk104_fifo_intr_bind(struct nvkm_fifo *); extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; -void gk104_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); +extern const struct nvkm_enum gk104_fifo_mmu_fault_reason[]; +extern const struct nvkm_enum gk104_fifo_mmu_fault_hubclient[]; +extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[]; void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); extern const struct nvkm_runq_func gk104_runq; @@ -155,8 +157,10 @@ extern const struct nvkm_chan_func gm107_chan; int gm200_fifo_chid_nr(struct nvkm_fifo *); int gm200_fifo_runq_nr(struct nvkm_fifo *); -void gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); - +extern const struct nvkm_enum gv100_fifo_mmu_fault_access[]; +extern const struct nvkm_enum gv100_fifo_mmu_fault_reason[]; +extern const struct nvkm_enum gv100_fifo_mmu_fault_hubclient[]; +extern const struct nvkm_enum gv100_fifo_mmu_fault_gpcclient[]; extern const struct nvkm_runq_func gv100_runq; extern const struct nvkm_engn_func gv100_engn; extern const struct nvkm_engn_func gv100_engn_ce; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 1a15b0a9ab7c..0b75565bfbc1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -24,6 +24,8 @@ #include "chid.h" #include "priv.h" +#include + void nvkm_runl_del(struct nvkm_runl *runl) { @@ -46,7 +48,8 @@ struct nvkm_engn * nvkm_runl_add(struct nvkm_runl *runl, int engi, const struct nvkm_engn_func *func, enum nvkm_subdev_type type, int inst) { - struct nvkm_device *device = runl->fifo->engine.subdev.device; + struct nvkm_fifo *fifo = runl->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_engine *engine; struct nvkm_engn *engn; @@ -63,7 +66,25 @@ nvkm_runl_add(struct nvkm_runl *runl, int engi, const struct nvkm_engn_func *fun engn->runl = runl; engn->id = engi; engn->engine = engine; + engn->fault = -1; list_add_tail(&engn->head, &runl->engns); + + /* Lookup MMU engine ID for fault handling. */ + if (device->top) + engn->fault = nvkm_top_fault_id(device, engine->subdev.type, engine->subdev.inst); + + if (engn->fault < 0 && fifo->func->mmu_fault) { + const struct nvkm_enum *map = fifo->func->mmu_fault->engine; + + while (map->name) { + if (map->data2 == engine->subdev.type && map->inst == engine->subdev.inst) { + engn->fault = map->value; + break; + } + map++; + } + } + return engn; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index cb0de870a118..b223da2d4399 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -13,6 +13,8 @@ struct nvkm_engn { struct nvkm_engine *engine; + int fault; + struct list_head head; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 2d14795b9842..47de0b97534a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -26,12 +26,8 @@ #include "cgrp.h" #include "changk104.h" -#include #include -#include -#include #include -#include #include @@ -67,7 +63,7 @@ tu102_runl = { }; static const struct nvkm_enum -tu102_fifo_fault_engine[] = { +tu102_fifo_mmu_fault_engine[] = { { 0x01, "DISPLAY" }, { 0x03, "PTP" }, { 0x06, "PWR_PMU" }, @@ -247,91 +243,14 @@ tu102_fifo_recover_engn(struct gk104_fifo *fifo, int engn) schedule_work(&fifo->recover.work); } -static void -tu102_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const struct nvkm_enum *er, *ee, *ec, *ea; - struct nvkm_engine *engine = NULL; - struct nvkm_fifo_chan *chan; - unsigned long flags; - const char *en = ""; - char ct[8] = "HUB/"; - int engn; - - er = nvkm_enum_find(fifo->func->fault.reason, info->reason); - ee = nvkm_enum_find(fifo->func->fault.engine, info->engine); - if (info->hub) { - ec = nvkm_enum_find(fifo->func->fault.hubclient, info->client); - } else { - ec = nvkm_enum_find(fifo->func->fault.gpcclient, info->client); - snprintf(ct, sizeof(ct), "GPC%d/", info->gpc); - } - ea = nvkm_enum_find(fifo->func->fault.access, info->access); - - if (ee && ee->data2) { - switch (ee->data2) { - case NVKM_SUBDEV_BAR: - nvkm_bar_bar1_reset(device); - break; - case NVKM_SUBDEV_INSTMEM: - nvkm_bar_bar2_reset(device); - break; - case NVKM_ENGINE_IFB: - nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); - break; - default: - engine = nvkm_device_engine(device, ee->data2, 0); - break; - } - } - - if (ee == NULL) { - struct nvkm_subdev *subdev = nvkm_top_fault(device, info->engine); - if (subdev) { - if (subdev->func == &nvkm_engine) - engine = container_of(subdev, typeof(*engine), subdev); - en = engine->subdev.name; - } - } else { - en = ee->name; - } - - spin_lock_irqsave(&fifo->base.lock, flags); - chan = nvkm_fifo_chan_inst_locked(&fifo->base, info->inst); - - nvkm_error(subdev, - "fault %02x [%s] at %016llx engine %02x [%s] client %02x " - "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n", - info->access, ea ? ea->name : "", info->addr, - info->engine, ee ? ee->name : en, - info->client, ct, ec ? ec->name : "", - info->reason, er ? er->name : "", chan ? chan->chid : -1, - info->inst, chan ? chan->object.client->name : "unknown"); - - /* Kill the channel that caused the fault. */ - if (chan) - tu102_fifo_recover_chan(&fifo->base, chan->chid); - - /* Channel recovery will probably have already done this for the - * correct engine(s), but just in case we can't find the channel - * information... - */ - for (engn = 0; engn < fifo->engine_nr && engine; engn++) { - if (fifo->engine[engn].engine == engine) { - tu102_fifo_recover_engn(fifo, engn); - break; - } - } - - spin_unlock_irqrestore(&fifo->base.lock, flags); -} - const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault = { - .recover = tu102_fifo_fault, + .recover = gf100_fifo_mmu_fault_recover, + .access = gv100_fifo_mmu_fault_access, + .engine = tu102_fifo_mmu_fault_engine, + .reason = gv100_fifo_mmu_fault_reason, + .hubclient = gv100_fifo_mmu_fault_hubclient, + .gpcclient = gv100_fifo_mmu_fault_gpcclient, }; static void @@ -441,11 +360,6 @@ tu102_fifo = { .fini = gk104_fifo_fini, .intr = tu102_fifo_intr, .mmu_fault = &tu102_fifo_mmu_fault, - .fault.access = gv100_fifo_fault_access, - .fault.engine = tu102_fifo_fault_engine, - .fault.reason = gv100_fifo_fault_reason, - .fault.hubclient = gv100_fifo_fault_hubclient, - .fault.gpcclient = gv100_fifo_fault_gpcclient, .engine_id = gk104_fifo_engine_id, .recover_chan = tu102_fifo_recover_chan, .runlist = &tu102_fifo_runlist, -- cgit v1.2.3 From c358f53871605a1a8d7ed6e544a05ea00e9c80cb Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:29 +1000 Subject: drm/nouveau/fifo: add new channel lookup interfaces - supports per-runlist CHIDs - channel group lock held across reference, rather than global lock v2: - remove unnecessary parenthesis Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 2 +- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 11 ++--- drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c | 6 +-- drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c | 11 ++--- drivers/gpu/drm/nouveau/nvkm/engine/falcon.c | 6 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 57 ---------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 50 +++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 10 ++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 17 +++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 3 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 47 ++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 3 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 10 ++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c | 10 ++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c | 10 ++-- drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c | 6 +-- drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c | 11 ++--- 28 files changed, 166 insertions(+), 132 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index b593407b9e36..176f0921d82f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -66,7 +66,7 @@ struct nvkm_falcon_func { u32 size; } data; void (*init)(struct nvkm_falcon *); - void (*intr)(struct nvkm_falcon *, struct nvkm_fifo_chan *); + void (*intr)(struct nvkm_falcon *, struct nvkm_chan *); u32 debug; u32 fbif; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index d3412c916290..a47667d00f3a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -34,6 +34,10 @@ struct nvkm_chan { struct nvkm_fifo_engn engn[NVKM_FIFO_ENGN_NR]; }; +struct nvkm_chan *nvkm_chan_get_chid(struct nvkm_engine *, int id, unsigned long *irqflags); +struct nvkm_chan *nvkm_chan_get_inst(struct nvkm_engine *, u64 inst, unsigned long *irqflags); +void nvkm_chan_put(struct nvkm_chan **, unsigned long irqflags); + struct nvkm_fifo { const struct nvkm_fifo_func *func; struct nvkm_engine engine; @@ -62,13 +66,6 @@ void nvkm_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); void nvkm_fifo_pause(struct nvkm_fifo *, unsigned long *); void nvkm_fifo_start(struct nvkm_fifo *, unsigned long *); -void nvkm_fifo_chan_put(struct nvkm_fifo *, unsigned long flags, - struct nvkm_fifo_chan **); -struct nvkm_fifo_chan * -nvkm_fifo_chan_inst(struct nvkm_fifo *, u64 inst, unsigned long *flags); -struct nvkm_fifo_chan * -nvkm_fifo_chan_chid(struct nvkm_fifo *, int chid, unsigned long *flags); - int nv04_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int nv10_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int nv17_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c index 09a112af2f89..c9bf6305c3ec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c @@ -40,7 +40,7 @@ gt215_ce_isr_error_name[] = { }; void -gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_fifo_chan *chan) +gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_chan *chan) { struct nvkm_subdev *subdev = &ce->engine.subdev; struct nvkm_device *device = subdev->device; @@ -55,9 +55,9 @@ gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_fifo_chan *chan) nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] " "subc %d mthd %04x data %08x\n", ssta, - en ? en->name : "", chan ? chan->chid : -1, + en ? en->name : "", chan ? chan->id : -1, chan ? chan->inst->addr : 0, - chan ? chan->object.client->name : "unknown", + chan ? chan->name : "unknown", subc, mthd, data); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c index be2a7181dc15..caca4f639895 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c @@ -81,8 +81,7 @@ g84_cipher_intr(struct nvkm_engine *cipher) { struct nvkm_subdev *subdev = &cipher->subdev; struct nvkm_device *device = subdev->device; - struct nvkm_fifo *fifo = device->fifo; - struct nvkm_fifo_chan *chan; + struct nvkm_chan *chan; u32 stat = nvkm_rd32(device, 0x102130); u32 mthd = nvkm_rd32(device, 0x102190); u32 data = nvkm_rd32(device, 0x102194); @@ -90,16 +89,16 @@ g84_cipher_intr(struct nvkm_engine *cipher) unsigned long flags; char msg[128]; - chan = nvkm_fifo_chan_inst(fifo, (u64)inst << 12, &flags); + chan = nvkm_chan_get_inst(cipher, (u64)inst << 12, &flags); if (stat) { nvkm_snprintbf(msg, sizeof(msg), g84_cipher_intr_mask, stat); nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] " "mthd %04x data %08x\n", stat, msg, - chan ? chan->chid : -1, (u64)inst << 12, - chan ? chan->object.client->name : "unknown", + chan ? chan->id : -1, (u64)inst << 12, + chan ? chan->name : "unknown", mthd, data); } - nvkm_fifo_chan_put(fifo, flags, &chan); + nvkm_chan_put(&chan, flags); nvkm_wr32(device, 0x102130, stat); nvkm_wr32(device, 0x10200c, 0x10); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c index 43b7dec45179..d619b40a42c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c @@ -65,10 +65,10 @@ nvkm_falcon_intr(struct nvkm_engine *engine) u32 dest = nvkm_rd32(device, base + 0x01c); u32 intr = nvkm_rd32(device, base + 0x008) & dest & ~(dest >> 16); u32 inst = nvkm_rd32(device, base + 0x050) & 0x3fffffff; - struct nvkm_fifo_chan *chan; + struct nvkm_chan *chan; unsigned long flags; - chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags); + chan = nvkm_chan_get_inst(engine, (u64)inst << 12, &flags); if (intr & 0x00000040) { if (falcon->func->intr) { @@ -89,7 +89,7 @@ nvkm_falcon_intr(struct nvkm_engine *engine) nvkm_wr32(device, base + 0x004, intr); } - nvkm_fifo_chan_put(device->fifo, flags, &chan); + nvkm_chan_put(&chan, flags); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index e51fb10a04f7..83da63bdf3c4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -62,63 +62,6 @@ nvkm_fifo_fault(struct nvkm_fifo *fifo, struct nvkm_fault_data *info) return fifo->func->mmu_fault->recover(fifo, info); } -void -nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags, - struct nvkm_fifo_chan **pchan) -{ - struct nvkm_fifo_chan *chan = *pchan; - if (likely(chan)) { - *pchan = NULL; - spin_unlock_irqrestore(&fifo->lock, flags); - } -} - -struct nvkm_fifo_chan * -nvkm_fifo_chan_inst_locked(struct nvkm_fifo *fifo, u64 inst) -{ - struct nvkm_fifo_chan *chan; - list_for_each_entry(chan, &fifo->chan, head) { - if (chan->inst->addr == inst) { - list_del(&chan->head); - list_add(&chan->head, &fifo->chan); - return chan; - } - } - return NULL; -} - -struct nvkm_fifo_chan * -nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags) -{ - struct nvkm_fifo_chan *chan; - unsigned long flags; - spin_lock_irqsave(&fifo->lock, flags); - if ((chan = nvkm_fifo_chan_inst_locked(fifo, inst))) { - *rflags = flags; - return chan; - } - spin_unlock_irqrestore(&fifo->lock, flags); - return NULL; -} - -struct nvkm_fifo_chan * -nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags) -{ - struct nvkm_fifo_chan *chan; - unsigned long flags; - spin_lock_irqsave(&fifo->lock, flags); - list_for_each_entry(chan, &fifo->chan, head) { - if (chan->chid == chid) { - list_del(&chan->head); - list_add(&chan->head, &fifo->chan); - *rflags = flags; - return chan; - } - } - spin_unlock_irqrestore(&fifo->lock, flags); - return NULL; -} - void nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index ea8148bad45e..bfbd5ec9a720 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -302,6 +302,56 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object) return data; } +void +nvkm_chan_put(struct nvkm_chan **pchan, unsigned long irqflags) +{ + struct nvkm_chan *chan = *pchan; + + if (!chan) + return; + + *pchan = NULL; + spin_unlock_irqrestore(&chan->cgrp->lock, irqflags); +} + +struct nvkm_chan * +nvkm_chan_get_inst(struct nvkm_engine *engine, u64 inst, unsigned long *pirqflags) +{ + struct nvkm_fifo *fifo = engine->subdev.device->fifo; + struct nvkm_runl *runl; + struct nvkm_engn *engn; + struct nvkm_chan *chan; + + nvkm_runl_foreach(runl, fifo) { + nvkm_runl_foreach_engn(engn, runl) { + if (engine == &fifo->engine || engn->engine == engine) { + chan = nvkm_runl_chan_get_inst(runl, inst, pirqflags); + if (chan || engn->engine == engine) + return chan; + } + } + } + + return NULL; +} + +struct nvkm_chan * +nvkm_chan_get_chid(struct nvkm_engine *engine, int id, unsigned long *pirqflags) +{ + struct nvkm_fifo *fifo = engine->subdev.device->fifo; + struct nvkm_runl *runl; + struct nvkm_engn *engn; + + nvkm_runl_foreach(runl, fifo) { + nvkm_runl_foreach_engn(engn, runl) { + if (fifo->chid || engn->engine == engine) + return nvkm_runl_chan_get_chid(runl, id, pirqflags); + } + } + + return NULL; +} + static const struct nvkm_object_func nvkm_fifo_chan_func = { .dtor = nvkm_fifo_chan_dtor, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 7fc4c37b407f..7c1db7721ff6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -84,13 +84,13 @@ gf100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null) if (show) { nvkm_snprintbf(msg, sizeof(msg), runq->func->intr_0_names, show); - chan = nvkm_fifo_chan_chid(runq->fifo, chid, &flags); + chan = nvkm_chan_get_chid(&runq->fifo->engine, chid, &flags); nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] " "subc %d mthd %04x data %08x\n", runq->id, show, msg, chid, chan ? chan->inst->addr : 0, chan ? chan->object.client->name : "unknown", subc, mthd, data); - nvkm_fifo_chan_put(runq->fifo, flags, &chan); + nvkm_chan_put(&chan, flags); } nvkm_wr32(device, 0x0400c0 + (runq->id * 0x2000), 0x80600008); @@ -367,9 +367,9 @@ gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *inf struct nvkm_device *device = subdev->device; const struct nvkm_enum *er, *ee, *ec, *ea; struct nvkm_engine *engine = NULL; - struct nvkm_fifo_chan *chan; struct nvkm_runl *runl; struct nvkm_engn *engn; + struct nvkm_chan *chan; unsigned long flags; char ct[8] = "HUB/"; @@ -409,7 +409,7 @@ gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *inf } } - chan = nvkm_fifo_chan_inst(fifo, info->inst, &flags); + chan = nvkm_chan_get_inst(&fifo->engine, info->inst, &flags); nvkm_error(subdev, "fault %02x [%s] at %016llx engine %02x [%s] client %02x " @@ -427,7 +427,7 @@ gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *inf if (engine && chan) gf100_fifo_recover(gf100_fifo(fifo), engine, (void *)chan); - nvkm_fifo_chan_put(fifo, flags, &chan); + nvkm_chan_put(&chan, flags); } static const struct nvkm_fifo_func_mmu_fault diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index b899127cfd72..85f22fce11ed 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -30,7 +30,6 @@ #include "channv04.h" #include "regsnv04.h" -#include #include #include #include @@ -241,7 +240,7 @@ nv04_fifo_intr_cache_error(struct nvkm_fifo *fifo, u32 chid, u32 get) { struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_fifo_chan *chan; + struct nvkm_chan *chan; unsigned long flags; u32 pull0 = nvkm_rd32(device, 0x003250); u32 mthd, data; @@ -264,12 +263,12 @@ nv04_fifo_intr_cache_error(struct nvkm_fifo *fifo, u32 chid, u32 get) if (!(pull0 & 0x00000100) || !nv04_fifo_swmthd(device, chid, mthd, data)) { - chan = nvkm_fifo_chan_chid(fifo, chid, &flags); + chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags); nvkm_error(subdev, "CACHE_ERROR - " "ch %d [%s] subc %d mthd %04x data %08x\n", - chid, chan ? chan->object.client->name : "unknown", + chid, chan ? chan->name : "unknown", (mthd >> 13) & 7, mthd & 0x1ffc, data); - nvkm_fifo_chan_put(fifo, flags, &chan); + nvkm_chan_put(&chan, flags); } nvkm_wr32(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0); @@ -296,12 +295,12 @@ nv04_fifo_intr_dma_pusher(struct nvkm_fifo *fifo, u32 chid) u32 dma_put = nvkm_rd32(device, 0x003240); u32 push = nvkm_rd32(device, 0x003220); u32 state = nvkm_rd32(device, 0x003228); - struct nvkm_fifo_chan *chan; + struct nvkm_chan *chan; unsigned long flags; const char *name; - chan = nvkm_fifo_chan_chid(fifo, chid, &flags); - name = chan ? chan->object.client->name : "unknown"; + chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags); + name = chan ? chan->name : "unknown"; if (device->card_type == NV_50) { u32 ho_get = nvkm_rd32(device, 0x003328); u32 ho_put = nvkm_rd32(device, 0x003320); @@ -332,7 +331,7 @@ nv04_fifo_intr_dma_pusher(struct nvkm_fifo *fifo, u32 chid) if (dma_get != dma_put) nvkm_wr32(device, 0x003244, dma_put); } - nvkm_fifo_chan_put(fifo, flags, &chan); + nvkm_chan_put(&chan, flags); nvkm_wr32(device, 0x003228, 0x00000000); nvkm_wr32(device, 0x003220, 0x00000001); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 19c6e706f33e..7bc7b89ffd18 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -14,9 +14,6 @@ struct gk104_fifo_chan; void nvkm_fifo_kevent(struct nvkm_fifo *, int chid); void nvkm_fifo_recover_chan(struct nvkm_fifo *, int chid); -struct nvkm_fifo_chan * -nvkm_fifo_chan_inst_locked(struct nvkm_fifo *, u64 inst); - struct nvkm_fifo_chan_oclass; struct nvkm_fifo_func { void *(*dtor)(struct nvkm_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 0b75565bfbc1..e4984e1e7c65 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -20,12 +20,59 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "runl.h" +#include "cgrp.h" #include "chan.h" #include "chid.h" #include "priv.h" +#include #include +struct nvkm_chan * +nvkm_runl_chan_get_inst(struct nvkm_runl *runl, u64 inst, unsigned long *pirqflags) +{ + struct nvkm_chid *chid = runl->chid; + struct nvkm_chan *chan; + unsigned long flags; + int id; + + spin_lock_irqsave(&chid->lock, flags); + for_each_set_bit(id, chid->used, chid->nr) { + chan = chid->data[id]; + if (likely(chan)) { + if (chan->inst->addr == inst) { + spin_lock(&chan->cgrp->lock); + *pirqflags = flags; + spin_unlock(&chid->lock); + return chan; + } + } + } + spin_unlock_irqrestore(&chid->lock, flags); + return NULL; +} + +struct nvkm_chan * +nvkm_runl_chan_get_chid(struct nvkm_runl *runl, int id, unsigned long *pirqflags) +{ + struct nvkm_chid *chid = runl->chid; + struct nvkm_chan *chan; + unsigned long flags; + + spin_lock_irqsave(&chid->lock, flags); + if (!WARN_ON(id >= chid->nr)) { + chan = chid->data[id]; + if (likely(chan)) { + spin_lock(&chan->cgrp->lock); + *pirqflags = flags; + spin_unlock(&chid->lock); + return chan; + } + } + spin_unlock_irqrestore(&chid->lock, flags); + return NULL; +} + void nvkm_runl_del(struct nvkm_runl *runl) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index b223da2d4399..e618e326b3c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -51,6 +51,9 @@ struct nvkm_engn *nvkm_runl_add(struct nvkm_runl *, int engi, const struct nvkm_ enum nvkm_subdev_type, int inst); void nvkm_runl_del(struct nvkm_runl *); +struct nvkm_chan *nvkm_runl_chan_get_chid(struct nvkm_runl *, int chid, unsigned long *irqflags); +struct nvkm_chan *nvkm_runl_chan_get_inst(struct nvkm_runl *, u64 inst, unsigned long *irqflags); + #define nvkm_runl_find_engn(engn,runl,cond) nvkm_list_find(engn, &(runl)->engns, head, (cond)) #define nvkm_runl_foreach(runl,fifo) list_for_each_entry((runl), &(fifo)->runls, head) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index f16eabf4f642..68da77df856a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1548,7 +1548,7 @@ gf100_gr_intr(struct nvkm_gr *base) struct gf100_gr *gr = gf100_gr(base); struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_fifo_chan *chan; + struct nvkm_chan *chan; unsigned long flags; u64 inst = nvkm_rd32(device, 0x409b00) & 0x0fffffff; u32 stat = nvkm_rd32(device, 0x400100); @@ -1561,10 +1561,10 @@ gf100_gr_intr(struct nvkm_gr *base) const char *name = "unknown"; int chid = -1; - chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags); + chan = nvkm_chan_get_inst(&gr->base.engine, (u64)inst << 12, &flags); if (chan) { - name = chan->object.client->name; - chid = chan->chid; + name = chan->name; + chid = chan->id; } if (device->card_type < NV_E0 || subc < 4) @@ -1631,7 +1631,7 @@ gf100_gr_intr(struct nvkm_gr *base) } nvkm_wr32(device, 0x400500, 0x00010001); - nvkm_fifo_chan_put(device->fifo, flags, &chan); + nvkm_chan_put(&chan, flags); } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c index 0bc1a238de43..81bd682c2102 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c @@ -1192,7 +1192,7 @@ nv04_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv04_gr_chan, oclass, &chan->object); chan->gr = gr; - chan->chid = fifoch->chid; + chan->chid = fifoch->id; *pobject = &chan->object; *ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c index 942450b33bc6..7fe6e58f6bab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c @@ -1011,7 +1011,7 @@ nv10_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv10_gr_chan, oclass, &chan->object); chan->gr = gr; - chan->chid = fifoch->chid; + chan->chid = fifoch->id; *pobject = &chan->object; NV_WRITE_CTX(0x00400e88, 0x08000000); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c index 6bff10cee71b..75434f5de7ad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c @@ -83,7 +83,7 @@ nv20_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv20_gr_chan, oclass, &chan->object); chan->gr = gr; - chan->chid = fifoch->chid; + chan->chid = fifoch->id; *pobject = &chan->object; ret = nvkm_memory_new(gr->base.engine.subdev.device, @@ -182,7 +182,7 @@ nv20_gr_intr(struct nvkm_gr *base) struct nv20_gr *gr = nv20_gr(base); struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_fifo_chan *chan; + struct nvkm_chan *chan; u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); @@ -196,7 +196,7 @@ nv20_gr_intr(struct nvkm_gr *base) char msg[128], src[128], sta[128]; unsigned long flags; - chan = nvkm_fifo_chan_chid(device->fifo, chid, &flags); + chan = nvkm_chan_get_chid(&gr->base.engine, chid, &flags); nvkm_wr32(device, NV03_PGRAPH_INTR, stat); nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); @@ -209,11 +209,11 @@ nv20_gr_intr(struct nvkm_gr *base) "nstatus %08x [%s] ch %d [%s] subc %d " "class %04x mthd %04x data %08x\n", show, msg, nsource, src, nstatus, sta, chid, - chan ? chan->object.client->name : "unknown", + chan ? chan->name : "unknown", subc, class, mthd, data); } - nvkm_fifo_chan_put(device->fifo, flags, &chan); + nvkm_chan_put(&chan, flags); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c index f3a56f17d94a..94685e4d4f87 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c @@ -29,7 +29,7 @@ nv25_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv25_gr_chan, oclass, &chan->object); chan->gr = gr; - chan->chid = fifoch->chid; + chan->chid = fifoch->id; *pobject = &chan->object; ret = nvkm_memory_new(gr->base.engine.subdev.device, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c index f268d2642d29..2d6273675291 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c @@ -29,7 +29,7 @@ nv2a_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv2a_gr_chan, oclass, &chan->object); chan->gr = gr; - chan->chid = fifoch->chid; + chan->chid = fifoch->id; *pobject = &chan->object; ret = nvkm_memory_new(gr->base.engine.subdev.device, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c index e5737cdf2fa1..647bd6fede04 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c @@ -30,7 +30,7 @@ nv30_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv30_gr_chan, oclass, &chan->object); chan->gr = gr; - chan->chid = fifoch->chid; + chan->chid = fifoch->id; *pobject = &chan->object; ret = nvkm_memory_new(gr->base.engine.subdev.device, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c index 1ab2da8ebf4e..2eae3fe4ef4e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c @@ -29,7 +29,7 @@ nv34_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv34_gr_chan, oclass, &chan->object); chan->gr = gr; - chan->chid = fifoch->chid; + chan->chid = fifoch->id; *pobject = &chan->object; ret = nvkm_memory_new(gr->base.engine.subdev.device, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c index 591260f5676b..657d7cdba369 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c @@ -29,7 +29,7 @@ nv35_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv35_gr_chan, oclass, &chan->object); chan->gr = gr; - chan->chid = fifoch->chid; + chan->chid = fifoch->id; *pobject = &chan->object; ret = nvkm_memory_new(gr->base.engine.subdev.device, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c index 67f3535ff97e..d2df097a6cf6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c @@ -275,8 +275,8 @@ nv40_gr_intr(struct nvkm_gr *base) "nstatus %08x [%s] ch %d [%08x %s] subc %d " "class %04x mthd %04x data %08x\n", show, msg, nsource, src, nstatus, sta, - chan ? chan->fifo->chid : -1, inst << 4, - chan ? chan->fifo->object.client->name : "unknown", + chan ? chan->fifo->id : -1, inst << 4, + chan ? chan->fifo->name : "unknown", subc, class, mthd, data); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c index 563a10097e95..1ba18a8e380f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c @@ -622,7 +622,7 @@ nv50_gr_intr(struct nvkm_gr *base) struct nv50_gr *gr = nv50_gr(base); struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_fifo_chan *chan; + struct nvkm_chan *chan; u32 stat = nvkm_rd32(device, 0x400100); u32 inst = nvkm_rd32(device, 0x40032c) & 0x0fffffff; u32 addr = nvkm_rd32(device, 0x400704); @@ -637,10 +637,10 @@ nv50_gr_intr(struct nvkm_gr *base) char msg[128]; int chid = -1; - chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags); + chan = nvkm_chan_get_inst(&gr->base.engine, (u64)inst << 12, &flags); if (chan) { - name = chan->object.client->name; - chid = chan->chid; + name = chan->name; + chid = chan->id; } if (show & 0x00100000) { @@ -672,7 +672,7 @@ nv50_gr_intr(struct nvkm_gr *base) if (nvkm_rd32(device, 0x400824) & (1 << 31)) nvkm_wr32(device, 0x400824, nvkm_rd32(device, 0x400824) & ~(1 << 31)); - nvkm_fifo_chan_put(device->fifo, flags, &chan); + nvkm_chan_put(&chan, flags); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c index b1054db4c1b8..cb0c3991b2ad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c @@ -213,8 +213,8 @@ nv31_mpeg_intr(struct nvkm_engine *engine) if (show) { nvkm_error(subdev, "ch %d [%s] %08x %08x %08x %08x\n", - mpeg->chan ? mpeg->chan->fifo->chid : -1, - mpeg->chan ? mpeg->chan->object.client->name : + mpeg->chan ? mpeg->chan->fifo->id : -1, + mpeg->chan ? mpeg->chan->fifo->name : "unknown", stat, type, mthd, data); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c index 521ce43a2871..0890a279458e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c @@ -182,8 +182,8 @@ nv44_mpeg_intr(struct nvkm_engine *engine) if (show) { nvkm_error(subdev, "ch %d [%08x %s] %08x %08x %08x %08x\n", - chan ? chan->fifo->chid : -1, inst << 4, - chan ? chan->object.client->name : "unknown", + chan ? chan->fifo->id : -1, inst << 4, + chan ? chan->fifo->name : "unknown", stat, type, mthd, data); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c index 1b87df03c823..c15b2cbf506b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c @@ -40,7 +40,7 @@ static const struct nvkm_enum g98_sec_isr_error_name[] = { }; static void -g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_fifo_chan *chan) +g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_chan *chan) { struct nvkm_subdev *subdev = &sec->engine.subdev; struct nvkm_device *device = subdev->device; @@ -54,9 +54,9 @@ g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_fifo_chan *chan) nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] " "subc %d mthd %04x data %08x\n", ssta, - en ? en->name : "UNKNOWN", chan ? chan->chid : -1, + en ? en->name : "UNKNOWN", chan ? chan->id : -1, chan ? chan->inst->addr : 0, - chan ? chan->object.client->name : "unknown", + chan ? chan->name : "unknown", subc, mthd, data); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c index 14871d0bd746..a9d464db6974 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c @@ -35,7 +35,7 @@ nvkm_sw_mthd(struct nvkm_sw *sw, int chid, int subc, u32 mthd, u32 data) spin_lock_irqsave(&sw->engine.lock, flags); list_for_each_entry(chan, &sw->chan, head) { - if (chan->fifo->chid == chid) { + if (chan->fifo->id == chid) { handled = nvkm_sw_chan_mthd(chan, subc, mthd, data); list_del(&chan->head); list_add(&chan->head, &sw->chan); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c index 95fd8f834010..48641735168e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c @@ -137,8 +137,7 @@ nv50_fb_intr(struct nvkm_fb *base) struct nv50_fb *fb = nv50_fb(base); struct nvkm_subdev *subdev = &fb->base.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_fifo *fifo = device->fifo; - struct nvkm_fifo_chan *chan; + struct nvkm_chan *chan; const struct nvkm_enum *en, *re, *cl, *sc; u32 trap[6], idx, inst; u8 st0, st1, st2, st3; @@ -178,18 +177,18 @@ nv50_fb_intr(struct nvkm_fb *base) else if (en && en->data) sc = nvkm_enum_find(en->data, st3); else sc = NULL; - chan = nvkm_fifo_chan_inst(fifo, inst, &flags); + chan = nvkm_chan_get_inst(&device->fifo->engine, inst, &flags); nvkm_error(subdev, "trapped %s at %02x%04x%04x on channel %d [%08x %s] " "engine %02x [%s] client %02x [%s] " "subclient %02x [%s] reason %08x [%s]\n", (trap[5] & 0x00000100) ? "read" : "write", trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, - chan ? chan->chid : -1, inst, - chan ? chan->object.client->name : "unknown", + chan ? chan->id : -1, inst, + chan ? chan->name : "unknown", st0, en ? en->name : "", st2, cl ? cl->name : "", st3, sc ? sc->name : "", st1, re ? re->name : ""); - nvkm_fifo_chan_put(fifo, flags, &chan); + nvkm_chan_put(&chan, flags); } static int -- cgit v1.2.3 From f48dd2936138882d7755cbbc5d9984015c75980c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:30 +1000 Subject: drm/nouveau/fifo: add new engine context tracking Channel groups have somewhat more complicated requirements than what we currently support. An engine context is shared between all channels in a channel group, VEID/subctx support (later) brings per-VEID components, and we need to track an individual channel's engine context pointers. This commit adds the structures and refcounting to support the above, wrapping the prior implementation for the moment. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 3 +- drivers/gpu/drm/nouveau/nvkm/core/oproxy.c | 7 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c | 110 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h | 23 +++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 83 ++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 14 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 66 +++++++++++++ 7 files changed, 296 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index a47667d00f3a..5a5c37480400 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -11,7 +11,6 @@ struct nvkm_fault_data; struct nvkm_fifo_engn { struct nvkm_object *object; int refcount; - int usecount; }; struct nvkm_chan { @@ -21,6 +20,8 @@ struct nvkm_chan { union { int id; int chid; }; /*FIXME: remove later */ + struct list_head cctxs; + struct nvkm_fifo *fifo; struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c index 3ffd4845d9e5..3385528da650 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c @@ -47,7 +47,12 @@ nvkm_oproxy_map(struct nvkm_object *object, void *argv, u32 argc, static int nvkm_oproxy_unmap(struct nvkm_object *object) { - return nvkm_object_unmap(nvkm_oproxy(object)->object); + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + + if (unlikely(!oproxy->object)) + return 0; + + return nvkm_object_unmap(oproxy->object); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c index e6ac178db8b5..ed838609f15d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c @@ -27,6 +27,112 @@ #include +static void +nvkm_cgrp_ectx_put(struct nvkm_cgrp *cgrp, struct nvkm_ectx **pectx) +{ + struct nvkm_ectx *ectx = *pectx; + + if (ectx) { + struct nvkm_engn *engn = ectx->engn; + + if (refcount_dec_and_test(&ectx->refs)) { + CGRP_TRACE(cgrp, "dtor ectx %d[%s]", engn->id, engn->engine->subdev.name); + list_del(&ectx->head); + kfree(ectx); + } + + *pectx = NULL; + } +} + +static int +nvkm_cgrp_ectx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_ectx **pectx, + struct nvkm_chan *chan, struct nvkm_client *client) +{ + struct nvkm_ectx *ectx; + int ret = 0; + + /* Look for an existing context for this engine in the channel group. */ + ectx = nvkm_list_find(ectx, &cgrp->ectxs, head, ectx->engn == engn); + if (ectx) { + refcount_inc(&ectx->refs); + *pectx = ectx; + return 0; + } + + /* Nope - create a fresh one. */ + CGRP_TRACE(cgrp, "ctor ectx %d[%s]", engn->id, engn->engine->subdev.name); + if (!(ectx = *pectx = kzalloc(sizeof(*ectx), GFP_KERNEL))) + return -ENOMEM; + + ectx->engn = engn; + refcount_set(&ectx->refs, 1); + list_add_tail(&ectx->head, &cgrp->ectxs); + return ret; +} + +void +nvkm_cgrp_vctx_put(struct nvkm_cgrp *cgrp, struct nvkm_vctx **pvctx) +{ + struct nvkm_vctx *vctx = *pvctx; + + if (vctx) { + struct nvkm_engn *engn = vctx->ectx->engn; + + if (refcount_dec_and_test(&vctx->refs)) { + CGRP_TRACE(cgrp, "dtor vctx %d[%s]", engn->id, engn->engine->subdev.name); + + nvkm_cgrp_ectx_put(cgrp, &vctx->ectx); + if (vctx->vmm) { + atomic_dec(&vctx->vmm->engref[engn->engine->subdev.type]); + nvkm_vmm_unref(&vctx->vmm); + } + list_del(&vctx->head); + kfree(vctx); + } + + *pvctx = NULL; + } +} + +int +nvkm_cgrp_vctx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_chan *chan, + struct nvkm_vctx **pvctx, struct nvkm_client *client) +{ + struct nvkm_ectx *ectx; + struct nvkm_vctx *vctx; + int ret; + + /* Look for an existing sub-context for this engine+VEID in the channel group. */ + vctx = nvkm_list_find(vctx, &cgrp->vctxs, head, + vctx->ectx->engn == engn && vctx->vmm == chan->vmm); + if (vctx) { + refcount_inc(&vctx->refs); + *pvctx = vctx; + return 0; + } + + /* Nope - create a fresh one. But, context first. */ + ret = nvkm_cgrp_ectx_get(cgrp, engn, &ectx, chan, client); + if (ret) { + CGRP_ERROR(cgrp, "ectx %d[%s]: %d", engn->id, engn->engine->subdev.name, ret); + return ret; + } + + /* Now, create the sub-context. */ + CGRP_TRACE(cgrp, "ctor vctx %d[%s]", engn->id, engn->engine->subdev.name); + if (!(vctx = *pvctx = kzalloc(sizeof(*vctx), GFP_KERNEL))) { + nvkm_cgrp_ectx_put(cgrp, &ectx); + return -ENOMEM; + } + + vctx->ectx = ectx; + vctx->vmm = nvkm_vmm_ref(chan->vmm); + refcount_set(&vctx->refs, 1); + list_add_tail(&vctx->head, &cgrp->vctxs); + return ret; +} + static void nvkm_cgrp_del(struct kref *kref) { @@ -36,6 +142,7 @@ nvkm_cgrp_del(struct kref *kref) if (runl->cgid) nvkm_chid_put(runl->cgid, cgrp->id, &cgrp->lock); + mutex_destroy(&cgrp->mutex); nvkm_vmm_unref(&cgrp->vmm); kfree(cgrp); } @@ -80,6 +187,9 @@ nvkm_cgrp_new(struct nvkm_runl *runl, const char *name, struct nvkm_vmm *vmm, bo cgrp->chans = NULL; cgrp->chan_nr = 0; spin_lock_init(&cgrp->lock); + INIT_LIST_HEAD(&cgrp->ectxs); + INIT_LIST_HEAD(&cgrp->vctxs); + mutex_init(&cgrp->mutex); if (runl->cgid) { cgrp->id = nvkm_chid_get(runl->cgid, cgrp); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h index d0510df9286a..50ba7c7ee0a8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h @@ -3,6 +3,22 @@ #define __NVKM_CGRP_H__ #include struct nvkm_chan; +struct nvkm_client; + +struct nvkm_vctx { + struct nvkm_ectx *ectx; + struct nvkm_vmm *vmm; + refcount_t refs; + + struct list_head head; +}; + +struct nvkm_ectx { + struct nvkm_engn *engn; + refcount_t refs; + + struct list_head head; +}; struct nvkm_cgrp { const struct nvkm_cgrp_func { @@ -19,6 +35,10 @@ struct nvkm_cgrp { spinlock_t lock; /* protects irq handler channel (group) lookup */ + struct list_head ectxs; + struct list_head vctxs; + struct mutex mutex; + struct list_head head; struct list_head chan; }; @@ -27,6 +47,9 @@ int nvkm_cgrp_new(struct nvkm_runl *, const char *name, struct nvkm_vmm *, bool struct nvkm_cgrp **); struct nvkm_cgrp *nvkm_cgrp_ref(struct nvkm_cgrp *); void nvkm_cgrp_unref(struct nvkm_cgrp **); +int nvkm_cgrp_vctx_get(struct nvkm_cgrp *, struct nvkm_engn *, struct nvkm_chan *, + struct nvkm_vctx **, struct nvkm_client *); +void nvkm_cgrp_vctx_put(struct nvkm_cgrp *, struct nvkm_vctx **); #define CGRP_PRCLI(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a) #define CGRP_PRINT(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:"f, (c)->id, ##a) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index bfbd5ec9a720..f250b0f9e274 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -65,9 +65,6 @@ nvkm_fifo_chan_child_fini(struct nvkm_oproxy *base, bool suspend) const char *name = engine->subdev.name; int ret = 0; - if (--engn->usecount) - return 0; - if (chan->func->engine_fini) { ret = chan->func->engine_fini(chan, engine, suspend); if (ret) { @@ -98,9 +95,6 @@ nvkm_fifo_chan_child_init(struct nvkm_oproxy *base) const char *name = engine->subdev.name; int ret; - if (engn->usecount++) - return 0; - if (engn->object) { ret = nvkm_object_init(engn->object); if (ret) @@ -144,8 +138,6 @@ nvkm_fifo_chan_child_del(struct nvkm_oproxy *base) static const struct nvkm_oproxy_func nvkm_fifo_chan_child_func = { .dtor[0] = nvkm_fifo_chan_child_del, - .init[0] = nvkm_fifo_chan_child_init, - .fini[0] = nvkm_fifo_chan_child_fini, }; int @@ -216,6 +208,80 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, return 0; } +void +nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct nvkm_cctx *cctx) +{ + /* Update context pointer. */ + if (cctx) + nvkm_fifo_chan_child_init(nvkm_oproxy(oproxy->object)); + else + nvkm_fifo_chan_child_fini(nvkm_oproxy(oproxy->object), false); +} + +void +nvkm_chan_cctx_put(struct nvkm_chan *chan, struct nvkm_cctx **pcctx) +{ + struct nvkm_cctx *cctx = *pcctx; + + if (cctx) { + struct nvkm_engn *engn = cctx->vctx->ectx->engn; + + if (refcount_dec_and_mutex_lock(&cctx->refs, &chan->cgrp->mutex)) { + CHAN_TRACE(chan, "dtor cctx %d[%s]", engn->id, engn->engine->subdev.name); + nvkm_cgrp_vctx_put(chan->cgrp, &cctx->vctx); + list_del(&cctx->head); + kfree(cctx); + mutex_unlock(&chan->cgrp->mutex); + } + + *pcctx = NULL; + } +} + +int +nvkm_chan_cctx_get(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_cctx **pcctx, + struct nvkm_client *client) +{ + struct nvkm_cgrp *cgrp = chan->cgrp; + struct nvkm_vctx *vctx; + struct nvkm_cctx *cctx; + int ret; + + /* Look for an existing channel context for this engine+VEID. */ + mutex_lock(&cgrp->mutex); + cctx = nvkm_list_find(cctx, &chan->cctxs, head, + cctx->vctx->ectx->engn == engn && cctx->vctx->vmm == chan->vmm); + if (cctx) { + refcount_inc(&cctx->refs); + *pcctx = cctx; + mutex_unlock(&chan->cgrp->mutex); + return 0; + } + + /* Nope - create a fresh one. But, sub-context first. */ + ret = nvkm_cgrp_vctx_get(cgrp, engn, chan, &vctx, client); + if (ret) { + CHAN_ERROR(chan, "vctx %d[%s]: %d", engn->id, engn->engine->subdev.name, ret); + goto done; + } + + /* Now, create the channel context - to track engine binding. */ + CHAN_TRACE(chan, "ctor cctx %d[%s]", engn->id, engn->engine->subdev.name); + if (!(cctx = *pcctx = kzalloc(sizeof(*cctx), GFP_KERNEL))) { + nvkm_cgrp_vctx_put(cgrp, &vctx); + ret = -ENOMEM; + goto done; + } + + cctx->vctx = vctx; + refcount_set(&cctx->refs, 1); + refcount_set(&cctx->uses, 0); + list_add_tail(&cctx->head, &chan->cctxs); +done: + mutex_unlock(&cgrp->mutex); + return ret; +} + static int nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) { @@ -409,6 +475,7 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); chan->fifo = fifo; + INIT_LIST_HEAD(&chan->cctxs); INIT_LIST_HEAD(&chan->head); /* Join channel group. diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 0f1added5c24..bf1c3b580def 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -3,9 +3,18 @@ #define __NVKM_CHAN_H__ #define nvkm_chan(p) container_of((p), struct nvkm_chan, object) /*FIXME: remove later */ #include +struct nvkm_engn; extern const struct nvkm_event_func nvkm_chan_event; +struct nvkm_cctx { + struct nvkm_vctx *vctx; + refcount_t refs; + refcount_t uses; + + struct list_head head; +}; + struct nvkm_chan_func { void *(*dtor)(struct nvkm_fifo_chan *); void (*init)(struct nvkm_fifo_chan *); @@ -26,6 +35,11 @@ int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, u32 engm, int bar, u32 base, u32 user, const struct nvkm_oclass *, struct nvkm_fifo_chan *); void nvkm_chan_del(struct nvkm_chan **); +int nvkm_chan_cctx_get(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx **, + struct nvkm_client * /*TODO: remove need for this */); +void nvkm_chan_cctx_put(struct nvkm_chan *, struct nvkm_cctx **); +struct nvkm_oproxy; +void nvkm_chan_cctx_bind(struct nvkm_chan *, struct nvkm_oproxy *, struct nvkm_cctx *); #define CHAN_PRCLI(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a) #define CHAN_PRINT(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:"f, (c)->id, ##a) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index c4f404840806..8681ff045887 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -63,10 +63,61 @@ nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_ struct nvkm_uobj { struct nvkm_oproxy oproxy; struct nvkm_chan *chan; + struct nvkm_cctx *cctx; }; +static int +nvkm_uchan_object_fini_1(struct nvkm_oproxy *oproxy, bool suspend) +{ + struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy); + struct nvkm_chan *chan = uobj->chan; + struct nvkm_cctx *cctx = uobj->cctx; + + /* Unbind engine context from channel, if no longer required. */ + if (refcount_dec_and_mutex_lock(&cctx->uses, &chan->cgrp->mutex)) { + nvkm_chan_cctx_bind(chan, oproxy, NULL); + mutex_unlock(&chan->cgrp->mutex); + } + + return 0; +} + +static int +nvkm_uchan_object_init_0(struct nvkm_oproxy *oproxy) +{ + struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy); + struct nvkm_chan *chan = uobj->chan; + struct nvkm_cctx *cctx = uobj->cctx; + int ret = 0; + + /* Bind engine context to channel, if it hasn't been already. */ + if (!refcount_inc_not_zero(&cctx->uses)) { + mutex_lock(&chan->cgrp->mutex); + if (!refcount_inc_not_zero(&cctx->uses)) { + if (ret == 0) { + nvkm_chan_cctx_bind(chan, oproxy, cctx); + refcount_set(&cctx->uses, 1); + } + } + mutex_unlock(&chan->cgrp->mutex); + } + + return ret; +} + +static void +nvkm_uchan_object_dtor(struct nvkm_oproxy *oproxy) +{ + struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy); + + nvkm_chan_cctx_put(uobj->chan, &uobj->cctx); +} + static const struct nvkm_oproxy_func nvkm_uchan_object = { + .dtor[1] = nvkm_uchan_object_dtor, + .init[0] = nvkm_uchan_object_init_0, + .fini[1] = nvkm_uchan_object_fini_1, }; static int @@ -74,9 +125,18 @@ nvkm_uchan_object_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) { struct nvkm_chan *chan = nvkm_uchan(oclass->parent)->chan; + struct nvkm_cgrp *cgrp = chan->cgrp; + struct nvkm_engn *engn; struct nvkm_uobj *uobj; struct nvkm_oclass _oclass; + int ret; + /* Lookup host engine state for target engine. */ + engn = nvkm_runl_find_engn(engn, cgrp->runl, engn->engine == oclass->engine); + if (WARN_ON(!engn)) + return -EINVAL; + + /* Allocate SW object. */ if (!(uobj = kzalloc(sizeof(*uobj), GFP_KERNEL))) return -ENOMEM; @@ -84,6 +144,12 @@ nvkm_uchan_object_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, uobj->chan = chan; *pobject = &uobj->oproxy.base; + /* Ref. channel context for target engine.*/ + ret = nvkm_chan_cctx_get(chan, engn, &uobj->cctx, oclass->client); + if (ret) + return ret; + + /* Allocate HW object. */ _oclass = *oclass; _oclass.parent = &chan->object; return nvkm_fifo_chan_child_new(&_oclass, argv, argc, &uobj->oproxy.object); -- cgit v1.2.3 From 4a492fd5d26298c82c555f603fe4aa38cf512464 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:30 +1000 Subject: drm/nouveau/fifo: add runlist wait() - adds g8x/turing registers, which were missing before - switches fermi to polled wait, like later hw (see: 4f2fc25c0f8bc...) Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 4 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 5 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 23 ++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 33 +++++++++++++--------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 2 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 27 ++++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 3 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 9 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 5 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 14 +++++++-- 15 files changed, 102 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 5a5c37480400..a4cc7f07bb89 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -54,6 +54,10 @@ struct nvkm_fifo { struct nvkm_event event; } nonstall; + struct { + u32 chan_msec; + } timeout; + int nr; struct list_head chan; spinlock_t lock; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 83da63bdf3c4..e08d8d14a19a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -319,6 +319,11 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, fifo->func = func; INIT_LIST_HEAD(&fifo->runqs); INIT_LIST_HEAD(&fifo->runls); + /*TODO: Needs to be >CTXSW_TIMEOUT, so RC can recover before this is hit. + * CTXSW_TIMEOUT HW default seems to differ between GPUs, so just a + * large number for now until we support changing it. + */ + fifo->timeout.chan_msec = 10000; spin_lock_init(&fifo->lock); mutex_init(&fifo->mutex); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 7c1db7721ff6..70a2609479b9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -115,12 +115,19 @@ gf100_runq = { .intr_0_names = gf100_runq_intr_0_names, }; +static bool +gf100_runl_pending(struct nvkm_runl *runl) +{ + return nvkm_rd32(runl->fifo->engine.subdev.device, 0x00227c) & 0x00100000; +} + void gf100_fifo_runlist_commit(struct gf100_fifo *fifo) { struct gf100_fifo_chan *chan; struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; + struct nvkm_runl *runl = nvkm_runl_first(&fifo->base); struct nvkm_memory *cur; int nr = 0; int target; @@ -150,10 +157,7 @@ gf100_fifo_runlist_commit(struct gf100_fifo *fifo) (target << 28)); nvkm_wr32(device, 0x002274, 0x01f00000 | nr); - if (wait_event_timeout(fifo->runlist.wait, - !(nvkm_rd32(device, 0x00227c) & 0x00100000), - msecs_to_jiffies(2000)) == 0) - nvkm_error(subdev, "runlist update timeout\n"); + runl->func->wait(runl); mutex_unlock(&fifo->base.mutex); } @@ -175,6 +179,8 @@ gf100_fifo_runlist_insert(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan) static const struct nvkm_runl_func gf100_runl = { + .wait = nv50_runl_wait, + .pending = gf100_runl_pending, }; static void @@ -558,14 +564,13 @@ gf100_fifo_intr_pbdma(struct nvkm_fifo *fifo) } static void -gf100_fifo_intr_runlist(struct gf100_fifo *fifo) +gf100_fifo_intr_runlist(struct nvkm_fifo *fifo) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 intr = nvkm_rd32(device, 0x002a00); if (intr & 0x10000000) { - wake_up(&fifo->runlist.wait); nvkm_wr32(device, 0x002a00, 0x10000000); intr &= ~0x10000000; } @@ -660,7 +665,7 @@ gf100_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x40000000) { - gf100_fifo_intr_runlist(gf100_fifo(fifo)); + gf100_fifo_intr_runlist(fifo); stat &= ~0x40000000; } @@ -779,8 +784,6 @@ gf100_fifo_oneinit(struct nvkm_fifo *base) if (ret) return ret; - init_waitqueue_head(&fifo->runlist.wait); - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000, 0x1000, false, &fifo->user.mem); if (ret) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h index 82b8467545a8..8e0c1a5e3c57 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -20,7 +20,6 @@ struct gf100_fifo { struct { struct nvkm_memory *mem[2]; int active; - wait_queue_head_t wait; } runlist; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index de8e3a17d79e..c816654dc245 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -197,12 +197,21 @@ gk104_runq = { .intr_0_names = gk104_runq_intr_0_names, }; +bool +gk104_runl_pending(struct nvkm_runl *runl) +{ + struct nvkm_device *device = runl->fifo->engine.subdev.device; + + return nvkm_rd32(device, 0x002284 + (runl->id * 0x08)) & 0x00100000; +} + void gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, struct nvkm_memory *mem, int nr) { struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; + struct nvkm_runl *rl = nvkm_runl_get(&fifo->base, runl, 0); int target; switch (nvkm_memory_target(mem)) { @@ -217,11 +226,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, (target << 28)); nvkm_wr32(device, 0x002274, (runl << 20) | nr); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x002284 + (runl * 0x08)) & 0x00100000)) - break; - ) < 0) - nvkm_error(subdev, "runlist %d update timeout\n", runl); + rl->func->wait(rl); } void @@ -299,6 +304,8 @@ gk104_fifo_runlist = { static const struct nvkm_runl_func gk104_runl = { + .wait = nv50_runl_wait, + .pending = gk104_runl_pending, }; int @@ -736,15 +743,14 @@ gk104_fifo_intr_dropped_fault(struct nvkm_fifo *fifo) } void -gk104_fifo_intr_runlist(struct gk104_fifo *fifo) +gk104_fifo_intr_runlist(struct nvkm_fifo *fifo) { - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_runl *runl; u32 mask = nvkm_rd32(device, 0x002a00); - while (mask) { - int runl = __ffs(mask); - wake_up(&fifo->runlist[runl].wait); - nvkm_wr32(device, 0x002a00, 1 << runl); - mask &= ~(1 << runl); + + nvkm_runl_foreach_cond(runl, fifo, mask & BIT(runl->id)) { + nvkm_wr32(device, 0x002a00, BIT(runl->id)); } } @@ -810,7 +816,7 @@ gk104_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x40000000) { - gk104_fifo_intr_runlist(gk104_fifo(fifo)); + gk104_fifo_intr_runlist(fifo); stat &= ~0x40000000; } @@ -949,7 +955,6 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) return ret; } - init_waitqueue_head(&fifo->runlist[i].wait); INIT_LIST_HEAD(&fifo->runlist[i].cgrp); INIT_LIST_HEAD(&fifo->runlist[i].chan); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 13f1efcc9e24..7cff1529ae35 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -30,7 +30,6 @@ struct gk104_fifo { struct { struct nvkm_memory *mem[2]; int next; - wait_queue_head_t wait; struct list_head cgrp; struct list_head chan; u32 engm; @@ -63,7 +62,6 @@ void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_update(struct gk104_fifo *, int runl); void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, struct gk104_fifo_engine_status *status); -void gk104_fifo_intr_runlist(struct gk104_fifo *fifo); void *gk104_fifo_dtor(struct nvkm_fifo *base); int gk104_fifo_oneinit(struct nvkm_fifo *); void gk104_fifo_init(struct nvkm_fifo *base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 5271f5504854..bcc78b35d4e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -60,6 +60,8 @@ gk110_fifo_runlist = { const struct nvkm_runl_func gk110_runl = { + .wait = nv50_runl_wait, + .pending = gk104_runl_pending, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index ecf4e6d94866..b6a2210f42c2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -54,6 +54,8 @@ gm107_fifo_runlist = { const struct nvkm_runl_func gm107_runl = { + .wait = nv50_runl_wait, + .pending = gk104_runl_pending, }; static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 0ca14b08ca3a..b810175209d1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -31,6 +31,8 @@ static const struct nvkm_runl_func gp100_runl = { + .wait = nv50_runl_wait, + .pending = gk104_runl_pending, }; static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 49d7c9e7fb8a..7ad04e97a82d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -84,6 +84,8 @@ gv100_fifo_runlist = { static const struct nvkm_runl_func gv100_runl = { + .wait = nv50_runl_wait, + .pending = gk104_runl_pending, }; const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 46013aea97d6..16e59d8ea325 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -25,11 +25,12 @@ #include "chid.h" #include "runl.h" +#include +#include + #include "nv50.h" #include "channv50.h" -#include - #include static const struct nvkm_chan_func @@ -74,8 +75,30 @@ nv50_fifo_runlist_update(struct nv50_fifo *fifo) mutex_unlock(&fifo->base.mutex); } +static bool +nv50_runl_pending(struct nvkm_runl *runl) +{ + return nvkm_rd32(runl->fifo->engine.subdev.device, 0x0032ec) & 0x00000100; +} + +int +nv50_runl_wait(struct nvkm_runl *runl) +{ + struct nvkm_fifo *fifo = runl->fifo; + + nvkm_msec(fifo->engine.subdev.device, fifo->timeout.chan_msec, + if (!nvkm_runl_update_pending(runl)) + return 0; + usleep_range(1, 2); + ); + + return -ETIMEDOUT; +} + const struct nvkm_runl_func nv50_runl = { + .wait = nv50_runl_wait, + .pending = nv50_runl_pending, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 7bc7b89ffd18..bab3cfbc5fcf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -101,6 +101,7 @@ int nv10_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_runl_func nv50_runl; +int nv50_runl_wait(struct nvkm_runl *); extern const struct nvkm_engn_func nv50_engn_sw; extern const struct nvkm_event_func g84_fifo_nonstall; @@ -123,6 +124,7 @@ int gk104_fifo_chid_nr(struct nvkm_fifo *); int gk104_fifo_runl_ctor(struct nvkm_fifo *); void gk104_fifo_init_pbdmas(struct nvkm_fifo *, u32); irqreturn_t gk104_fifo_intr(struct nvkm_inth *); +void gk104_fifo_intr_runlist(struct nvkm_fifo *); void gk104_fifo_intr_chsw(struct nvkm_fifo *); void gk104_fifo_intr_bind(struct nvkm_fifo *); extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; @@ -131,6 +133,7 @@ extern const struct nvkm_enum gk104_fifo_mmu_fault_hubclient[]; extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[]; void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); +bool gk104_runl_pending(struct nvkm_runl *); extern const struct nvkm_runq_func gk104_runq; void gk104_runq_init(struct nvkm_runq *); bool gk104_runq_intr(struct nvkm_runq *, struct nvkm_runl *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index e4984e1e7c65..0e1d703456b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -73,6 +73,15 @@ nvkm_runl_chan_get_chid(struct nvkm_runl *runl, int id, unsigned long *pirqflags return NULL; } +bool +nvkm_runl_update_pending(struct nvkm_runl *runl) +{ + if (!runl->func->pending(runl)) + return false; + + return true; +} + void nvkm_runl_del(struct nvkm_runl *runl) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index e618e326b3c3..7682731c3af6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -24,6 +24,8 @@ struct nvkm_engn { struct nvkm_runl { const struct nvkm_runl_func { + int (*wait)(struct nvkm_runl *); + bool (*pending)(struct nvkm_runl *); } *func; struct nvkm_fifo *fifo; int id; @@ -50,13 +52,16 @@ struct nvkm_runl *nvkm_runl_get(struct nvkm_fifo *, int runi, u32 addr); struct nvkm_engn *nvkm_runl_add(struct nvkm_runl *, int engi, const struct nvkm_engn_func *, enum nvkm_subdev_type, int inst); void nvkm_runl_del(struct nvkm_runl *); +bool nvkm_runl_update_pending(struct nvkm_runl *); struct nvkm_chan *nvkm_runl_chan_get_chid(struct nvkm_runl *, int chid, unsigned long *irqflags); struct nvkm_chan *nvkm_runl_chan_get_inst(struct nvkm_runl *, u64 inst, unsigned long *irqflags); #define nvkm_runl_find_engn(engn,runl,cond) nvkm_list_find(engn, &(runl)->engns, head, (cond)) +#define nvkm_runl_first(fifo) list_first_entry(&(fifo)->runls, struct nvkm_runl, head) #define nvkm_runl_foreach(runl,fifo) list_for_each_entry((runl), &(fifo)->runls, head) +#define nvkm_runl_foreach_cond(runl,fifo,cond) nvkm_list_foreach(runl, &(fifo)->runls, head, (cond)) #define nvkm_runl_foreach_engn(engn,runl) list_for_each_entry((engn), &(runl)->engns, head) #define nvkm_runl_foreach_engn_cond(engn,runl,cond) \ nvkm_list_foreach(engn, &(runl)->engns, head, (cond)) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 47de0b97534a..f0564fa400b7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -35,6 +35,14 @@ static const struct nvkm_chan_func tu102_chan = { }; +static bool +tu102_runl_pending(struct nvkm_runl *runl) +{ + struct nvkm_device *device = runl->fifo->engine.subdev.device; + + return nvkm_rd32(device, 0x002b0c + (runl->id * 0x10)) & 0x00008000; +} + static void tu102_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, struct nvkm_memory *mem, int nr) @@ -46,8 +54,6 @@ tu102_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, nvkm_wr32(device, 0x002b00 + (runl * 0x10), lower_32_bits(addr)); nvkm_wr32(device, 0x002b04 + (runl * 0x10), upper_32_bits(addr)); nvkm_wr32(device, 0x002b08 + (runl * 0x10), nr); - - /*XXX: how to wait? can you even wait? */ } static const struct gk104_fifo_runlist_func @@ -60,6 +66,8 @@ tu102_fifo_runlist = { static const struct nvkm_runl_func tu102_runl = { + .wait = nv50_runl_wait, + .pending = tu102_runl_pending, }; static const struct nvkm_enum @@ -319,7 +327,7 @@ tu102_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x40000000) { - gk104_fifo_intr_runlist(gk104_fifo(fifo)); + gk104_fifo_intr_runlist(fifo); stat &= ~0x40000000; } -- cgit v1.2.3 From 3a6bc9c242e10c203a5b083af7823b50b5d63010 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:31 +1000 Subject: drm/nouveau/fifo: add runlist block()/allow() Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 13 ++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 14 +++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 14 +++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 2 ++ .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 4 ---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 18 +++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 28 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 6 +++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 2 ++ 13 files changed, 95 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index f250b0f9e274..748f3f199b9f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -211,11 +211,24 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, void nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct nvkm_cctx *cctx) { + struct nvkm_cgrp *cgrp = chan->cgrp; + struct nvkm_runl *runl = cgrp->runl; + + /* Prevent any channel in channel group from being rescheduled, kick them + * off host and any engine(s) they're loaded on. + */ + if (cgrp->hw) + nvkm_runl_block(runl); + /* Update context pointer. */ if (cctx) nvkm_fifo_chan_child_init(nvkm_oproxy(oproxy->object)); else nvkm_fifo_chan_child_fini(nvkm_oproxy(oproxy->object), false); + + /* Resume normal operation. */ + if (cgrp->hw) + nvkm_runl_allow(runl); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 70a2609479b9..fcfc241c8a99 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -115,6 +115,18 @@ gf100_runq = { .intr_0_names = gf100_runq_intr_0_names, }; +static void +gf100_runl_allow(struct nvkm_runl *runl, u32 engm) +{ + nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, engm, 0x00000000); +} + +static void +gf100_runl_block(struct nvkm_runl *runl, u32 engm) +{ + nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, engm, engm); +} + static bool gf100_runl_pending(struct nvkm_runl *runl) { @@ -181,6 +193,8 @@ static const struct nvkm_runl_func gf100_runl = { .wait = nv50_runl_wait, .pending = gf100_runl_pending, + .block = gf100_runl_block, + .allow = gf100_runl_allow, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index c816654dc245..12aebf83f090 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -197,6 +197,18 @@ gk104_runq = { .intr_0_names = gk104_runq_intr_0_names, }; +void +gk104_runl_allow(struct nvkm_runl *runl, u32 engm) +{ + nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, BIT(runl->id), 0x00000000); +} + +void +gk104_runl_block(struct nvkm_runl *runl, u32 engm) +{ + nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, BIT(runl->id), BIT(runl->id)); +} + bool gk104_runl_pending(struct nvkm_runl *runl) { @@ -306,6 +318,8 @@ static const struct nvkm_runl_func gk104_runl = { .wait = nv50_runl_wait, .pending = gk104_runl_pending, + .block = gk104_runl_block, + .allow = gk104_runl_allow, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index bcc78b35d4e2..134de3c71ad5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -62,6 +62,8 @@ const struct nvkm_runl_func gk110_runl = { .wait = nv50_runl_wait, .pending = gk104_runl_pending, + .block = gk104_runl_block, + .allow = gk104_runl_allow, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index b6a2210f42c2..d3b2aa701f53 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -56,6 +56,8 @@ const struct nvkm_runl_func gm107_runl = { .wait = nv50_runl_wait, .pending = gk104_runl_pending, + .block = gk104_runl_block, + .allow = gk104_runl_allow, }; static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index b810175209d1..4dd3fb04d7e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -33,6 +33,8 @@ static const struct nvkm_runl_func gp100_runl = { .wait = nv50_runl_wait, .pending = gk104_runl_pending, + .block = gk104_runl_block, + .allow = gk104_runl_allow, }; static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 34a8e792c0e8..6e74fdc0dc24 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -37,15 +37,12 @@ gv100_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *chan) static int gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid) { - struct nvkm_subdev *subdev = &chan->base.fifo->engine.subdev; - struct nvkm_device *device = subdev->device; const u32 mask = ce ? 0x00020000 : 0x00010000; const u32 data = valid ? mask : 0x00000000; int ret; /* Block runlist to prevent the channel from being rescheduled. */ mutex_lock(&chan->fifo->base.mutex); - nvkm_mask(device, 0x002630, BIT(chan->runl), BIT(chan->runl)); /* Preempt the channel. */ ret = gk104_fifo_gpfifo_kick_locked(chan); @@ -57,7 +54,6 @@ gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid } /* Resume runlist. */ - nvkm_mask(device, 0x002630, BIT(chan->runl), 0); mutex_unlock(&chan->fifo->base.mutex); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 7ad04e97a82d..c147c26b80ca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -86,6 +86,8 @@ static const struct nvkm_runl_func gv100_runl = { .wait = nv50_runl_wait, .pending = gk104_runl_pending, + .block = gk104_runl_block, + .allow = gk104_runl_allow, }; const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 85f22fce11ed..446e65dcb036 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -129,14 +129,13 @@ nv04_engn = { }; void -nv04_fifo_pause(struct nvkm_fifo *base, unsigned long *pflags) -__acquires(fifo->base.lock) +nv04_fifo_pause(struct nvkm_fifo *fifo, unsigned long *pflags) +__acquires(fifo->lock) { - struct nv04_fifo *fifo = nv04_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; unsigned long flags; - spin_lock_irqsave(&fifo->base.lock, flags); + spin_lock_irqsave(&fifo->lock, flags); *pflags = flags; nvkm_wr32(device, NV03_PFIFO_CACHES, 0x00000000); @@ -165,17 +164,16 @@ __acquires(fifo->base.lock) } void -nv04_fifo_start(struct nvkm_fifo *base, unsigned long *pflags) -__releases(fifo->base.lock) +nv04_fifo_start(struct nvkm_fifo *fifo, unsigned long *pflags) +__releases(fifo->lock) { - struct nv04_fifo *fifo = nv04_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; unsigned long flags = *pflags; nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000001); nvkm_wr32(device, NV03_PFIFO_CACHES, 0x00000001); - spin_unlock_irqrestore(&fifo->base.lock, flags); + spin_unlock_irqrestore(&fifo->lock, flags); } const struct nvkm_runl_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index bab3cfbc5fcf..16fe77ee4c86 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -134,6 +134,8 @@ extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[]; void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); bool gk104_runl_pending(struct nvkm_runl *); +void gk104_runl_block(struct nvkm_runl *, u32); +void gk104_runl_allow(struct nvkm_runl *, u32); extern const struct nvkm_runq_func gk104_runq; void gk104_runq_init(struct nvkm_runq *); bool gk104_runq_intr(struct nvkm_runq *, struct nvkm_runl *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 0e1d703456b6..438e884b8100 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -82,6 +82,34 @@ nvkm_runl_update_pending(struct nvkm_runl *runl) return true; } +void +nvkm_runl_allow(struct nvkm_runl *runl) +{ + struct nvkm_fifo *fifo = runl->fifo; + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + if (!--runl->blocked) { + RUNL_TRACE(runl, "running"); + runl->func->allow(runl, ~0); + } + spin_unlock_irqrestore(&fifo->lock, flags); +} + +void +nvkm_runl_block(struct nvkm_runl *runl) +{ + struct nvkm_fifo *fifo = runl->fifo; + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + if (!runl->blocked++) { + RUNL_TRACE(runl, "stopped"); + runl->func->block(runl, ~0); + } + spin_unlock_irqrestore(&fifo->lock, flags); +} + void nvkm_runl_del(struct nvkm_runl *runl) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index 7682731c3af6..aebd8a750d38 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -26,6 +26,8 @@ struct nvkm_runl { const struct nvkm_runl_func { int (*wait)(struct nvkm_runl *); bool (*pending)(struct nvkm_runl *); + void (*block)(struct nvkm_runl *, u32 engm); + void (*allow)(struct nvkm_runl *, u32 engm); } *func; struct nvkm_fifo *fifo; int id; @@ -44,6 +46,8 @@ struct nvkm_runl { int chan_nr; struct mutex mutex; + int blocked; + struct list_head head; }; @@ -52,6 +56,8 @@ struct nvkm_runl *nvkm_runl_get(struct nvkm_fifo *, int runi, u32 addr); struct nvkm_engn *nvkm_runl_add(struct nvkm_runl *, int engi, const struct nvkm_engn_func *, enum nvkm_subdev_type, int inst); void nvkm_runl_del(struct nvkm_runl *); +void nvkm_runl_block(struct nvkm_runl *); +void nvkm_runl_allow(struct nvkm_runl *); bool nvkm_runl_update_pending(struct nvkm_runl *); struct nvkm_chan *nvkm_runl_chan_get_chid(struct nvkm_runl *, int chid, unsigned long *irqflags); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index f0564fa400b7..7d3c9d8e54a7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -68,6 +68,8 @@ static const struct nvkm_runl_func tu102_runl = { .wait = nv50_runl_wait, .pending = tu102_runl_pending, + .block = gk104_runl_block, + .allow = gk104_runl_allow, }; static const struct nvkm_enum -- cgit v1.2.3 From 62742b5ef314c622ae9d848938223071ba360706 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:31 +1000 Subject: drm/nouveau/fifo: add chan bind()/unbind() - stops programming (non-existent) runl id field on bind(), from maxwell Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 3 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 15 +--------- .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.c | 6 ++-- .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 13 ++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 35 ++++++++++++++++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 28 +++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 2 ++ .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 7 ----- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 6 ---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 19 ++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 4 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 6 ++++ 17 files changed, 115 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index bf1c3b580def..fe398ed544cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -16,6 +16,9 @@ struct nvkm_cctx { }; struct nvkm_chan_func { + void (*bind)(struct nvkm_chan *); + void (*unbind)(struct nvkm_chan *); + void *(*dtor)(struct nvkm_fifo_chan *); void (*init)(struct nvkm_fifo_chan *); void (*fini)(struct nvkm_fifo_chan *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 903b54c07750..100631a44a85 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -166,23 +166,10 @@ g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context); } -static void -g84_fifo_chan_init(struct nvkm_fifo_chan *base) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - struct nv50_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u64 addr = chan->ramfc->addr >> 8; - u32 chid = chan->base.chid; - - nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr); - nv50_fifo_runlist_update(fifo); -} - static const struct nvkm_fifo_chan_func g84_fifo_chan_func = { .dtor = nv50_fifo_chan_dtor, - .init = g84_fifo_chan_init, + .init = nv50_fifo_chan_init, .fini = nv50_fifo_chan_fini, .engine_ctor = g84_fifo_chan_engine_ctor, .engine_dtor = nv50_fifo_chan_engine_dtor, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c index c44d7c81dd52..0fc97c4c341a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c @@ -194,19 +194,17 @@ nv50_fifo_chan_fini(struct nvkm_fifo_chan *base) /* remove channel from runlist, fifo will unload context */ nvkm_mask(device, 0x002600 + (chid * 4), 0x80000000, 0x00000000); nv50_fifo_runlist_update(fifo); - nvkm_wr32(device, 0x002600 + (chid * 4), 0x00000000); } -static void +void nv50_fifo_chan_init(struct nvkm_fifo_chan *base) { struct nv50_fifo_chan *chan = nv50_fifo_chan(base); struct nv50_fifo *fifo = chan->fifo; struct nvkm_device *device = fifo->base.engine.subdev.device; - u64 addr = chan->ramfc->addr >> 12; u32 chid = chan->base.chid; - nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr); + nvkm_mask(device, 0x002600 + (chid * 4), 0x80000000, 0x80000000); nv50_fifo_runlist_update(fifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h index 3a95730d7ff5..5d5d9f3d9928 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h @@ -40,6 +40,7 @@ struct nv50_fifo_chan { int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, const struct nvkm_oclass *, struct nv50_fifo_chan *); void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); +void nv50_fifo_chan_init(struct nvkm_fifo_chan *); void nv50_fifo_chan_fini(struct nvkm_fifo_chan *); struct nvkm_gpuobj **nv50_fifo_chan_engine(struct nv50_fifo_chan *, struct nvkm_engine *); void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index afaa2dea4ef8..2777f03ffc29 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -21,16 +21,29 @@ * * Authors: Ben Skeggs */ +#include "cgrp.h" #include "chan.h" #include "runl.h" +#include + #include "nv50.h" #include "channv50.h" #include +static void +g84_chan_bind(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_wr32(device, 0x002600 + (chan->id * 4), nv50_fifo_chan(chan)->ramfc->addr >> 8); +} + const struct nvkm_chan_func g84_chan = { + .bind = g84_chan_bind, + .unbind = nv50_chan_unbind, }; const struct nvkm_engn_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index fcfc241c8a99..50109f4f3860 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" @@ -38,8 +39,32 @@ #include +static void gf100_fifo_intr_engine(struct nvkm_fifo *); + +static void +gf100_chan_unbind(struct nvkm_chan *chan) +{ + struct nvkm_fifo *fifo = chan->cgrp->runl->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; + + /*TODO: Is this cargo-culted, or necessary? RM does *something* here... Why? */ + gf100_fifo_intr_engine(fifo); + + nvkm_wr32(device, 0x003000 + (chan->id * 8), 0x00000000); +} + +static void +gf100_chan_bind(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_wr32(device, 0x003000 + (chan->id * 8), 0xc0000000 | chan->inst->addr >> 12); +} + static const struct nvkm_chan_func gf100_chan = { + .bind = gf100_chan_bind, + .unbind = gf100_chan_unbind, }; static const struct nvkm_engn_func @@ -619,15 +644,15 @@ gf100_fifo_intr_engine_unit(struct nvkm_fifo *fifo, int engn) } } -void -gf100_fifo_intr_engine(struct gf100_fifo *fifo) +static void +gf100_fifo_intr_engine(struct nvkm_fifo *fifo) { - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; u32 mask = nvkm_rd32(device, 0x0025a4); while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_engine_unit(&fifo->base, unit); + gf100_fifo_intr_engine_unit(fifo, unit); mask &= ~(1 << unit); } } @@ -684,7 +709,7 @@ gf100_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x80000000) { - gf100_fifo_intr_engine(gf100_fifo(fifo)); + gf100_fifo_intr_engine(fifo); stat &= ~0x80000000; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h index 8e0c1a5e3c57..16268e81077d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -28,7 +28,6 @@ struct gf100_fifo { } user; }; -void gf100_fifo_intr_engine(struct gf100_fifo *); void gf100_fifo_runlist_insert(struct gf100_fifo *, struct gf100_fifo_chan *); void gf100_fifo_runlist_remove(struct gf100_fifo *, struct gf100_fifo_chan *); void gf100_fifo_runlist_commit(struct gf100_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 12aebf83f090..fafe9453ab0c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -38,8 +38,36 @@ #include +void +gk104_chan_unbind(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_wr32(device, 0x800000 + (chan->id * 8), 0x00000000); +} + +void +gk104_chan_bind_inst(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_wr32(device, 0x800000 + (chan->id * 8), 0x80000000 | chan->inst->addr >> 12); +} + +void +gk104_chan_bind(struct nvkm_chan *chan) +{ + struct nvkm_runl *runl = chan->cgrp->runl; + struct nvkm_device *device = runl->fifo->engine.subdev.device; + + nvkm_mask(device, 0x800004 + (chan->id * 8), 0x000f0000, runl->id << 16); + gk104_chan_bind_inst(chan); +} + static const struct nvkm_chan_func gk104_chan = { + .bind = gk104_chan_bind, + .unbind = gk104_chan_unbind, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 134de3c71ad5..1724937a2f5f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -35,6 +35,8 @@ const struct nvkm_chan_func gk110_chan = { + .bind = gk104_chan_bind, + .unbind = gk104_chan_unbind, }; const struct nvkm_cgrp_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index d3b2aa701f53..742404bf8415 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -34,6 +34,8 @@ const struct nvkm_chan_func gm107_chan = { + .bind = gk104_chan_bind_inst, + .unbind = gk104_chan_unbind, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 5d6e3a7b8f1e..93739b34bfcd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -157,10 +157,6 @@ gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000); gf100_fifo_runlist_commit(fifo); } - - gf100_fifo_intr_engine(fifo); - - nvkm_wr32(device, 0x003000 + coff, 0x00000000); } static void @@ -169,11 +165,8 @@ gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base) struct gf100_fifo_chan *chan = gf100_fifo_chan(base); struct gf100_fifo *fifo = chan->fifo; struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 addr = chan->base.inst->addr >> 12; u32 coff = chan->base.chid * 8; - nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr); - if (list_empty(&chan->head) && !chan->killed) { gf100_fifo_runlist_insert(fifo, chan); nvkm_wr32(device, 0x003004 + coff, 0x001f0001); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index 6415e80a1fbf..c2b5eaa9cdea 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -208,8 +208,6 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) gk104_fifo_gpfifo_kick(chan); gk104_fifo_runlist_update(fifo, chan->runl); } - - nvkm_wr32(device, 0x800000 + coff, 0x00000000); } void @@ -218,12 +216,8 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) struct gk104_fifo_chan *chan = gk104_fifo_chan(base); struct gk104_fifo *fifo = chan->fifo; struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 addr = chan->base.inst->addr >> 12; u32 coff = chan->base.chid * 8; - nvkm_mask(device, 0x800004 + coff, 0x000f0000, chan->runl << 16); - nvkm_wr32(device, 0x800000 + coff, 0x80000000 | addr); - if (list_empty(&chan->head) && !chan->killed) { gk104_fifo_runlist_insert(fifo, chan); nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index c147c26b80ca..eb59527544b2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -33,6 +33,8 @@ static const struct nvkm_chan_func gv100_chan = { + .bind = gk104_chan_bind_inst, + .unbind = gk104_chan_unbind, }; const struct nvkm_engn_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 16e59d8ea325..d7adb057e4ca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" @@ -33,8 +34,26 @@ #include +void +nv50_chan_unbind(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_wr32(device, 0x002600 + (chan->id * 4), 0x00000000); +} + +static void +nv50_chan_bind(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_wr32(device, 0x002600 + (chan->id * 4), nv50_fifo_chan(chan)->ramfc->addr >> 12); +} + static const struct nvkm_chan_func nv50_chan = { + .bind = nv50_chan_bind, + .unbind = nv50_chan_unbind, }; static const struct nvkm_engn_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 16fe77ee4c86..f023aa0a559e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -103,6 +103,7 @@ int nv50_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_runl_func nv50_runl; int nv50_runl_wait(struct nvkm_runl *); extern const struct nvkm_engn_func nv50_engn_sw; +void nv50_chan_unbind(struct nvkm_chan *); extern const struct nvkm_event_func g84_fifo_nonstall; extern const struct nvkm_engn_func g84_engn; @@ -142,6 +143,9 @@ bool gk104_runq_intr(struct nvkm_runq *, struct nvkm_runl *); extern const struct nvkm_bitfield gk104_runq_intr_0_names[]; extern const struct nvkm_engn_func gk104_engn; extern const struct nvkm_engn_func gk104_engn_ce; +void gk104_chan_bind(struct nvkm_chan *); +void gk104_chan_bind_inst(struct nvkm_chan *); +void gk104_chan_unbind(struct nvkm_chan *); int gk110_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_runl_func gk110_runl; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 7d3c9d8e54a7..b23fc330aa6c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -33,6 +33,8 @@ static const struct nvkm_chan_func tu102_chan = { + .bind = gk104_chan_bind_inst, + .unbind = gk104_chan_unbind, }; static bool diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index 8681ff045887..c1d2035e00cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -217,6 +217,9 @@ nvkm_uchan_fini(struct nvkm_object *object, bool suspend) if (ret && suspend) return ret; + if (chan->func->unbind) + chan->func->unbind(chan); + return 0; } @@ -225,6 +228,9 @@ nvkm_uchan_init(struct nvkm_object *object) { struct nvkm_chan *chan = nvkm_uchan(object)->chan; + if (chan->func->bind) + chan->func->bind(chan); + return chan->object.func->init(&chan->object); } -- cgit v1.2.3 From 67059b9fb8997f3d4515d72052c331503b00274b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:32 +1000 Subject: drm/nouveau/fifo: add chan start()/stop() - nvkm_chan_error() built on top, stops channel and sends 'killed' event - removes an odd double-bashing of channel enable regs on kepler and up - pokes doorbell on turing and up, after enabling channel Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 7 ++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 13 +--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 73 +++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 7 ++- .../gpu/drm/nouveau/nvkm/engine/fifo/channv04.h | 2 - .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.c | 7 --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 22 ++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 24 +++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 2 + .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 6 -- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 7 --- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 9 +-- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c | 8 --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 9 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 27 ++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 18 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 7 ++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 25 ++++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 11 +++- 27 files changed, 191 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index a4cc7f07bb89..798fbd3b530c 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -20,6 +20,10 @@ struct nvkm_chan { union { int id; int chid; }; /*FIXME: remove later */ + spinlock_t lock; + atomic_t blocked; + atomic_t errored; + struct list_head cctxs; struct nvkm_fifo *fifo; @@ -62,9 +66,6 @@ struct nvkm_fifo { struct list_head chan; spinlock_t lock; struct mutex mutex; - -#define NVKM_FIFO_EVENT_KILLED BIT(0) - struct nvkm_event kevent; /* channel killed */ }; void nvkm_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index e08d8d14a19a..549e4b1fcbe1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -62,16 +62,6 @@ nvkm_fifo_fault(struct nvkm_fifo *fifo, struct nvkm_fault_data *info) return fifo->func->mmu_fault->recover(fifo, info); } -void -nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid) -{ - nvkm_event_ntfy(&fifo->kevent, chid, NVKM_FIFO_EVENT_KILLED); -} - -static const struct nvkm_event_func -nvkm_fifo_kevent_func = { -}; - static int nvkm_fifo_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) @@ -293,7 +283,6 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) if (fifo->func->dtor) data = fifo->func->dtor(fifo); - nvkm_event_fini(&fifo->kevent); nvkm_event_fini(&fifo->nonstall.event); mutex_destroy(&fifo->mutex); return data; @@ -343,5 +332,5 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, return ret; } - return nvkm_event_init(&nvkm_fifo_kevent_func, &fifo->engine.subdev, 1, nr, &fifo->kevent); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 748f3f199b9f..4f11448ed720 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -24,6 +24,7 @@ #include "chan.h" #include "chid.h" #include "cgrp.h" +#include "chid.h" #include "runl.h" #include "priv.h" @@ -219,6 +220,8 @@ nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct n */ if (cgrp->hw) nvkm_runl_block(runl); + else + nvkm_chan_block(chan); /* Update context pointer. */ if (cctx) @@ -229,6 +232,8 @@ nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct n /* Resume normal operation. */ if (cgrp->hw) nvkm_runl_allow(runl); + else + nvkm_chan_allow(chan); } void @@ -295,23 +300,6 @@ done: return ret; } -static int -nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) -{ - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - union nvif_chan_event_args *args = argv; - - switch (args->v0.type) { - case NVIF_CHAN_EVENT_V0_KILLED: - return nvkm_uevent_add(uevent, &chan->fifo->kevent, chan->chid, - NVKM_FIFO_EVENT_KILLED, NULL); - default: - break; - } - - return -ENOSYS; -} - static int nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc, enum nvkm_object_map *type, u64 *addr, u64 *size) @@ -327,7 +315,8 @@ static int nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend) { struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - chan->func->fini(chan); + if (chan->func->fini) + chan->func->fini(chan); return 0; } @@ -335,10 +324,51 @@ static int nvkm_fifo_chan_init(struct nvkm_object *object) { struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - chan->func->init(chan); + if (chan->func->init) + chan->func->init(chan); return 0; } +static void +nvkm_chan_block_locked(struct nvkm_chan *chan) +{ + CHAN_TRACE(chan, "block %d", atomic_read(&chan->blocked)); + if (atomic_inc_return(&chan->blocked) == 1) + chan->func->stop(chan); +} + +void +nvkm_chan_error(struct nvkm_chan *chan, bool preempt) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (atomic_inc_return(&chan->errored) == 1) { + CHAN_ERROR(chan, "errored - disabling channel"); + nvkm_chan_block_locked(chan); + nvkm_event_ntfy(&chan->cgrp->runl->chid->event, chan->id, NVKM_CHAN_EVENT_ERRORED); + } + spin_unlock_irqrestore(&chan->lock, flags); +} + +void +nvkm_chan_block(struct nvkm_chan *chan) +{ + spin_lock_irq(&chan->lock); + nvkm_chan_block_locked(chan); + spin_unlock_irq(&chan->lock); +} + +void +nvkm_chan_allow(struct nvkm_chan *chan) +{ + spin_lock_irq(&chan->lock); + CHAN_TRACE(chan, "allow %d", atomic_read(&chan->blocked)); + if (atomic_dec_and_test(&chan->blocked)) + chan->func->start(chan); + spin_unlock_irq(&chan->lock); +} + void nvkm_chan_del(struct nvkm_chan **pchan) { @@ -437,7 +467,6 @@ nvkm_fifo_chan_func = { .init = nvkm_fifo_chan_init, .fini = nvkm_fifo_chan_fini, .map = nvkm_fifo_chan_map, - .uevent = nvkm_fifo_chan_uevent, }; int @@ -481,10 +510,12 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, func->engine_fini = fn->engine_fini; func->object_ctor = fn->object_ctor; func->object_dtor = fn->object_dtor; - func->submit_token = fn->submit_token; chan->func = func; chan->id = -1; + spin_lock_init(&chan->lock); + atomic_set(&chan->blocked, 1); + atomic_set(&chan->errored, 0); nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); chan->fifo = fifo; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index fe398ed544cf..d573d9fdb4d8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -18,6 +18,9 @@ struct nvkm_cctx { struct nvkm_chan_func { void (*bind)(struct nvkm_chan *); void (*unbind)(struct nvkm_chan *); + void (*start)(struct nvkm_chan *); + void (*stop)(struct nvkm_chan *); + u32 (*doorbell_handle)(struct nvkm_chan *); void *(*dtor)(struct nvkm_fifo_chan *); void (*init)(struct nvkm_fifo_chan *); @@ -30,7 +33,6 @@ struct nvkm_chan_func { bool suspend); int (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *); void (*object_dtor)(struct nvkm_fifo_chan *, int); - u32 (*submit_token)(struct nvkm_fifo_chan *); }; int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, @@ -38,6 +40,9 @@ int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, u32 engm, int bar, u32 base, u32 user, const struct nvkm_oclass *, struct nvkm_fifo_chan *); void nvkm_chan_del(struct nvkm_chan **); +void nvkm_chan_allow(struct nvkm_chan *); +void nvkm_chan_block(struct nvkm_chan *); +void nvkm_chan_error(struct nvkm_chan *, bool preempt); int nvkm_chan_cctx_get(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx **, struct nvkm_client * /*TODO: remove need for this */); void nvkm_chan_cctx_put(struct nvkm_chan *, struct nvkm_cctx **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h index 727bc8976b40..837f9f7f69ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h @@ -18,8 +18,6 @@ struct nv04_fifo_chan { extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func; void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *); -void nv04_fifo_dma_init(struct nvkm_fifo_chan *); -void nv04_fifo_dma_fini(struct nvkm_fifo_chan *); void nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *, int); extern const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c index 0fc97c4c341a..7669d17406c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c @@ -188,11 +188,7 @@ nv50_fifo_chan_fini(struct nvkm_fifo_chan *base) { struct nv50_fifo_chan *chan = nv50_fifo_chan(base); struct nv50_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 chid = chan->base.chid; - /* remove channel from runlist, fifo will unload context */ - nvkm_mask(device, 0x002600 + (chid * 4), 0x80000000, 0x00000000); nv50_fifo_runlist_update(fifo); } @@ -201,10 +197,7 @@ nv50_fifo_chan_init(struct nvkm_fifo_chan *base) { struct nv50_fifo_chan *chan = nv50_fifo_chan(base); struct nv50_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 chid = chan->base.chid; - nvkm_mask(device, 0x002600 + (chid * 4), 0x80000000, 0x80000000); nv50_fifo_runlist_update(fifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c index ed2ae9e69987..d515cf08fc3b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c @@ -88,8 +88,6 @@ nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base) const struct nvkm_fifo_chan_func nv04_fifo_dma_func = { .dtor = nv04_fifo_dma_dtor, - .init = nv04_fifo_dma_init, - .fini = nv04_fifo_dma_fini, .object_ctor = nv04_fifo_dma_object_ctor, .object_dtor = nv04_fifo_dma_object_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c index c42c2e01d801..2f0dceaf3b01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c @@ -176,8 +176,6 @@ nv40_fifo_dma_object_ctor(struct nvkm_fifo_chan *base, static const struct nvkm_fifo_chan_func nv40_fifo_dma_func = { .dtor = nv04_fifo_dma_dtor, - .init = nv04_fifo_dma_init, - .fini = nv04_fifo_dma_fini, .engine_ctor = nv40_fifo_dma_engine_ctor, .engine_dtor = nv40_fifo_dma_engine_dtor, .engine_init = nv40_fifo_dma_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 2777f03ffc29..91b43f17120b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -44,6 +44,8 @@ const struct nvkm_chan_func g84_chan = { .bind = g84_chan_bind, .unbind = nv50_chan_unbind, + .start = nv50_chan_start, + .stop = nv50_chan_stop, }; const struct nvkm_engn_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 50109f4f3860..e47ca113e9e8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -39,6 +39,22 @@ #include +static void +gf100_chan_stop(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_mask(device, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000); +} + +static void +gf100_chan_start(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_wr32(device, 0x003004 + (chan->id * 8), 0x001f0001); +} + static void gf100_fifo_intr_engine(struct nvkm_fifo *); static void @@ -65,6 +81,8 @@ static const struct nvkm_chan_func gf100_chan = { .bind = gf100_chan_bind, .unbind = gf100_chan_unbind, + .start = gf100_chan_start, + .stop = gf100_chan_stop, }; static const struct nvkm_engn_func @@ -321,7 +339,6 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, struct gf100_fifo_chan *chan) { struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; u32 chid = chan->base.chid; int engi = gf100_fifo_engine_id(&fifo->base, engine); @@ -329,14 +346,13 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, engine->subdev.name, chid); assert_spin_locked(&fifo->base.lock); - nvkm_mask(device, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000); + nvkm_chan_error(&chan->base, false); list_del_init(&chan->head); chan->killed = true; if (engi >= 0 && engi != GF100_FIFO_ENGN_SW) fifo->recover.mask |= BIT(engi); schedule_work(&fifo->recover.work); - nvkm_fifo_kevent(&fifo->base, chid); } static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index fafe9453ab0c..5ba922cf3c2c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -38,6 +38,22 @@ #include +void +gk104_chan_stop(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_mask(device, 0x800004 + (chan->id * 8), 0x00000800, 0x00000800); +} + +void +gk104_chan_start(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_mask(device, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); +} + void gk104_chan_unbind(struct nvkm_chan *chan) { @@ -68,6 +84,8 @@ static const struct nvkm_chan_func gk104_chan = { .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, + .start = gk104_chan_start, + .stop = gk104_chan_stop, }; void @@ -469,13 +487,9 @@ gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid) chan = gk104_fifo_recover_chid(fifo, runl, chid); if (chan) { chan->killed = true; - nvkm_fifo_kevent(&fifo->base, chid); + nvkm_chan_error(&chan->base, false); } - /* Disable channel. */ - nvkm_wr32(device, 0x800004 + (chid * 0x08), stat | 0x00000800); - nvkm_warn(subdev, "channel %d: killed\n", chid); - /* Block channel assignments from changing during recovery. */ gk104_fifo_recover_runl(fifo, runl); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 1724937a2f5f..3582b9f55611 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -37,6 +37,8 @@ const struct nvkm_chan_func gk110_chan = { .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, + .start = gk104_chan_start, + .stop = gk104_chan_stop, }; const struct nvkm_cgrp_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 742404bf8415..2924ce10c337 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -36,6 +36,8 @@ const struct nvkm_chan_func gm107_chan = { .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, + .start = gk104_chan_start, + .stop = gk104_chan_stop, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 93739b34bfcd..29783d271f1e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -149,12 +149,9 @@ gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) { struct gf100_fifo_chan *chan = gf100_fifo_chan(base); struct gf100_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 coff = chan->base.chid * 8; if (!list_empty(&chan->head) && !chan->killed) { gf100_fifo_runlist_remove(fifo, chan); - nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000); gf100_fifo_runlist_commit(fifo); } } @@ -164,12 +161,9 @@ gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base) { struct gf100_fifo_chan *chan = gf100_fifo_chan(base); struct gf100_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 coff = chan->base.chid * 8; if (list_empty(&chan->head) && !chan->killed) { gf100_fifo_runlist_insert(fifo, chan); - nvkm_wr32(device, 0x003004 + coff, 0x001f0001); gf100_fifo_runlist_commit(fifo); } } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index c2b5eaa9cdea..1847b1b7af8b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -199,12 +199,9 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) { struct gk104_fifo_chan *chan = gk104_fifo_chan(base); struct gk104_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 coff = chan->base.chid * 8; if (!list_empty(&chan->head)) { gk104_fifo_runlist_remove(fifo, chan); - nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800); gk104_fifo_gpfifo_kick(chan); gk104_fifo_runlist_update(fifo, chan->runl); } @@ -215,14 +212,10 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) { struct gk104_fifo_chan *chan = gk104_fifo_chan(base); struct gk104_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 coff = chan->base.chid * 8; if (list_empty(&chan->head) && !chan->killed) { gk104_fifo_runlist_insert(fifo, chan); - nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400); gk104_fifo_runlist_update(fifo, chan->runl); - nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400); } } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 6e74fdc0dc24..a901ce269e06 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -28,12 +28,6 @@ #include #include -static u32 -gv100_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *chan) -{ - return chan->chid; -} - static int gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid) { @@ -125,7 +119,6 @@ gv100_fifo_gpfifo = { .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gv100_fifo_gpfifo_engine_init, .engine_fini = gv100_fifo_gpfifo_engine_fini, - .submit_token = gv100_fifo_gpfifo_submit_token, }; int @@ -159,7 +152,7 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, *chid = chan->base.chid; *inst = chan->base.inst->addr; - *token = chan->base.func->submit_token(&chan->base); + *token = chan->base.func->doorbell_handle(&chan->base); /* Hack to support GPUs where even individual channels should be * part of a channel group. diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c index 4d35bee0ab54..1c48a109a2b8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c @@ -28,13 +28,6 @@ #include #include -static u32 -tu102_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *base) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - return (chan->runl << 16) | chan->base.chid; -} - static const struct nvkm_fifo_chan_func tu102_fifo_gpfifo = { .dtor = gk104_fifo_gpfifo_dtor, @@ -44,7 +37,6 @@ tu102_fifo_gpfifo = { .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gv100_fifo_gpfifo_engine_init, .engine_fini = gv100_fifo_gpfifo_engine_fini, - .submit_token = tu102_fifo_gpfifo_submit_token, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index eb59527544b2..0e9e070201b1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -31,10 +31,19 @@ #include +static u32 +gv100_chan_doorbell_handle(struct nvkm_chan *chan) +{ + return chan->id; +} + static const struct nvkm_chan_func gv100_chan = { .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, + .start = gk104_chan_start, + .stop = gk104_chan_stop, + .doorbell_handle = gv100_chan_doorbell_handle, }; const struct nvkm_engn_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 446e65dcb036..a0a28a81f7f4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -52,15 +52,14 @@ nv04_fifo_ramfc[] = { }; void -nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) +nv04_chan_stop(struct nvkm_chan *chan) { - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nv04_fifo *fifo = chan->fifo; + struct nv04_fifo *fifo = nv04_fifo(chan->cgrp->runl->fifo); struct nvkm_device *device = fifo->base.engine.subdev.device; struct nvkm_memory *fctx = device->imem->ramfc; const struct nv04_fifo_ramfc *c; unsigned long flags; - u32 data = chan->ramfc; + u32 data = nv04_fifo_chan(chan)->ramfc; u32 chid; /* prevent fifo context switches */ @@ -69,7 +68,7 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) /* if this channel is active, replace it with a null context */ chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.chid->mask; - if (chid == chan->base.chid) { + if (chid == chan->id) { nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0); nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); @@ -98,26 +97,26 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) } /* restore normal operation, after disabling dma mode */ - nvkm_mask(device, NV04_PFIFO_MODE, 1 << chan->base.chid, 0); + nvkm_mask(device, NV04_PFIFO_MODE, BIT(chan->id), 0); nvkm_wr32(device, NV03_PFIFO_CACHES, 1); spin_unlock_irqrestore(&fifo->base.lock, flags); } void -nv04_fifo_dma_init(struct nvkm_fifo_chan *base) +nv04_chan_start(struct nvkm_chan *chan) { - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nv04_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - u32 mask = 1 << chan->base.chid; + struct nvkm_fifo *fifo = chan->cgrp->runl->fifo; unsigned long flags; - spin_lock_irqsave(&fifo->base.lock, flags); - nvkm_mask(device, NV04_PFIFO_MODE, mask, mask); - spin_unlock_irqrestore(&fifo->base.lock, flags); + + spin_lock_irqsave(&fifo->lock, flags); + nvkm_mask(fifo->engine.subdev.device, NV04_PFIFO_MODE, BIT(chan->id), BIT(chan->id)); + spin_unlock_irqrestore(&fifo->lock, flags); } static const struct nvkm_chan_func nv04_chan = { + .start = nv04_chan_start, + .stop = nv04_chan_stop, }; const struct nvkm_cgrp_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index 0f7c88ae5a1c..8d302cb8ba8c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -45,6 +45,8 @@ nv10_fifo_ramfc[] = { static const struct nvkm_chan_func nv10_chan = { + .start = nv04_chan_start, + .stop = nv04_chan_stop, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index 59b752986ac1..7b1b90d285c1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -54,6 +54,8 @@ nv17_fifo_ramfc[] = { static const struct nvkm_chan_func nv17_chan = { + .start = nv04_chan_start, + .stop = nv04_chan_stop, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index d0fc6c528825..19f7c0407e70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -64,6 +64,8 @@ nv40_fifo_ramfc[] = { static const struct nvkm_chan_func nv40_chan = { + .start = nv04_chan_start, + .stop = nv04_chan_stop, }; static const struct nvkm_engn_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index d7adb057e4ca..38d36749862c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -34,6 +34,22 @@ #include +void +nv50_chan_stop(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_mask(device, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); +} + +void +nv50_chan_start(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + nvkm_mask(device, 0x002600 + (chan->id * 4), 0x80000000, 0x80000000); +} + void nv50_chan_unbind(struct nvkm_chan *chan) { @@ -54,6 +70,8 @@ static const struct nvkm_chan_func nv50_chan = { .bind = nv50_chan_bind, .unbind = nv50_chan_unbind, + .start = nv50_chan_start, + .stop = nv50_chan_stop, }; static const struct nvkm_engn_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index f023aa0a559e..d9de5ab26452 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -11,7 +11,6 @@ struct nvkm_runq; struct gk104_fifo; struct gk104_fifo_chan; -void nvkm_fifo_kevent(struct nvkm_fifo *, int chid); void nvkm_fifo_recover_chan(struct nvkm_fifo *, int chid); struct nvkm_fifo_chan_oclass; @@ -95,6 +94,8 @@ void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); extern const struct nvkm_runl_func nv04_runl; extern const struct nvkm_engn_func nv04_engn; extern const struct nvkm_cgrp_func nv04_cgrp; +void nv04_chan_start(struct nvkm_chan *); +void nv04_chan_stop(struct nvkm_chan *); int nv10_fifo_chid_nr(struct nvkm_fifo *); @@ -104,6 +105,8 @@ extern const struct nvkm_runl_func nv50_runl; int nv50_runl_wait(struct nvkm_runl *); extern const struct nvkm_engn_func nv50_engn_sw; void nv50_chan_unbind(struct nvkm_chan *); +void nv50_chan_start(struct nvkm_chan *); +void nv50_chan_stop(struct nvkm_chan *); extern const struct nvkm_event_func g84_fifo_nonstall; extern const struct nvkm_engn_func g84_engn; @@ -146,6 +149,8 @@ extern const struct nvkm_engn_func gk104_engn_ce; void gk104_chan_bind(struct nvkm_chan *); void gk104_chan_bind_inst(struct nvkm_chan *); void gk104_chan_unbind(struct nvkm_chan *); +void gk104_chan_start(struct nvkm_chan *); +void gk104_chan_stop(struct nvkm_chan *); int gk110_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_runl_func gk110_runl; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index aebd8a750d38..35dce7c83124 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -34,6 +34,7 @@ struct nvkm_runl { u32 addr; struct nvkm_chid *cgid; +#define NVKM_CHAN_EVENT_ERRORED BIT(0) struct nvkm_chid *chid; struct list_head engns; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index b23fc330aa6c..4ae8544a22cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -28,13 +28,32 @@ #include #include +#include #include +static u32 +tu102_chan_doorbell_handle(struct nvkm_chan *chan) +{ + return (chan->cgrp->runl->id << 16) | chan->id; +} + +static void +tu102_chan_start(struct nvkm_chan *chan) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + + gk104_chan_start(chan); + nvkm_wr32(device, device->vfn->addr.user + 0x0090, chan->func->doorbell_handle(chan)); +} + static const struct nvkm_chan_func tu102_chan = { .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, + .start = tu102_chan_start, + .stop = gk104_chan_stop, + .doorbell_handle = tu102_chan_doorbell_handle, }; static bool @@ -202,13 +221,9 @@ tu102_fifo_recover_chan(struct nvkm_fifo *base, int chid) chan = tu102_fifo_recover_chid(fifo, runl, chid); if (chan) { chan->killed = true; - nvkm_fifo_kevent(&fifo->base, chid); + nvkm_chan_error(&chan->base, false); } - /* Disable channel. */ - nvkm_wr32(device, 0x800004 + (chid * 0x08), stat | 0x00000800); - nvkm_warn(subdev, "channel %d: killed\n", chid); - /* Block channel assignments from changing during recovery. */ tu102_fifo_recover_runl(fifo, runl); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index c1d2035e00cf..096e09f23177 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -22,6 +22,7 @@ #define nvkm_uchan(p) container_of((p), struct nvkm_uchan, object) #include "cgrp.h" #include "chan.h" +#include "chid.h" #include "runl.h" #include @@ -52,7 +53,8 @@ nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_ return nvkm_uevent_add(uevent, &runl->fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT, NULL); case NVIF_CHAN_EVENT_V0_KILLED: - return chan->object.func->uevent(&chan->object, argv, argc, uevent); + return nvkm_uevent_add(uevent, &runl->chid->event, chan->id, + NVKM_CHAN_EVENT_ERRORED, NULL); default: break; } @@ -213,6 +215,8 @@ nvkm_uchan_fini(struct nvkm_object *object, bool suspend) struct nvkm_chan *chan = nvkm_uchan(object)->chan; int ret; + nvkm_chan_block(chan); + ret = chan->object.func->fini(&chan->object, suspend); if (ret && suspend) return ret; @@ -228,9 +232,14 @@ nvkm_uchan_init(struct nvkm_object *object) { struct nvkm_chan *chan = nvkm_uchan(object)->chan; + if (atomic_read(&chan->errored)) + return 0; + if (chan->func->bind) chan->func->bind(chan); + nvkm_chan_allow(chan); + return chan->object.func->init(&chan->object); } -- cgit v1.2.3 From acff941535639a1d244ad9a20dbf3266d39915ed Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:33 +1000 Subject: drm/nouveau/fifo: add chan/cgrp preempt() Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 11 ------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 30 +++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 3 ++ .../gpu/drm/nouveau/nvkm/engine/fifo/changk104.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 14 +++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 23 +++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 1 + .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 17 -------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 45 +--------------------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 12 +----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 6 ++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 12 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 1 + 19 files changed, 102 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 549e4b1fcbe1..1c3c3495a250 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -33,17 +33,6 @@ #include #include -void -nvkm_fifo_recover_chan(struct nvkm_fifo *fifo, int chid) -{ - unsigned long flags; - if (WARN_ON(!fifo->func->recover_chan)) - return; - spin_lock_irqsave(&fifo->lock, flags); - fifo->func->recover_chan(fifo, chid); - spin_unlock_irqrestore(&fifo->lock, flags); -} - void nvkm_fifo_pause(struct nvkm_fifo *fifo, unsigned long *flags) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h index 50ba7c7ee0a8..1440c72ad7dd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h @@ -22,6 +22,7 @@ struct nvkm_ectx { struct nvkm_cgrp { const struct nvkm_cgrp_func { + void (*preempt)(struct nvkm_cgrp *); } *func; char name[64]; struct nvkm_runl *runl; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 4f11448ed720..9b8f346d52b1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -222,6 +222,7 @@ nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct n nvkm_runl_block(runl); else nvkm_chan_block(chan); + nvkm_chan_preempt(chan, true); /* Update context pointer. */ if (cctx) @@ -300,6 +301,33 @@ done: return ret; } +int +nvkm_chan_preempt_locked(struct nvkm_chan *chan, bool wait) +{ + struct nvkm_runl *runl = chan->cgrp->runl; + + CHAN_TRACE(chan, "preempt"); + chan->func->preempt(chan); + if (!wait) + return 0; + + return nvkm_runl_preempt_wait(runl); +} + +int +nvkm_chan_preempt(struct nvkm_chan *chan, bool wait) +{ + int ret; + + if (!chan->func->preempt) + return 0; + + mutex_lock(&chan->cgrp->runl->mutex); + ret = nvkm_chan_preempt_locked(chan, wait); + mutex_unlock(&chan->cgrp->runl->mutex); + return ret; +} + static int nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc, enum nvkm_object_map *type, u64 *addr, u64 *size) @@ -346,6 +374,8 @@ nvkm_chan_error(struct nvkm_chan *chan, bool preempt) if (atomic_inc_return(&chan->errored) == 1) { CHAN_ERROR(chan, "errored - disabling channel"); nvkm_chan_block_locked(chan); + if (preempt) + chan->func->preempt(chan); nvkm_event_ntfy(&chan->cgrp->runl->chid->event, chan->id, NVKM_CHAN_EVENT_ERRORED); } spin_unlock_irqrestore(&chan->lock, flags); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index d573d9fdb4d8..2ad385914bec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -20,6 +20,7 @@ struct nvkm_chan_func { void (*unbind)(struct nvkm_chan *); void (*start)(struct nvkm_chan *); void (*stop)(struct nvkm_chan *); + void (*preempt)(struct nvkm_chan *); u32 (*doorbell_handle)(struct nvkm_chan *); void *(*dtor)(struct nvkm_fifo_chan *); @@ -43,6 +44,8 @@ void nvkm_chan_del(struct nvkm_chan **); void nvkm_chan_allow(struct nvkm_chan *); void nvkm_chan_block(struct nvkm_chan *); void nvkm_chan_error(struct nvkm_chan *, bool preempt); +int nvkm_chan_preempt(struct nvkm_chan *, bool wait); +int nvkm_chan_preempt_locked(struct nvkm_chan *, bool wait); int nvkm_chan_cctx_get(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx **, struct nvkm_client * /*TODO: remove need for this */); void nvkm_chan_cctx_put(struct nvkm_chan *, struct nvkm_cctx **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h index 9713daee6c76..7a83b8667443 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h @@ -33,8 +33,6 @@ int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *, struct nvkm_engine *, struct nvkm_object *); void gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); -int gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *); -int gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *); int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index e47ca113e9e8..4c3338c4d47a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -39,6 +39,12 @@ #include +void +gf100_chan_preempt(struct nvkm_chan *chan) +{ + nvkm_wr32(chan->cgrp->runl->fifo->engine.subdev.device, 0x002634, chan->id); +} + static void gf100_chan_stop(struct nvkm_chan *chan) { @@ -83,6 +89,7 @@ gf100_chan = { .unbind = gf100_chan_unbind, .start = gf100_chan_start, .stop = gf100_chan_stop, + .preempt = gf100_chan_preempt, }; static const struct nvkm_engn_func @@ -158,6 +165,12 @@ gf100_runq = { .intr_0_names = gf100_runq_intr_0_names, }; +bool +gf100_runl_preempt_pending(struct nvkm_runl *runl) +{ + return nvkm_rd32(runl->fifo->engine.subdev.device, 0x002634) & 0x00100000; +} + static void gf100_runl_allow(struct nvkm_runl *runl, u32 engm) { @@ -238,6 +251,7 @@ gf100_runl = { .pending = gf100_runl_pending, .block = gf100_runl_block, .allow = gf100_runl_allow, + .preempt_pending = gf100_runl_preempt_pending, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 5ba922cf3c2c..bcaa0efc19a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -86,6 +86,7 @@ gk104_chan = { .unbind = gk104_chan_unbind, .start = gk104_chan_start, .stop = gk104_chan_stop, + .preempt = gf100_chan_preempt, }; void @@ -366,6 +367,7 @@ gk104_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .preempt_pending = gf100_runl_preempt_pending, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 3582b9f55611..a88e24ba956d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -30,19 +30,41 @@ #include "changk104.h" #include +#include #include +void +gk110_chan_preempt(struct nvkm_chan *chan) +{ + struct nvkm_cgrp *cgrp = chan->cgrp; + + if (cgrp->hw) { + cgrp->func->preempt(cgrp); + return; + } + + gf100_chan_preempt(chan); +} + const struct nvkm_chan_func gk110_chan = { .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, .start = gk104_chan_start, .stop = gk104_chan_stop, + .preempt = gk110_chan_preempt, }; +static void +gk110_cgrp_preempt(struct nvkm_cgrp *cgrp) +{ + nvkm_wr32(cgrp->runl->fifo->engine.subdev.device, 0x002634, 0x01000000 | cgrp->id); +} + const struct nvkm_cgrp_func gk110_cgrp = { + .preempt = gk110_cgrp_preempt, }; void @@ -68,6 +90,7 @@ gk110_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .preempt_pending = gf100_runl_preempt_pending, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 2924ce10c337..a98ea71df2de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -38,6 +38,7 @@ gm107_chan = { .unbind = gk104_chan_unbind, .start = gk104_chan_start, .stop = gk104_chan_stop, + .preempt = gk110_chan_preempt, }; static void @@ -62,6 +63,7 @@ gm107_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .preempt_pending = gf100_runl_preempt_pending, }; static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 4dd3fb04d7e5..ddac252508fb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -35,6 +35,7 @@ gp100_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .preempt_pending = gf100_runl_preempt_pending, }; static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 29783d271f1e..77a4f2346f04 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -62,26 +62,9 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, { const u32 offset = gf100_fifo_gpfifo_engine_addr(engine); struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - struct nvkm_subdev *subdev = &chan->fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; struct nvkm_gpuobj *inst = chan->base.inst; int ret = 0; - mutex_lock(&chan->fifo->base.mutex); - nvkm_wr32(device, 0x002634, chan->base.chid); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x002634) == chan->base.chid) - break; - ) < 0) { - nvkm_error(subdev, "channel %d [%s] kick timeout\n", - chan->base.chid, chan->base.object.client->name); - ret = -ETIMEDOUT; - } - mutex_unlock(&chan->fifo->base.mutex); - - if (ret && suspend) - return ret; - if (offset) { nvkm_kmap(inst); nvkm_wo32(inst, offset + 0x00, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index 1847b1b7af8b..9440cf57a1b8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -33,43 +33,6 @@ #include #include -int -gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *chan) -{ - struct gk104_fifo *fifo = chan->fifo; - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_client *client = chan->base.object.client; - struct nvkm_fifo_cgrp *cgrp = chan->cgrp; - int ret = 0; - - if (cgrp) - nvkm_wr32(device, 0x002634, cgrp->id | 0x01000000); - else - nvkm_wr32(device, 0x002634, chan->base.chid); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x002634) & 0x00100000)) - break; - ) < 0) { - nvkm_error(subdev, "%s %d [%s] kick timeout\n", - cgrp ? "tsg" : "channel", - cgrp ? cgrp->id : chan->base.chid, client->name); - nvkm_fifo_recover_chan(&fifo->base, chan->base.chid); - ret = -ETIMEDOUT; - } - return ret; -} - -int -gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan) -{ - int ret; - mutex_lock(&chan->base.fifo->mutex); - ret = gk104_fifo_gpfifo_kick_locked(chan); - mutex_unlock(&chan->base.fifo->mutex); - return ret; -} - static u32 gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) { @@ -110,11 +73,6 @@ gk104_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, struct gk104_fifo_chan *chan = gk104_fifo_chan(base); struct nvkm_gpuobj *inst = chan->base.inst; u32 offset = gk104_fifo_gpfifo_engine_addr(engine); - int ret; - - ret = gk104_fifo_gpfifo_kick(chan); - if (ret && suspend) - return ret; if (offset) { nvkm_kmap(inst); @@ -127,7 +85,7 @@ gk104_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, nvkm_done(inst); } - return ret; + return 0; } static int @@ -202,7 +160,6 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) if (!list_empty(&chan->head)) { gk104_fifo_runlist_remove(fifo, chan); - gk104_fifo_gpfifo_kick(chan); gk104_fifo_runlist_update(fifo, chan->runl); } } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index a901ce269e06..66d6079ff210 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -33,23 +33,15 @@ gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid { const u32 mask = ce ? 0x00020000 : 0x00010000; const u32 data = valid ? mask : 0x00000000; - int ret; - - /* Block runlist to prevent the channel from being rescheduled. */ - mutex_lock(&chan->fifo->base.mutex); - /* Preempt the channel. */ - ret = gk104_fifo_gpfifo_kick_locked(chan); - if (ret == 0) { + if (1) { /* Update engine context validity. */ nvkm_kmap(chan->base.inst); nvkm_mo32(chan->base.inst, 0x0ac, mask, data); nvkm_done(chan->base.inst); } - /* Resume runlist. */ - mutex_unlock(&chan->fifo->base.mutex); - return ret; + return 0; } int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 0e9e070201b1..2e61a7b38437 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -43,6 +43,7 @@ gv100_chan = { .unbind = gk104_chan_unbind, .start = gk104_chan_start, .stop = gk104_chan_stop, + .preempt = gk110_chan_preempt, .doorbell_handle = gv100_chan_doorbell_handle, }; @@ -99,6 +100,7 @@ gv100_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .preempt_pending = gf100_runl_preempt_pending, }; const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index d9de5ab26452..1a0d94bb1aaa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -11,8 +11,6 @@ struct nvkm_runq; struct gk104_fifo; struct gk104_fifo_chan; -void nvkm_fifo_recover_chan(struct nvkm_fifo *, int chid); - struct nvkm_fifo_chan_oclass; struct nvkm_fifo_func { void *(*dtor)(struct nvkm_fifo *); @@ -107,6 +105,7 @@ extern const struct nvkm_engn_func nv50_engn_sw; void nv50_chan_unbind(struct nvkm_chan *); void nv50_chan_start(struct nvkm_chan *); void nv50_chan_stop(struct nvkm_chan *); +void nv50_chan_preempt(struct nvkm_chan *); extern const struct nvkm_event_func g84_fifo_nonstall; extern const struct nvkm_engn_func g84_engn; @@ -120,9 +119,11 @@ void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); void gf100_fifo_mmu_fault_recover(struct nvkm_fifo *, struct nvkm_fault_data *); extern const struct nvkm_enum gf100_fifo_mmu_fault_access[]; extern const struct nvkm_event_func gf100_fifo_nonstall; +bool gf100_runl_preempt_pending(struct nvkm_runl *); void gf100_runq_init(struct nvkm_runq *); bool gf100_runq_intr(struct nvkm_runq *, struct nvkm_runl *); extern const struct nvkm_engn_func gf100_engn_sw; +void gf100_chan_preempt(struct nvkm_chan *); int gk104_fifo_chid_nr(struct nvkm_fifo *); int gk104_fifo_runl_ctor(struct nvkm_fifo *); @@ -156,6 +157,7 @@ int gk110_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_runl_func gk110_runl; extern const struct nvkm_cgrp_func gk110_cgrp; extern const struct nvkm_chan_func gk110_chan; +void gk110_chan_preempt(struct nvkm_chan *); extern const struct nvkm_runq_func gk208_runq; void gk208_runq_init(struct nvkm_runq *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 438e884b8100..325c4de1b7d2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -26,6 +26,7 @@ #include "priv.h" #include +#include #include struct nvkm_chan * @@ -73,6 +74,17 @@ nvkm_runl_chan_get_chid(struct nvkm_runl *runl, int id, unsigned long *pirqflags return NULL; } +int +nvkm_runl_preempt_wait(struct nvkm_runl *runl) +{ + return nvkm_msec(runl->fifo->engine.subdev.device, runl->fifo->timeout.chan_msec, + if (!runl->func->preempt_pending(runl)) + break; + + usleep_range(1, 2); + ) < 0 ? -ETIMEDOUT : 0; +} + bool nvkm_runl_update_pending(struct nvkm_runl *runl) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index 35dce7c83124..68d6854e6d0f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -28,6 +28,7 @@ struct nvkm_runl { bool (*pending)(struct nvkm_runl *); void (*block)(struct nvkm_runl *, u32 engm); void (*allow)(struct nvkm_runl *, u32 engm); + bool (*preempt_pending)(struct nvkm_runl *); } *func; struct nvkm_fifo *fifo; int id; @@ -60,6 +61,7 @@ void nvkm_runl_del(struct nvkm_runl *); void nvkm_runl_block(struct nvkm_runl *); void nvkm_runl_allow(struct nvkm_runl *); bool nvkm_runl_update_pending(struct nvkm_runl *); +int nvkm_runl_preempt_wait(struct nvkm_runl *); struct nvkm_chan *nvkm_runl_chan_get_chid(struct nvkm_runl *, int chid, unsigned long *irqflags); struct nvkm_chan *nvkm_runl_chan_get_inst(struct nvkm_runl *, u64 inst, unsigned long *irqflags); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 4ae8544a22cf..641c1ff0aa5d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -53,6 +53,7 @@ tu102_chan = { .unbind = gk104_chan_unbind, .start = tu102_chan_start, .stop = gk104_chan_stop, + .preempt = gk110_chan_preempt, .doorbell_handle = tu102_chan_doorbell_handle, }; @@ -91,6 +92,7 @@ tu102_runl = { .pending = tu102_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .preempt_pending = gf100_runl_preempt_pending, }; static const struct nvkm_enum diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index 096e09f23177..1fe7bd6a9aa8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -216,6 +216,7 @@ nvkm_uchan_fini(struct nvkm_object *object, bool suspend) int ret; nvkm_chan_block(chan); + nvkm_chan_preempt(chan, true); ret = chan->object.func->fini(&chan->object, suspend); if (ret && suspend) -- cgit v1.2.3 From 520db0405e9daed6b96b69149673491d80849fe7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:33 +1000 Subject: drm/nouveau/fifo: kill channel on a selection of PBDMA errors A bunch of these can be handled in such a way that the channel can continue, however, any of these are a pretty decent sign something has gone horribly wrong, and the safest option is to disable the channel. This is a bit of a hack, we will want to handle these individually and dump relevant debug info for each at some point. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 4c3338c4d47a..ff28b5a4c36f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -30,7 +30,6 @@ #include "gf100.h" #include "changf100.h" -#include #include #include #include @@ -138,8 +137,9 @@ gf100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null) nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] " "subc %d mthd %04x data %08x\n", runq->id, show, msg, chid, chan ? chan->inst->addr : 0, - chan ? chan->object.client->name : "unknown", - subc, mthd, data); + chan ? chan->name : "unknown", subc, mthd, data); + if ((stat & 0xc67fe000) && chan) + nvkm_chan_error(chan, true); nvkm_chan_put(&chan, flags); } -- cgit v1.2.3 From 0b1bb1296f288bb7164d143ca82dc958f87cbff6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:33 +1000 Subject: drm/nouveau/fifo: kill channel on NV_PPBDMA_INTR_1_CTXNOTVALID Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 6 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h | 1 + 3 files changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index bcaa0efc19a9..41b265b683cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -164,6 +164,12 @@ gk104_runq_intr_1(struct nvkm_runq *runq) u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & 0xfff; char msg[128]; + if (stat & 0x80000000) { + if (runq->func->intr_1_ctxnotvalid && + runq->func->intr_1_ctxnotvalid(runq, chid)) + stat &= ~0x80000000; + } + if (stat) { nvkm_snprintbf(msg, sizeof(msg), gk104_runq_intr_1_names, stat); nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n", diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 2e61a7b38437..e68f3b7767b0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -55,11 +55,34 @@ const struct nvkm_engn_func gv100_engn_ce = { }; +static bool +gv100_runq_intr_1_ctxnotvalid(struct nvkm_runq *runq, int chid) +{ + struct nvkm_fifo *fifo = runq->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_chan *chan; + unsigned long flags; + + RUNQ_ERROR(runq, "CTXNOTVALID chid:%d", chid); + + chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags); + if (WARN_ON_ONCE(!chan)) + return false; + + nvkm_chan_error(chan, true); + nvkm_chan_put(&chan, flags); + + nvkm_mask(device, 0x0400ac + (runq->id * 0x2000), 0x00030000, 0x00030000); + nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), 0x80000000); + return true; +} + const struct nvkm_runq_func gv100_runq = { .init = gk208_runq_init, .intr = gk104_runq_intr, .intr_0_names = gk104_runq_intr_0_names, + .intr_1_ctxnotvalid = gv100_runq_intr_1_ctxnotvalid, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h index f939d3500cb6..011fbf69bb35 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h @@ -9,6 +9,7 @@ struct nvkm_runq { void (*init)(struct nvkm_runq *); bool (*intr)(struct nvkm_runq *, struct nvkm_runl *); const struct nvkm_bitfield *intr_0_names; + bool (*intr_1_ctxnotvalid)(struct nvkm_runq *, int chid); } *func; struct nvkm_fifo *fifo; int id; -- cgit v1.2.3 From 4d60100a23ec5b98e43277d82e5de53c359cf02c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:34 +1000 Subject: drm/nouveau/fifo: add common channel recovery That sure was fun to untangle. - handled per-runlist, rather than globally - more straight-forward process in general - various potential SW/HW races have been fixed - fixes lockdep issues that were present in >=gk104's prior implementation - volta recovery now actually stands a chance of working - volta/turing waiting for PBDMA idle before engine reset - turing using hw-provided TSG info for CTXSW_TIMEOUT Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c | 13 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h | 11 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 286 +++++++++++-------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 5 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 341 +++++------------------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 23 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 28 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 16 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 185 ++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 18 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 210 +++----------- 19 files changed, 559 insertions(+), 605 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 1c3c3495a250..078a97ab5e37 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -93,11 +93,12 @@ static int nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend) { struct nvkm_fifo *fifo = nvkm_fifo(engine); + struct nvkm_runl *runl; nvkm_inth_block(&fifo->engine.subdev.inth); - if (fifo->func->fini) - fifo->func->fini(fifo); + nvkm_runl_foreach(runl, fifo) + nvkm_runl_fini(runl); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c index ed838609f15d..fd9e6144981e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c @@ -168,6 +168,18 @@ nvkm_cgrp_ref(struct nvkm_cgrp *cgrp) return cgrp; } +void +nvkm_cgrp_put(struct nvkm_cgrp **pcgrp, unsigned long irqflags) +{ + struct nvkm_cgrp *cgrp = *pcgrp; + + if (!cgrp) + return; + + *pcgrp = NULL; + spin_unlock_irqrestore(&cgrp->lock, irqflags); +} + int nvkm_cgrp_new(struct nvkm_runl *runl, const char *name, struct nvkm_vmm *vmm, bool hw, struct nvkm_cgrp **pcgrp) @@ -190,6 +202,7 @@ nvkm_cgrp_new(struct nvkm_runl *runl, const char *name, struct nvkm_vmm *vmm, bo INIT_LIST_HEAD(&cgrp->ectxs); INIT_LIST_HEAD(&cgrp->vctxs); mutex_init(&cgrp->mutex); + atomic_set(&cgrp->rc, NVKM_CGRP_RC_NONE); if (runl->cgid) { cgrp->id = nvkm_chid_get(runl->cgid, cgrp); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h index 1440c72ad7dd..e7ce66fecfd4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h @@ -40,6 +40,11 @@ struct nvkm_cgrp { struct list_head vctxs; struct mutex mutex; +#define NVKM_CGRP_RC_NONE 0 +#define NVKM_CGRP_RC_PENDING 1 +#define NVKM_CGRP_RC_RUNNING 2 + atomic_t rc; + struct list_head head; struct list_head chan; }; @@ -52,6 +57,12 @@ int nvkm_cgrp_vctx_get(struct nvkm_cgrp *, struct nvkm_engn *, struct nvkm_chan struct nvkm_vctx **, struct nvkm_client *); void nvkm_cgrp_vctx_put(struct nvkm_cgrp *, struct nvkm_vctx **); +void nvkm_cgrp_put(struct nvkm_cgrp **, unsigned long irqflags); + +#define nvkm_cgrp_foreach_chan(chan,cgrp) for ((chan) = (cgrp)->chans; (chan); (chan) = NULL) +#define nvkm_cgrp_foreach_chan_safe(chan,ctmp,cgrp) \ + (void)(ctmp); nvkm_cgrp_foreach_chan((chan), (cgrp)) + #define CGRP_PRCLI(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a) #define CGRP_PRINT(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:"f, (c)->id, ##a) #define CGRP_ERROR(c,f,a...) CGRP_PRCLI((c), ERROR, err, " "f"\n", ##a) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index ff28b5a4c36f..4fc9e80b5f69 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -91,8 +91,98 @@ gf100_chan = { .preempt = gf100_chan_preempt, }; +bool +gf100_engn_mmu_fault_triggered(struct nvkm_engn *engn) +{ + struct nvkm_runl *runl = engn->runl; + struct nvkm_fifo *fifo = runl->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; + u32 data = nvkm_rd32(device, 0x002a30 + (engn->id * 4)); + + ENGN_DEBUG(engn, "%08x: mmu fault triggered", data); + if (!(data & 0x00000100)) + return false; + + spin_lock(&fifo->lock); + nvkm_mask(device, 0x002a30 + (engn->id * 4), 0x00000100, 0x00000000); + if (atomic_dec_and_test(&runl->rc_triggered)) + nvkm_mask(device, 0x002140, 0x00000100, 0x00000100); + spin_unlock(&fifo->lock); + return true; +} + +void +gf100_engn_mmu_fault_trigger(struct nvkm_engn *engn) +{ + struct nvkm_runl *runl = engn->runl; + struct nvkm_fifo *fifo = runl->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; + + ENGN_DEBUG(engn, "triggering mmu fault on 0x%02x", engn->fault); + spin_lock(&fifo->lock); + if (atomic_inc_return(&runl->rc_triggered) == 1) + nvkm_mask(device, 0x002140, 0x00000100, 0x00000000); + nvkm_wr32(device, 0x002100, 0x00000100); + nvkm_wr32(device, 0x002a30 + (engn->id * 4), 0x00000100 | engn->fault); + spin_unlock(&fifo->lock); +} + +/*TODO: clean all this up. */ +struct gf100_engn_status { + bool busy; + bool save; + bool unk0; + bool unk1; + u8 chid; +}; + +static void +gf100_engn_status(struct nvkm_engn *engn, struct gf100_engn_status *status) +{ + u32 stat = nvkm_rd32(engn->engine->subdev.device, 0x002640 + (engn->id * 4)); + + status->busy = (stat & 0x10000000); + status->save = (stat & 0x00100000); + status->unk0 = (stat & 0x00004000); + status->unk1 = (stat & 0x00001000); + status->chid = (stat & 0x0000007f); + + ENGN_DEBUG(engn, "%08x: busy %d save %d unk0 %d unk1 %d chid %d", + stat, status->busy, status->save, status->unk0, status->unk1, status->chid); +} + +static int +gf100_engn_cxid(struct nvkm_engn *engn, bool *cgid) +{ + struct gf100_engn_status status; + + gf100_engn_status(engn, &status); + if (status.busy) { + *cgid = false; + return status.chid; + } + + return -ENODEV; +} + +static bool +gf100_engn_chsw(struct nvkm_engn *engn) +{ + struct gf100_engn_status status; + + gf100_engn_status(engn, &status); + if (status.busy && (status.unk0 || status.unk1)) + return true; + + return false; +} + static const struct nvkm_engn_func gf100_engn = { + .chsw = gf100_engn_chsw, + .cxid = gf100_engn_cxid, + .mmu_fault_trigger = gf100_engn_mmu_fault_trigger, + .mmu_fault_triggered = gf100_engn_mmu_fault_triggered, }; const struct nvkm_engn_func @@ -138,6 +228,8 @@ gf100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null) "subc %d mthd %04x data %08x\n", runq->id, show, msg, chid, chan ? chan->inst->addr : 0, chan ? chan->name : "unknown", subc, mthd, data); + + /*TODO: use proper procedure for clearing each exception / debug output */ if ((stat & 0xc67fe000) && chan) nvkm_chan_error(chan, true); nvkm_chan_put(&chan, flags); @@ -171,6 +263,12 @@ gf100_runl_preempt_pending(struct nvkm_runl *runl) return nvkm_rd32(runl->fifo->engine.subdev.device, 0x002634) & 0x00100000; } +static void +gf100_runl_fault_clear(struct nvkm_runl *runl) +{ + nvkm_mask(runl->fifo->engine.subdev.device, 0x00262c, 0x00000000, 0x00000000); +} + static void gf100_runl_allow(struct nvkm_runl *runl, u32 engm) { @@ -251,6 +349,7 @@ gf100_runl = { .pending = gf100_runl_pending, .block = gf100_runl_block, .allow = gf100_runl_allow, + .fault_clear = gf100_runl_fault_clear, .preempt_pending = gf100_runl_preempt_pending, }; @@ -282,28 +381,6 @@ gf100_fifo_nonstall = { .fini = gf100_fifo_nonstall_block, }; -static struct nvkm_engine * -gf100_fifo_id_engine(struct nvkm_fifo *fifo, int engi) -{ - enum nvkm_subdev_type type; - int inst; - - switch (engi) { - case GF100_FIFO_ENGN_GR : type = NVKM_ENGINE_GR ; inst = 0; break; - case GF100_FIFO_ENGN_MSPDEC: type = NVKM_ENGINE_MSPDEC; inst = 0; break; - case GF100_FIFO_ENGN_MSPPP : type = NVKM_ENGINE_MSPPP ; inst = 0; break; - case GF100_FIFO_ENGN_MSVLD : type = NVKM_ENGINE_MSVLD ; inst = 0; break; - case GF100_FIFO_ENGN_CE0 : type = NVKM_ENGINE_CE ; inst = 0; break; - case GF100_FIFO_ENGN_CE1 : type = NVKM_ENGINE_CE ; inst = 1; break; - case GF100_FIFO_ENGN_SW : type = NVKM_ENGINE_SW ; inst = 0; break; - default: - WARN_ON(1); - return NULL; - } - - return nvkm_device_engine(fifo->engine.subdev.device, type, inst); -} - static int gf100_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) { @@ -320,62 +397,13 @@ gf100_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) } } -static void -gf100_fifo_recover_work(struct work_struct *w) -{ - struct gf100_fifo *fifo = container_of(w, typeof(*fifo), recover.work); - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_engine *engine; - unsigned long flags; - u32 engm, engn, todo; - - spin_lock_irqsave(&fifo->base.lock, flags); - engm = fifo->recover.mask; - fifo->recover.mask = 0ULL; - spin_unlock_irqrestore(&fifo->base.lock, flags); - - nvkm_mask(device, 0x002630, engm, engm); - - for (todo = engm; engn = __ffs(todo), todo; todo &= ~BIT_ULL(engn)) { - if ((engine = gf100_fifo_id_engine(&fifo->base, engn))) { - nvkm_subdev_fini(&engine->subdev, false); - WARN_ON(nvkm_subdev_init(&engine->subdev)); - } - } - - gf100_fifo_runlist_commit(fifo); - nvkm_wr32(device, 0x00262c, engm); - nvkm_mask(device, 0x002630, engm, 0x00000000); -} - -static void -gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, - struct gf100_fifo_chan *chan) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - u32 chid = chan->base.chid; - int engi = gf100_fifo_engine_id(&fifo->base, engine); - - nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n", - engine->subdev.name, chid); - assert_spin_locked(&fifo->base.lock); - - nvkm_chan_error(&chan->base, false); - list_del_init(&chan->head); - chan->killed = true; - - if (engi >= 0 && engi != GF100_FIFO_ENGN_SW) - fifo->recover.mask |= BIT(engi); - schedule_work(&fifo->recover.work); -} - static const struct nvkm_enum gf100_fifo_mmu_fault_engine[] = { { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR }, { 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB }, { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, { 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM }, - { 0x07, "PFIFO", NULL, NVKM_ENGINE_FIFO }, + { 0x07, "PFIFO" }, { 0x10, "PMSVLD", NULL, NVKM_ENGINE_MSVLD }, { 0x11, "PMSPPP", NULL, NVKM_ENGINE_MSPPP }, { 0x13, "PCOUNTER" }, @@ -452,6 +480,13 @@ gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *inf nvkm_runl_foreach(runl, fifo) { engn = nvkm_runl_find_engn(engn, runl, engn->fault == info->engine); if (engn) { + /* Fault triggered by CTXSW_TIMEOUT recovery procedure. */ + if (engn->func->mmu_fault_triggered && + engn->func->mmu_fault_triggered(engn)) { + nvkm_runl_rc_engn(runl, engn); + return; + } + engine = engn->engine; break; } @@ -496,11 +531,8 @@ gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *inf chan ? chan->id : -1, info->inst, chan ? chan->name : "unknown"); /* Handle host/engine faults. */ - if (fifo->func->recover_chan && chan) - fifo->func->recover_chan(fifo, chan->id); - else - if (engine && chan) - gf100_fifo_recover(gf100_fifo(fifo), engine, (void *)chan); + if (chan) + nvkm_runl_rc_cgrp(chan->cgrp); nvkm_chan_put(&chan, flags); } @@ -515,56 +547,72 @@ gf100_fifo_mmu_fault = { .gpcclient = gf100_fifo_mmu_fault_gpcclient, }; -static const struct nvkm_enum -gf100_fifo_sched_reason[] = { - { 0x0a, "CTXSW_TIMEOUT" }, - {} -}; - -static void -gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo) +void +gf100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo, u32 engm) { - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_engine *engine; - struct gf100_fifo_chan *chan; - unsigned long flags; - u32 engn; - - spin_lock_irqsave(&fifo->base.lock, flags); - for (engn = 0; engn < 6; engn++) { - u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04)); - u32 busy = (stat & 0x80000000); - u32 save = (stat & 0x00100000); /* maybe? */ - u32 unk0 = (stat & 0x00040000); - u32 unk1 = (stat & 0x00001000); - u32 chid = (stat & 0x0000007f); - (void)save; - - if (busy && unk0 && unk1) { - list_for_each_entry(chan, &fifo->chan, head) { - if (chan->base.chid == chid) { - engine = gf100_fifo_id_engine(&fifo->base, engn); - if (!engine) - break; - gf100_fifo_recover(fifo, engine, chan); - break; + struct nvkm_runl *runl; + struct nvkm_engn *engn, *engn2; + bool cgid, cgid2; + int id, id2; + + nvkm_runl_foreach(runl, fifo) { + /* Stop the runlist, and go through all engines serving it. */ + nvkm_runl_block(runl); + nvkm_runl_foreach_engn_cond(engn, runl, engm & BIT(engn->id)) { + /* Determine what channel (group) the engine is on. */ + id = engn->func->cxid(engn, &cgid); + if (id >= 0) { + /* Trigger MMU fault on any engine(s) on that channel (group). */ + nvkm_runl_foreach_engn_cond(engn2, runl, engn2->func->cxid) { + id2 = engn2->func->cxid(engn2, &cgid2); + if (cgid2 == cgid && id2 == id) + engn2->func->mmu_fault_trigger(engn2); } } } + nvkm_runl_allow(runl); /* HW will keep runlist blocked via ERROR_SCHED_DISABLE. */ } - spin_unlock_irqrestore(&fifo->base.lock, flags); } static void -gf100_fifo_intr_sched(struct gf100_fifo *fifo) +gf100_fifo_intr_sched_ctxsw(struct nvkm_fifo *fifo) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_runl *runl; + struct nvkm_engn *engn; + u32 engm = 0; + + /* Look for any engines that are busy, and awaiting chsw ack. */ + nvkm_runl_foreach(runl, fifo) { + nvkm_runl_foreach_engn_cond(engn, runl, engn->func->chsw) { + if (WARN_ON(engn->fault < 0) || !engn->func->chsw(engn)) + continue; + + engm |= BIT(engn->id); + } + } + + if (!engm) + return; + + fifo->func->intr_ctxsw_timeout(fifo, engm); +} + +static const struct nvkm_enum +gf100_fifo_intr_sched_names[] = { + { 0x0a, "CTXSW_TIMEOUT" }, + {} +}; + +void +gf100_fifo_intr_sched(struct nvkm_fifo *fifo) +{ + struct nvkm_subdev *subdev = &fifo->engine.subdev; struct nvkm_device *device = subdev->device; u32 intr = nvkm_rd32(device, 0x00254c); u32 code = intr & 0x000000ff; const struct nvkm_enum *en; - en = nvkm_enum_find(gf100_fifo_sched_reason, code); + en = nvkm_enum_find(gf100_fifo_intr_sched_names, code); nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : ""); @@ -704,7 +752,7 @@ gf100_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x00000100) { - gf100_fifo_intr_sched(gf100_fifo(fifo)); + gf100_fifo_intr_sched(fifo); nvkm_wr32(device, 0x002100, 0x00000100); stat &= ~0x00000100; } @@ -754,13 +802,6 @@ gf100_fifo_intr(struct nvkm_inth *inth) return IRQ_HANDLED; } -static void -gf100_fifo_fini(struct nvkm_fifo *base) -{ - struct gf100_fifo *fifo = gf100_fifo(base); - flush_work(&fifo->recover.work); -} - static void gf100_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) { @@ -888,9 +929,9 @@ gf100_fifo = { .runl_ctor = gf100_fifo_runl_ctor, .init = gf100_fifo_init, .init_pbdmas = gf100_fifo_init_pbdmas, - .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gf100_fifo_mmu_fault, .engine_id = gf100_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, @@ -910,7 +951,6 @@ gf100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) return -ENOMEM; INIT_LIST_HEAD(&fifo->chan); - INIT_WORK(&fifo->recover.work, gf100_fifo_recover_work); *pfifo = &fifo->base; return nvkm_fifo_ctor(&gf100_fifo, device, type, inst, &fifo->base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h index 16268e81077d..6d7771f505c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -12,11 +12,6 @@ struct gf100_fifo { struct list_head chan; - struct { - struct work_struct work; - u64 mask; - } recover; - struct { struct nvkm_memory *mem[2]; int active; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 41b265b683cd..d8cb2626b188 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -89,14 +88,23 @@ gk104_chan = { .preempt = gf100_chan_preempt, }; -void -gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, - struct gk104_fifo_engine_status *status) +/*TODO: clean this up */ +struct gk104_engn_status { + bool busy; + bool faulted; + bool chsw; + bool save; + bool load; + struct { + bool tsg; + u32 id; + } prev, next, *chan; +}; + +static void +gk104_engn_status(struct nvkm_engn *engn, struct gk104_engn_status *status) { - struct nvkm_engine *engine = fifo->engine[engn].engine; - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x08)); + u32 stat = nvkm_rd32(engn->runl->fifo->engine.subdev.device, 0x002640 + (engn->id * 0x08)); status->busy = !!(stat & 0x80000000); status->faulted = !!(stat & 0x40000000); @@ -111,7 +119,7 @@ gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, if (status->busy && status->chsw) { if (status->load && status->save) { - if (engine && nvkm_engine_chsw_load(engine)) + if (nvkm_engine_chsw_load(engn->engine)) status->chan = &status->next; else status->chan = &status->prev; @@ -126,24 +134,64 @@ gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, status->chan = &status->prev; } - nvkm_debug(subdev, "engine %02d: busy %d faulted %d chsw %d " - "save %d load %d %sid %d%s-> %sid %d%s\n", - engn, status->busy, status->faulted, - status->chsw, status->save, status->load, + ENGN_DEBUG(engn, "%08x: busy %d faulted %d chsw %d save %d load %d %sid %d%s-> %sid %d%s", + stat, status->busy, status->faulted, status->chsw, status->save, status->load, status->prev.tsg ? "tsg" : "ch", status->prev.id, status->chan == &status->prev ? "*" : " ", status->next.tsg ? "tsg" : "ch", status->next.id, status->chan == &status->next ? "*" : " "); } +int +gk104_engn_cxid(struct nvkm_engn *engn, bool *cgid) +{ + struct gk104_engn_status status; + + gk104_engn_status(engn, &status); + if (status.chan) { + *cgid = status.chan->tsg; + return status.chan->id; + } + + return -ENODEV; +} + +bool +gk104_engn_chsw(struct nvkm_engn *engn) +{ + struct gk104_engn_status status; + + gk104_engn_status(engn, &status); + if (status.busy && status.chsw) + return true; + + return false; +} + const struct nvkm_engn_func gk104_engn = { + .chsw = gk104_engn_chsw, + .cxid = gk104_engn_cxid, + .mmu_fault_trigger = gf100_engn_mmu_fault_trigger, + .mmu_fault_triggered = gf100_engn_mmu_fault_triggered, }; const struct nvkm_engn_func gk104_engn_ce = { + .chsw = gk104_engn_chsw, + .cxid = gk104_engn_cxid, + .mmu_fault_trigger = gf100_engn_mmu_fault_trigger, + .mmu_fault_triggered = gf100_engn_mmu_fault_triggered, }; +bool +gk104_runq_idle(struct nvkm_runq *runq) +{ + struct nvkm_device *device = runq->fifo->engine.subdev.device; + + return !(nvkm_rd32(device, 0x003080 + (runq->id * 4)) & 0x0000e000); +} + static const struct nvkm_bitfield gk104_runq_intr_1_names[] = { { 0x00000001, "HCE_RE_ILLEGAL_OP" }, @@ -248,8 +296,15 @@ gk104_runq = { .init = gk104_runq_init, .intr = gk104_runq_intr, .intr_0_names = gk104_runq_intr_0_names, + .idle = gk104_runq_idle, }; +void +gk104_runl_fault_clear(struct nvkm_runl *runl) +{ + nvkm_wr32(runl->fifo->engine.subdev.device, 0x00262c, BIT(runl->id)); +} + void gk104_runl_allow(struct nvkm_runl *runl, u32 engm) { @@ -373,6 +428,7 @@ gk104_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .fault_clear = gk104_runl_fault_clear, .preempt_pending = gf100_runl_preempt_pending, }; @@ -394,193 +450,6 @@ gk104_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) return -1; } -static void -gk104_fifo_recover_work(struct work_struct *w) -{ - struct gk104_fifo *fifo = container_of(w, typeof(*fifo), recover.work); - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_engine *engine; - unsigned long flags; - u32 engm, runm, todo; - int engn, runl; - - spin_lock_irqsave(&fifo->base.lock, flags); - runm = fifo->recover.runm; - engm = fifo->recover.engm; - fifo->recover.engm = 0; - fifo->recover.runm = 0; - spin_unlock_irqrestore(&fifo->base.lock, flags); - - nvkm_mask(device, 0x002630, runm, runm); - - for (todo = engm; engn = __ffs(todo), todo; todo &= ~BIT(engn)) { - if ((engine = fifo->engine[engn].engine)) { - nvkm_subdev_fini(&engine->subdev, false); - WARN_ON(nvkm_subdev_init(&engine->subdev)); - } - } - - for (todo = runm; runl = __ffs(todo), todo; todo &= ~BIT(runl)) - gk104_fifo_runlist_update(fifo, runl); - - nvkm_wr32(device, 0x00262c, runm); - nvkm_mask(device, 0x002630, runm, 0x00000000); -} - -static void gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn); - -static void -gk104_fifo_recover_runl(struct gk104_fifo *fifo, int runl) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 runm = BIT(runl); - - assert_spin_locked(&fifo->base.lock); - if (fifo->recover.runm & runm) - return; - fifo->recover.runm |= runm; - - /* Block runlist to prevent channel assignment(s) from changing. */ - nvkm_mask(device, 0x002630, runm, runm); - - /* Schedule recovery. */ - nvkm_warn(subdev, "runlist %d: scheduled for recovery\n", runl); - schedule_work(&fifo->recover.work); -} - -static struct gk104_fifo_chan * -gk104_fifo_recover_chid(struct gk104_fifo *fifo, int runl, int chid) -{ - struct gk104_fifo_chan *chan; - struct nvkm_fifo_cgrp *cgrp; - - list_for_each_entry(chan, &fifo->runlist[runl].chan, head) { - if (chan->base.chid == chid) { - list_del_init(&chan->head); - return chan; - } - } - - list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) { - if (cgrp->id == chid) { - chan = list_first_entry(&cgrp->chan, typeof(*chan), head); - list_del_init(&chan->head); - if (!--cgrp->chan_nr) - list_del_init(&cgrp->head); - return chan; - } - } - - return NULL; -} - -void -gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 stat = nvkm_rd32(device, 0x800004 + (chid * 0x08)); - const u32 runl = (stat & 0x000f0000) >> 16; - const bool used = (stat & 0x00000001); - unsigned long engn, engm = fifo->runlist[runl].engm; - struct gk104_fifo_chan *chan; - - assert_spin_locked(&fifo->base.lock); - if (!used) - return; - - /* Lookup SW state for channel, and mark it as dead. */ - chan = gk104_fifo_recover_chid(fifo, runl, chid); - if (chan) { - chan->killed = true; - nvkm_chan_error(&chan->base, false); - } - - /* Block channel assignments from changing during recovery. */ - gk104_fifo_recover_runl(fifo, runl); - - /* Schedule recovery for any engines the channel is on. */ - for_each_set_bit(engn, &engm, fifo->engine_nr) { - struct gk104_fifo_engine_status status; - gk104_fifo_engine_status(fifo, engn, &status); - if (!status.chan || status.chan->id != chid) - continue; - gk104_fifo_recover_engn(fifo, engn); - } -} - -static void -gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn) -{ - struct nvkm_engine *engine = fifo->engine[engn].engine; - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 runl = fifo->engine[engn].runl; - const u32 engm = BIT(engn); - struct gk104_fifo_engine_status status; - int mmui = -1; - - assert_spin_locked(&fifo->base.lock); - if (fifo->recover.engm & engm) - return; - fifo->recover.engm |= engm; - - /* Block channel assignments from changing during recovery. */ - gk104_fifo_recover_runl(fifo, runl); - - /* Determine which channel (if any) is currently on the engine. */ - gk104_fifo_engine_status(fifo, engn, &status); - if (status.chan) { - /* The channel is not longer viable, kill it. */ - gk104_fifo_recover_chan(&fifo->base, status.chan->id); - } - - /* Determine MMU fault ID for the engine, if we're not being - * called from the fault handler already. - */ - if (!status.faulted && engine) { - mmui = nvkm_top_fault_id(device, engine->subdev.type, engine->subdev.inst); - if (mmui < 0) { - const struct nvkm_enum *en = fifo->func->mmu_fault->engine; - for (; en && en->name; en++) { - if (en->data2 == engine->subdev.type && - en->inst == engine->subdev.inst) { - mmui = en->value; - break; - } - } - } - WARN_ON(mmui < 0); - } - - /* Trigger a MMU fault for the engine. - * - * No good idea why this is needed, but nvgpu does something similar, - * and it makes recovery from CTXSW_TIMEOUT a lot more reliable. - */ - if (mmui >= 0) { - nvkm_wr32(device, 0x002a30 + (engn * 0x04), 0x00000100 | mmui); - - /* Wait for fault to trigger. */ - nvkm_msec(device, 2000, - gk104_fifo_engine_status(fifo, engn, &status); - if (status.faulted) - break; - ); - - /* Release MMU fault trigger, and ACK the fault. */ - nvkm_wr32(device, 0x002a30 + (engn * 0x04), 0x00000000); - nvkm_wr32(device, 0x00259c, BIT(mmui)); - nvkm_wr32(device, 0x002100, 0x10000000); - } - - /* Schedule recovery. */ - nvkm_warn(subdev, "engine %d: scheduled for recovery\n", engn); - schedule_work(&fifo->recover.work); -} - static const struct nvkm_enum gk104_fifo_mmu_fault_engine[] = { { 0x00, "GR", NULL, NVKM_ENGINE_GR }, @@ -728,64 +597,6 @@ gk104_fifo_intr_bind(struct nvkm_fifo *fifo) nvkm_error(subdev, "BIND_ERROR %02x [%s]\n", code, en ? en->name : ""); } -static const struct nvkm_enum -gk104_fifo_sched_reason[] = { - { 0x0a, "CTXSW_TIMEOUT" }, - {} -}; - -static void -gk104_fifo_intr_sched_ctxsw(struct gk104_fifo *fifo) -{ - struct nvkm_device *device = fifo->base.engine.subdev.device; - unsigned long flags, engm = 0; - u32 engn; - - /* We need to ACK the SCHED_ERROR here, and prevent it reasserting, - * as MMU_FAULT cannot be triggered while it's pending. - */ - spin_lock_irqsave(&fifo->base.lock, flags); - nvkm_mask(device, 0x002140, 0x00000100, 0x00000000); - nvkm_wr32(device, 0x002100, 0x00000100); - - for (engn = 0; engn < fifo->engine_nr; engn++) { - struct gk104_fifo_engine_status status; - - gk104_fifo_engine_status(fifo, engn, &status); - if (!status.busy || !status.chsw) - continue; - - engm |= BIT(engn); - } - - for_each_set_bit(engn, &engm, fifo->engine_nr) - gk104_fifo_recover_engn(fifo, engn); - - nvkm_mask(device, 0x002140, 0x00000100, 0x00000100); - spin_unlock_irqrestore(&fifo->base.lock, flags); -} - -static void -gk104_fifo_intr_sched(struct gk104_fifo *fifo) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 intr = nvkm_rd32(device, 0x00254c); - u32 code = intr & 0x000000ff; - const struct nvkm_enum *en = - nvkm_enum_find(gk104_fifo_sched_reason, code); - - nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : ""); - - switch (code) { - case 0x0a: - gk104_fifo_intr_sched_ctxsw(fifo); - break; - default: - break; - } -} - void gk104_fifo_intr_chsw(struct nvkm_fifo *fifo) { @@ -840,7 +651,7 @@ gk104_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x00000100) { - gk104_fifo_intr_sched(gk104_fifo(fifo)); + gf100_fifo_intr_sched(fifo); nvkm_wr32(device, 0x002100, 0x00000100); stat &= ~0x00000100; } @@ -901,13 +712,6 @@ gk104_fifo_intr(struct nvkm_inth *inth) return IRQ_HANDLED; } -void -gk104_fifo_fini(struct nvkm_fifo *base) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - flush_work(&fifo->recover.work); -} - void gk104_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) { @@ -999,7 +803,6 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) continue; fifo->engine[engn].engine = nvkm_device_engine(device, tdev->type, tdev->inst); - fifo->engine[engn].runl = tdev->runlist; fifo->engine_nr = max(fifo->engine_nr, engn + 1); fifo->runlist[tdev->runlist].engm |= BIT(engn); fifo->runlist[tdev->runlist].engm_sw |= BIT(engn); @@ -1064,7 +867,6 @@ gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device, if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) return -ENOMEM; fifo->func = func; - INIT_WORK(&fifo->recover.work, gk104_fifo_recover_work); *pfifo = &fifo->base; return nvkm_fifo_ctor(func, device, type, inst, &fifo->base); @@ -1080,12 +882,11 @@ gk104_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = gk104_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = gk104_fifo_recover_chan, .runlist = &gk104_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gk104_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 7cff1529ae35..64d9b1e857e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -14,16 +14,8 @@ struct gk104_fifo { const struct gk104_fifo_func *func; struct nvkm_fifo base; - struct { - struct work_struct work; - u32 engm; - u32 runm; - } recover; - struct { struct nvkm_engine *engine; - int runl; - int pbid; } engine[16]; int engine_nr; @@ -43,29 +35,14 @@ struct gk104_fifo { } user; }; -struct gk104_fifo_engine_status { - bool busy; - bool faulted; - bool chsw; - bool save; - bool load; - struct { - bool tsg; - u32 id; - } prev, next, *chan; -}; - int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int index, int nr, struct nvkm_fifo **); void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_update(struct gk104_fifo *, int runl); -void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, - struct gk104_fifo_engine_status *status); void *gk104_fifo_dtor(struct nvkm_fifo *base); int gk104_fifo_oneinit(struct nvkm_fifo *); void gk104_fifo_init(struct nvkm_fifo *base); -void gk104_fifo_fini(struct nvkm_fifo *base); extern const struct gk104_fifo_runlist_func gk104_fifo_runlist; void gk104_fifo_runlist_chan(struct gk104_fifo_chan *, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index a88e24ba956d..f27b7ea23e15 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -90,6 +90,7 @@ gk110_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .fault_clear = gk104_runl_fault_clear, .preempt_pending = gf100_runl_preempt_pending, }; @@ -115,12 +116,11 @@ gk110_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = gk104_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index ab813aa6d1a1..9886bd38a212 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -40,6 +40,7 @@ gk208_runq = { .init = gk208_runq_init, .intr = gk104_runq_intr, .intr_0_names = gk104_runq_intr_0_names, + .idle = gk104_runq_idle, }; static int @@ -58,12 +59,11 @@ gk208_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = gk104_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 0d633b805331..9177383d5f79 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -34,12 +34,11 @@ gk20a_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = gk104_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, + .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = gk104_fifo_recover_chan, .runlist = &gk110_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index a98ea71df2de..bf8671bf3892 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -63,6 +63,7 @@ gm107_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .fault_clear = gk104_runl_fault_clear, .preempt_pending = gf100_runl_preempt_pending, }; @@ -139,12 +140,11 @@ gm107_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = gk104_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, + .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gm107_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 6fa96a4c3e23..13c293aba6f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -48,12 +48,11 @@ gm200_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = gk104_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, + .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gm107_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index ddac252508fb..7698d640a6f7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -35,6 +35,7 @@ gp100_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .fault_clear = gk104_runl_fault_clear, .preempt_pending = gf100_runl_preempt_pending, }; @@ -106,12 +107,11 @@ gp100_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = gk104_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, .intr_mmu_fault_unit = gp100_fifo_intr_mmu_fault_unit, + .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gp100_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = gk104_fifo_recover_chan, .runlist = &gm107_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gp100_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index e68f3b7767b0..4ff2c75f53ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -20,6 +20,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "chan.h" +#include "chid.h" #include "cgrp.h" #include "runl.h" #include "runq.h" @@ -49,10 +50,14 @@ gv100_chan = { const struct nvkm_engn_func gv100_engn = { + .chsw = gk104_engn_chsw, + .cxid = gk104_engn_cxid, }; const struct nvkm_engn_func gv100_engn_ce = { + .chsw = gk104_engn_chsw, + .cxid = gk104_engn_cxid, }; static bool @@ -83,8 +88,15 @@ gv100_runq = { .intr = gk104_runq_intr, .intr_0_names = gk104_runq_intr_0_names, .intr_1_ctxnotvalid = gv100_runq_intr_1_ctxnotvalid, + .idle = gk104_runq_idle, }; +void +gv100_runl_preempt(struct nvkm_runl *runl) +{ + nvkm_wr32(runl->fifo->engine.subdev.device, 0x002638, BIT(runl->id)); +} + void gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan, struct nvkm_memory *memory, u32 offset) @@ -123,6 +135,7 @@ gv100_runl = { .pending = gk104_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .preempt = gv100_runl_preempt, .preempt_pending = gf100_runl_preempt_pending, }; @@ -362,6 +375,18 @@ gv100_fifo_mmu_fault = { .gpcclient = gv100_fifo_mmu_fault_gpcclient, }; +static void +gv100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo, u32 engm) +{ + struct nvkm_runl *runl; + struct nvkm_engn *engn; + + nvkm_runl_foreach(runl, fifo) { + nvkm_runl_foreach_engn_cond(engn, runl, engm & BIT(engn->id)) + nvkm_runl_rc_engn(runl, engn); + } +} + static const struct nvkm_fifo_func gv100_fifo = { .dtor = gk104_fifo_dtor, @@ -372,11 +397,10 @@ gv100_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = gk104_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, + .intr_ctxsw_timeout = gv100_fifo_intr_ctxsw_timeout, .mmu_fault = &gv100_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = gk104_fifo_recover_chan, .runlist = &gv100_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gv100_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 1a0d94bb1aaa..48153d8bba32 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -5,6 +5,7 @@ #include #include struct nvkm_cgrp; +struct nvkm_engn; struct nvkm_memory; struct nvkm_runl; struct nvkm_runq; @@ -24,10 +25,9 @@ struct nvkm_fifo_func { void (*init)(struct nvkm_fifo *); void (*init_pbdmas)(struct nvkm_fifo *, u32 mask); - void (*fini)(struct nvkm_fifo *); - irqreturn_t (*intr)(struct nvkm_inth *); void (*intr_mmu_fault_unit)(struct nvkm_fifo *, int unit); + void (*intr_ctxsw_timeout)(struct nvkm_fifo *, u32 engm); const struct nvkm_fifo_func_mmu_fault { void (*recover)(struct nvkm_fifo *, struct nvkm_fault_data *); @@ -41,7 +41,6 @@ struct nvkm_fifo_func { int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *); void (*pause)(struct nvkm_fifo *, unsigned long *); void (*start)(struct nvkm_fifo *, unsigned long *); - void (*recover_chan)(struct nvkm_fifo *, int chid); const struct gk104_fifo_runlist_func { u8 size; @@ -116,12 +115,16 @@ int gf100_fifo_runq_nr(struct nvkm_fifo *); bool gf100_fifo_intr_pbdma(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault(struct nvkm_fifo *); void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int); +void gf100_fifo_intr_sched(struct nvkm_fifo *); +void gf100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *, u32); void gf100_fifo_mmu_fault_recover(struct nvkm_fifo *, struct nvkm_fault_data *); extern const struct nvkm_enum gf100_fifo_mmu_fault_access[]; extern const struct nvkm_event_func gf100_fifo_nonstall; bool gf100_runl_preempt_pending(struct nvkm_runl *); void gf100_runq_init(struct nvkm_runq *); bool gf100_runq_intr(struct nvkm_runq *, struct nvkm_runl *); +void gf100_engn_mmu_fault_trigger(struct nvkm_engn *); +bool gf100_engn_mmu_fault_triggered(struct nvkm_engn *); extern const struct nvkm_engn_func gf100_engn_sw; void gf100_chan_preempt(struct nvkm_chan *); @@ -136,16 +139,19 @@ extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; extern const struct nvkm_enum gk104_fifo_mmu_fault_reason[]; extern const struct nvkm_enum gk104_fifo_mmu_fault_hubclient[]; extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[]; -void gk104_fifo_recover_chan(struct nvkm_fifo *, int); int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); bool gk104_runl_pending(struct nvkm_runl *); void gk104_runl_block(struct nvkm_runl *, u32); void gk104_runl_allow(struct nvkm_runl *, u32); +void gk104_runl_fault_clear(struct nvkm_runl *); extern const struct nvkm_runq_func gk104_runq; void gk104_runq_init(struct nvkm_runq *); bool gk104_runq_intr(struct nvkm_runq *, struct nvkm_runl *); extern const struct nvkm_bitfield gk104_runq_intr_0_names[]; +bool gk104_runq_idle(struct nvkm_runq *); extern const struct nvkm_engn_func gk104_engn; +bool gk104_engn_chsw(struct nvkm_engn *); +int gk104_engn_cxid(struct nvkm_engn *, bool *cgid); extern const struct nvkm_engn_func gk104_engn_ce; void gk104_chan_bind(struct nvkm_chan *); void gk104_chan_bind_inst(struct nvkm_chan *); @@ -174,10 +180,12 @@ extern const struct nvkm_enum gv100_fifo_mmu_fault_access[]; extern const struct nvkm_enum gv100_fifo_mmu_fault_reason[]; extern const struct nvkm_enum gv100_fifo_mmu_fault_hubclient[]; extern const struct nvkm_enum gv100_fifo_mmu_fault_gpcclient[]; +void gv100_runl_preempt(struct nvkm_runl *); extern const struct nvkm_runq_func gv100_runq; extern const struct nvkm_engn_func gv100_engn; extern const struct nvkm_engn_func gv100_engn_ce; +void tu102_fifo_intr_ctxsw_timeout_info(struct nvkm_engn *, u32 info); extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault; int nvkm_uchan_new(struct nvkm_fifo *, struct nvkm_cgrp *, const struct nvkm_oclass *, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 325c4de1b7d2..27c688d11464 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -24,11 +24,164 @@ #include "chan.h" #include "chid.h" #include "priv.h" +#include "runq.h" #include #include #include +struct nvkm_cgrp * +nvkm_engn_cgrp_get(struct nvkm_engn *engn, unsigned long *pirqflags) +{ + struct nvkm_cgrp *cgrp = NULL; + struct nvkm_chan *chan; + bool cgid; + int id; + + id = engn->func->cxid(engn, &cgid); + if (id < 0) + return NULL; + + if (!cgid) { + chan = nvkm_runl_chan_get_chid(engn->runl, id, pirqflags); + if (chan) + cgrp = chan->cgrp; + } else { + cgrp = nvkm_runl_cgrp_get_cgid(engn->runl, id, pirqflags); + } + + WARN_ON(!cgrp); + return cgrp; +} + +#include "gf100.h" +#include "gk104.h" + +static void +nvkm_runl_rc(struct nvkm_runl *runl) +{ + struct nvkm_fifo *fifo = runl->fifo; + struct nvkm_cgrp *cgrp, *gtmp; + struct nvkm_chan *chan, *ctmp; + struct nvkm_engn *engn; + unsigned long flags; + int rc, state, i; + bool reset; + + /* Runlist is blocked before scheduling recovery - fetch count. */ + BUG_ON(!mutex_is_locked(&runl->mutex)); + rc = atomic_xchg(&runl->rc_pending, 0); + if (!rc) + return; + + /* Look for channel groups flagged for RC. */ + nvkm_runl_foreach_cgrp_safe(cgrp, gtmp, runl) { + state = atomic_cmpxchg(&cgrp->rc, NVKM_CGRP_RC_PENDING, NVKM_CGRP_RC_RUNNING); + if (state == NVKM_CGRP_RC_PENDING) { + /* Disable all channels in them, and remove from runlist. */ + nvkm_cgrp_foreach_chan_safe(chan, ctmp, cgrp) + nvkm_chan_error(chan, false); + } + } + + /* On GPUs with runlist preempt, wait for PBDMA(s) servicing runlist to go idle. */ + if (runl->func->preempt) { + for (i = 0; i < runl->runq_nr; i++) { + struct nvkm_runq *runq = runl->runq[i]; + + if (runq) { + nvkm_msec(fifo->engine.subdev.device, 2000, + if (runq->func->idle(runq)) + break; + ); + } + } + } + + /* Look for engines that are still on flagged channel groups - reset them. */ + nvkm_runl_foreach_engn_cond(engn, runl, engn->func->cxid) { + cgrp = nvkm_engn_cgrp_get(engn, &flags); + if (!cgrp) { + ENGN_DEBUG(engn, "cxid not valid"); + continue; + } + + reset = atomic_read(&cgrp->rc) == NVKM_CGRP_RC_RUNNING; + nvkm_cgrp_put(&cgrp, flags); + if (!reset) { + ENGN_DEBUG(engn, "cxid not in recovery"); + continue; + } + + ENGN_DEBUG(engn, "resetting..."); + nvkm_subdev_fini(&engn->engine->subdev, false); + WARN_ON(nvkm_subdev_init(&engn->engine->subdev)); + } + + /* Submit runlist update, and clear any remaining exception state. */ + if (runl->fifo->engine.subdev.device->card_type < NV_E0) + gf100_fifo_runlist_commit(gf100_fifo(runl->fifo)); + else + gk104_fifo_runlist_update(gk104_fifo(runl->fifo), runl->id); + if (runl->func->fault_clear) + runl->func->fault_clear(runl); + + /* Unblock runlist processing. */ + while (rc--) + nvkm_runl_allow(runl); +} + +static void +nvkm_runl_rc_runl(struct nvkm_runl *runl) +{ + RUNL_ERROR(runl, "rc scheduled"); + + nvkm_runl_block(runl); + if (runl->func->preempt) + runl->func->preempt(runl); + + atomic_inc(&runl->rc_pending); + schedule_work(&runl->work); +} + +void +nvkm_runl_rc_cgrp(struct nvkm_cgrp *cgrp) +{ + if (atomic_cmpxchg(&cgrp->rc, NVKM_CGRP_RC_NONE, NVKM_CGRP_RC_PENDING) != NVKM_CGRP_RC_NONE) + return; + + CGRP_ERROR(cgrp, "rc scheduled"); + nvkm_runl_rc_runl(cgrp->runl); +} + +void +nvkm_runl_rc_engn(struct nvkm_runl *runl, struct nvkm_engn *engn) +{ + struct nvkm_cgrp *cgrp; + unsigned long flags; + + /* Lookup channel group currently on engine. */ + cgrp = nvkm_engn_cgrp_get(engn, &flags); + if (!cgrp) { + ENGN_DEBUG(engn, "rc skipped, not on channel"); + return; + } + + nvkm_runl_rc_cgrp(cgrp); + nvkm_cgrp_put(&cgrp, flags); +} + +static void +nvkm_runl_work(struct work_struct *work) +{ + struct nvkm_runl *runl = container_of(work, typeof(*runl), work); + + mutex_lock(&runl->mutex); + nvkm_runl_rc(runl); + mutex_unlock(&runl->mutex); + +} + struct nvkm_chan * nvkm_runl_chan_get_inst(struct nvkm_runl *runl, u64 inst, unsigned long *pirqflags) { @@ -74,6 +227,27 @@ nvkm_runl_chan_get_chid(struct nvkm_runl *runl, int id, unsigned long *pirqflags return NULL; } +struct nvkm_cgrp * +nvkm_runl_cgrp_get_cgid(struct nvkm_runl *runl, int id, unsigned long *pirqflags) +{ + struct nvkm_chid *cgid = runl->cgid; + struct nvkm_cgrp *cgrp; + unsigned long flags; + + spin_lock_irqsave(&cgid->lock, flags); + if (!WARN_ON(id >= cgid->nr)) { + cgrp = cgid->data[id]; + if (likely(cgrp)) { + spin_lock(&cgrp->lock); + *pirqflags = flags; + spin_unlock(&cgid->lock); + return cgrp; + } + } + spin_unlock_irqrestore(&cgid->lock, flags); + return NULL; +} + int nvkm_runl_preempt_wait(struct nvkm_runl *runl) { @@ -81,6 +255,7 @@ nvkm_runl_preempt_wait(struct nvkm_runl *runl) if (!runl->func->preempt_pending(runl)) break; + nvkm_runl_rc(runl); usleep_range(1, 2); ) < 0 ? -ETIMEDOUT : 0; } @@ -91,6 +266,7 @@ nvkm_runl_update_pending(struct nvkm_runl *runl) if (!runl->func->pending(runl)) return false; + nvkm_runl_rc(runl); return true; } @@ -122,6 +298,12 @@ nvkm_runl_block(struct nvkm_runl *runl) spin_unlock_irqrestore(&fifo->lock, flags); } +void +nvkm_runl_fini(struct nvkm_runl *runl) +{ + flush_work(&runl->work); +} + void nvkm_runl_del(struct nvkm_runl *runl) { @@ -214,6 +396,9 @@ nvkm_runl_new(struct nvkm_fifo *fifo, int runi, u32 addr, int id_nr) INIT_LIST_HEAD(&runl->engns); INIT_LIST_HEAD(&runl->cgrps); mutex_init(&runl->mutex); + INIT_WORK(&runl->work, nvkm_runl_work); + atomic_set(&runl->rc_triggered, 0); + atomic_set(&runl->rc_pending, 0); list_add_tail(&runl->head, &fifo->runls); if (!fifo->chid) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index 68d6854e6d0f..47bffc7bb7c0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -7,6 +7,10 @@ enum nvkm_subdev_type; struct nvkm_engn { const struct nvkm_engn_func { + bool (*chsw)(struct nvkm_engn *); + int (*cxid)(struct nvkm_engn *, bool *cgid); + void (*mmu_fault_trigger)(struct nvkm_engn *); + bool (*mmu_fault_triggered)(struct nvkm_engn *); } *func; struct nvkm_runl *runl; int id; @@ -28,6 +32,8 @@ struct nvkm_runl { bool (*pending)(struct nvkm_runl *); void (*block)(struct nvkm_runl *, u32 engm); void (*allow)(struct nvkm_runl *, u32 engm); + void (*fault_clear)(struct nvkm_runl *); + void (*preempt)(struct nvkm_runl *); bool (*preempt_pending)(struct nvkm_runl *); } *func; struct nvkm_fifo *fifo; @@ -50,6 +56,10 @@ struct nvkm_runl { int blocked; + struct work_struct work; + atomic_t rc_triggered; + atomic_t rc_pending; + struct list_head head; }; @@ -58,11 +68,16 @@ struct nvkm_runl *nvkm_runl_get(struct nvkm_fifo *, int runi, u32 addr); struct nvkm_engn *nvkm_runl_add(struct nvkm_runl *, int engi, const struct nvkm_engn_func *, enum nvkm_subdev_type, int inst); void nvkm_runl_del(struct nvkm_runl *); +void nvkm_runl_fini(struct nvkm_runl *); void nvkm_runl_block(struct nvkm_runl *); void nvkm_runl_allow(struct nvkm_runl *); bool nvkm_runl_update_pending(struct nvkm_runl *); int nvkm_runl_preempt_wait(struct nvkm_runl *); +void nvkm_runl_rc_engn(struct nvkm_runl *, struct nvkm_engn *); +void nvkm_runl_rc_cgrp(struct nvkm_cgrp *); + +struct nvkm_cgrp *nvkm_runl_cgrp_get_cgid(struct nvkm_runl *, int cgid, unsigned long *irqflags); struct nvkm_chan *nvkm_runl_chan_get_chid(struct nvkm_runl *, int chid, unsigned long *irqflags); struct nvkm_chan *nvkm_runl_chan_get_inst(struct nvkm_runl *, u64 inst, unsigned long *irqflags); @@ -74,6 +89,9 @@ struct nvkm_chan *nvkm_runl_chan_get_inst(struct nvkm_runl *, u64 inst, unsigned #define nvkm_runl_foreach_engn(engn,runl) list_for_each_entry((engn), &(runl)->engns, head) #define nvkm_runl_foreach_engn_cond(engn,runl,cond) \ nvkm_list_foreach(engn, &(runl)->engns, head, (cond)) +#define nvkm_runl_foreach_cgrp(cgrp,runl) list_for_each_entry((cgrp), &(runl)->cgrps, head) +#define nvkm_runl_foreach_cgrp_safe(cgrp,gtmp,runl) \ + list_for_each_entry_safe((cgrp), (gtmp), &(runl)->cgrps, head) #define RUNL_PRINT(r,l,p,f,a...) \ nvkm_printk__(&(r)->fifo->engine.subdev, NV_DBG_##l, p, "%06x:"f, (r)->addr, ##a) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h index 011fbf69bb35..2cb4836e8b31 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h @@ -10,6 +10,7 @@ struct nvkm_runq { bool (*intr)(struct nvkm_runq *, struct nvkm_runl *); const struct nvkm_bitfield *intr_0_names; bool (*intr_1_ctxnotvalid)(struct nvkm_runq *, int chid); + bool (*idle)(struct nvkm_runq *); } *func; struct nvkm_fifo *fifo; int id; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 641c1ff0aa5d..724a99a5597f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -92,6 +92,7 @@ tu102_runl = { .pending = tu102_runl_pending, .block = gk104_runl_block, .allow = gk104_runl_allow, + .preempt = gv100_runl_preempt, .preempt_pending = gf100_runl_preempt_pending, }; @@ -123,155 +124,6 @@ tu102_fifo_mmu_fault_engine[] = { {} }; -static void -tu102_fifo_recover_work(struct work_struct *w) -{ - struct gk104_fifo *fifo = container_of(w, typeof(*fifo), recover.work); - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_engine *engine; - unsigned long flags; - u32 engm, runm, todo; - int engn, runl; - - spin_lock_irqsave(&fifo->base.lock, flags); - runm = fifo->recover.runm; - engm = fifo->recover.engm; - fifo->recover.engm = 0; - fifo->recover.runm = 0; - spin_unlock_irqrestore(&fifo->base.lock, flags); - - nvkm_mask(device, 0x002630, runm, runm); - - for (todo = engm; engn = __ffs(todo), todo; todo &= ~BIT(engn)) { - if ((engine = fifo->engine[engn].engine)) { - nvkm_subdev_fini(&engine->subdev, false); - WARN_ON(nvkm_subdev_init(&engine->subdev)); - } - } - - for (todo = runm; runl = __ffs(todo), todo; todo &= ~BIT(runl)) - gk104_fifo_runlist_update(fifo, runl); - - nvkm_mask(device, 0x002630, runm, 0x00000000); -} - -static void tu102_fifo_recover_engn(struct gk104_fifo *fifo, int engn); - -static void -tu102_fifo_recover_runl(struct gk104_fifo *fifo, int runl) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 runm = BIT(runl); - - assert_spin_locked(&fifo->base.lock); - if (fifo->recover.runm & runm) - return; - fifo->recover.runm |= runm; - - /* Block runlist to prevent channel assignment(s) from changing. */ - nvkm_mask(device, 0x002630, runm, runm); - - /* Schedule recovery. */ - nvkm_warn(subdev, "runlist %d: scheduled for recovery\n", runl); - schedule_work(&fifo->recover.work); -} - -static struct gk104_fifo_chan * -tu102_fifo_recover_chid(struct gk104_fifo *fifo, int runl, int chid) -{ - struct gk104_fifo_chan *chan; - struct nvkm_fifo_cgrp *cgrp; - - list_for_each_entry(chan, &fifo->runlist[runl].chan, head) { - if (chan->base.chid == chid) { - list_del_init(&chan->head); - return chan; - } - } - - list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) { - if (cgrp->id == chid) { - chan = list_first_entry(&cgrp->chan, typeof(*chan), head); - list_del_init(&chan->head); - if (!--cgrp->chan_nr) - list_del_init(&cgrp->head); - return chan; - } - } - - return NULL; -} - -static void -tu102_fifo_recover_chan(struct nvkm_fifo *base, int chid) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 stat = nvkm_rd32(device, 0x800004 + (chid * 0x08)); - const u32 runl = (stat & 0x000f0000) >> 16; - const bool used = (stat & 0x00000001); - unsigned long engn, engm = fifo->runlist[runl].engm; - struct gk104_fifo_chan *chan; - - assert_spin_locked(&fifo->base.lock); - if (!used) - return; - - /* Lookup SW state for channel, and mark it as dead. */ - chan = tu102_fifo_recover_chid(fifo, runl, chid); - if (chan) { - chan->killed = true; - nvkm_chan_error(&chan->base, false); - } - - /* Block channel assignments from changing during recovery. */ - tu102_fifo_recover_runl(fifo, runl); - - /* Schedule recovery for any engines the channel is on. */ - for_each_set_bit(engn, &engm, fifo->engine_nr) { - struct gk104_fifo_engine_status status; - - gk104_fifo_engine_status(fifo, engn, &status); - if (!status.chan || status.chan->id != chid) - continue; - tu102_fifo_recover_engn(fifo, engn); - } -} - -static void -tu102_fifo_recover_engn(struct gk104_fifo *fifo, int engn) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 runl = fifo->engine[engn].runl; - const u32 engm = BIT(engn); - struct gk104_fifo_engine_status status; - - assert_spin_locked(&fifo->base.lock); - if (fifo->recover.engm & engm) - return; - fifo->recover.engm |= engm; - - /* Block channel assignments from changing during recovery. */ - tu102_fifo_recover_runl(fifo, runl); - - /* Determine which channel (if any) is currently on the engine. */ - gk104_fifo_engine_status(fifo, engn, &status); - if (status.chan) { - /* The channel is not longer viable, kill it. */ - tu102_fifo_recover_chan(&fifo->base, status.chan->id); - } - - /* Preempt the runlist */ - nvkm_wr32(device, 0x2638, BIT(runl)); - - /* Schedule recovery. */ - nvkm_warn(subdev, "engine %d: scheduled for recovery\n", engn); - schedule_work(&fifo->recover.work); -} - const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault = { .recover = gf100_fifo_mmu_fault_recover, @@ -282,22 +134,55 @@ tu102_fifo_mmu_fault = { .gpcclient = gv100_fifo_mmu_fault_gpcclient, }; -static void -tu102_fifo_intr_ctxsw_timeout(struct gk104_fifo *fifo) +void +tu102_fifo_intr_ctxsw_timeout_info(struct nvkm_engn *engn, u32 info) { - struct nvkm_device *device = fifo->base.engine.subdev.device; - unsigned long flags, engm; - u32 engn; + struct nvkm_runl *runl = engn->runl; + struct nvkm_cgrp *cgrp; + unsigned long flags; + + /* Check that engine hasn't become unstuck since timeout raised. */ + ENGN_DEBUG(engn, "CTXSW_TIMEOUT %08x", info); + if (info & 0xc0000000) + return; - spin_lock_irqsave(&fifo->base.lock, flags); + /* Determine channel group the engine is stuck on, and schedule recovery. */ + switch (info & 0x0000c000) { + case 0x00004000: /* LOAD */ + cgrp = nvkm_runl_cgrp_get_cgid(runl, info & 0x3fff0000, &flags); + break; + case 0x00008000: /* SAVE */ + case 0x0000c000: /* SWITCH */ + cgrp = nvkm_runl_cgrp_get_cgid(runl, info & 0x00003fff, &flags); + break; + default: + cgrp = NULL; + break; + } - engm = nvkm_rd32(device, 0x2a30); - nvkm_wr32(device, 0x2a30, engm); + if (!WARN_ON(!cgrp)) { + nvkm_runl_rc_cgrp(cgrp); + nvkm_cgrp_put(&cgrp, flags); + } +} - for_each_set_bit(engn, &engm, 32) - tu102_fifo_recover_engn(fifo, engn); +static void +tu102_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_runl *runl; + struct nvkm_engn *engn; + u32 engm = nvkm_rd32(device, 0x002a30); + u32 info; + + nvkm_runl_foreach(runl, fifo) { + nvkm_runl_foreach_engn_cond(engn, runl, engm & BIT(engn->id)) { + info = nvkm_rd32(device, 0x003200 + (engn->id * 4)); + tu102_fifo_intr_ctxsw_timeout_info(engn, info); + } + } - spin_unlock_irqrestore(&fifo->base.lock, flags); + nvkm_wr32(device, 0x002a30, engm); } static void @@ -326,7 +211,7 @@ tu102_fifo_intr(struct nvkm_inth *inth) } if (stat & 0x00000002) { - tu102_fifo_intr_ctxsw_timeout(gk104_fifo(fifo)); + tu102_fifo_intr_ctxsw_timeout(fifo); stat &= ~0x00000002; } @@ -386,11 +271,9 @@ tu102_fifo = { .runl_ctor = gk104_fifo_runl_ctor, .init = gk104_fifo_init, .init_pbdmas = tu102_fifo_init_pbdmas, - .fini = gk104_fifo_fini, .intr = tu102_fifo_intr, .mmu_fault = &tu102_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .recover_chan = tu102_fifo_recover_chan, .runlist = &tu102_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &tu102_runl, @@ -410,7 +293,6 @@ tu102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) return -ENOMEM; fifo->func = &tu102_fifo; - INIT_WORK(&fifo->recover.work, tu102_fifo_recover_work); *pfifo = &fifo->base; return nvkm_fifo_ctor(&tu102_fifo, device, type, inst, &fifo->base); -- cgit v1.2.3 From b084fff210bfd00de5cdef1802291272c77f581d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:35 +1000 Subject: drm/nouveau/fifo: add common runlist control - less dependence on waiting for runlist updates, on GPUs that allow it - supports runqueue selector in RAMRL entries - completes switch to common runl/cgrp/chan topology info Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h | 7 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 88 +++++++----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 2 - .../gpu/drm/nouveau/nvkm/engine/fifo/changf100.h | 3 - .../gpu/drm/nouveau/nvkm/engine/fifo/changk104.h | 6 - .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.c | 20 --- .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 69 ++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 12 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 119 +++------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 24 ---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 17 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 21 ++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 15 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 27 ---- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 40 ------ .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 15 -- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 31 ++--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 154 ++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h | 5 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 18 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 26 ++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 11 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 28 ++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 11 +- 35 files changed, 284 insertions(+), 505 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 798fbd3b530c..2d34f1944d64 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -17,6 +17,7 @@ struct nvkm_chan { const struct nvkm_chan_func *func; char name[64]; struct nvkm_cgrp *cgrp; + int runq; union { int id; int chid; }; /*FIXME: remove later */ @@ -63,7 +64,6 @@ struct nvkm_fifo { } timeout; int nr; - struct list_head chan; spinlock_t lock; struct mutex mutex; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 078a97ab5e37..0cbfb9225e6c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -310,8 +310,6 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, if (ret) return ret; - INIT_LIST_HEAD(&fifo->chan); - nr = func->chid_nr(fifo); fifo->nr = nr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c index fd9e6144981e..ac42dfc9d4cc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c @@ -196,7 +196,7 @@ nvkm_cgrp_new(struct nvkm_runl *runl, const char *name, struct nvkm_vmm *vmm, bo cgrp->hw = hw; cgrp->id = -1; kref_init(&cgrp->kref); - cgrp->chans = NULL; + INIT_LIST_HEAD(&cgrp->chans); cgrp->chan_nr = 0; spin_lock_init(&cgrp->lock); INIT_LIST_HEAD(&cgrp->ectxs); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h index e7ce66fecfd4..be9fbe9fab37 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h @@ -31,7 +31,7 @@ struct nvkm_cgrp { int id; struct kref kref; - struct nvkm_chan *chans; + struct list_head chans; int chan_nr; spinlock_t lock; /* protects irq handler channel (group) lookup */ @@ -46,7 +46,6 @@ struct nvkm_cgrp { atomic_t rc; struct list_head head; - struct list_head chan; }; int nvkm_cgrp_new(struct nvkm_runl *, const char *name, struct nvkm_vmm *, bool hw, @@ -59,9 +58,9 @@ void nvkm_cgrp_vctx_put(struct nvkm_cgrp *, struct nvkm_vctx **); void nvkm_cgrp_put(struct nvkm_cgrp **, unsigned long irqflags); -#define nvkm_cgrp_foreach_chan(chan,cgrp) for ((chan) = (cgrp)->chans; (chan); (chan) = NULL) +#define nvkm_cgrp_foreach_chan(chan,cgrp) list_for_each_entry((chan), &(cgrp)->chans, head) #define nvkm_cgrp_foreach_chan_safe(chan,ctmp,cgrp) \ - (void)(ctmp); nvkm_cgrp_foreach_chan((chan), (cgrp)) + list_for_each_entry_safe((chan), (ctmp), &(cgrp)->chans, head) #define CGRP_PRCLI(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a) #define CGRP_PRINT(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:"f, (c)->id, ##a) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 9b8f346d52b1..3832a9aad80a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -339,22 +339,60 @@ nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc, return 0; } -static int -nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend) +void +nvkm_chan_remove_locked(struct nvkm_chan *chan) { - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - if (chan->func->fini) - chan->func->fini(chan); - return 0; + struct nvkm_cgrp *cgrp = chan->cgrp; + struct nvkm_runl *runl = cgrp->runl; + + if (list_empty(&chan->head)) + return; + + CHAN_TRACE(chan, "remove"); + if (!--cgrp->chan_nr) { + runl->cgrp_nr--; + list_del(&cgrp->head); + } + runl->chan_nr--; + list_del_init(&chan->head); + atomic_set(&runl->changed, 1); } -static int -nvkm_fifo_chan_init(struct nvkm_object *object) +void +nvkm_chan_remove(struct nvkm_chan *chan, bool preempt) { - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - if (chan->func->init) - chan->func->init(chan); - return 0; + struct nvkm_runl *runl = chan->cgrp->runl; + + mutex_lock(&runl->mutex); + if (preempt && chan->func->preempt) + nvkm_chan_preempt_locked(chan, true); + nvkm_chan_remove_locked(chan); + nvkm_runl_update_locked(runl, true); + mutex_unlock(&runl->mutex); +} + +void +nvkm_chan_insert(struct nvkm_chan *chan) +{ + struct nvkm_cgrp *cgrp = chan->cgrp; + struct nvkm_runl *runl = cgrp->runl; + + mutex_lock(&runl->mutex); + if (WARN_ON(!list_empty(&chan->head))) { + mutex_unlock(&runl->mutex); + return; + } + + CHAN_TRACE(chan, "insert"); + list_add_tail(&chan->head, &cgrp->chans); + runl->chan_nr++; + if (!cgrp->chan_nr++) { + list_add_tail(&cgrp->head, &cgrp->runl->cgrps); + runl->cgrp_nr++; + } + atomic_set(&runl->changed, 1); + nvkm_runl_update_locked(runl, true); + mutex_unlock(&runl->mutex); } static void @@ -420,15 +458,7 @@ static void * nvkm_fifo_chan_dtor(struct nvkm_object *object) { struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - struct nvkm_fifo *fifo = chan->fifo; void *data = chan->func->dtor(chan); - unsigned long flags; - - spin_lock_irqsave(&fifo->lock, flags); - if (!list_empty(&chan->head)) { - list_del(&chan->head); - } - spin_unlock_irqrestore(&fifo->lock, flags); if (chan->vmm) { nvkm_vmm_part(chan->vmm, chan->inst->memory); @@ -494,8 +524,6 @@ nvkm_chan_get_chid(struct nvkm_engine *engine, int id, unsigned long *pirqflags) static const struct nvkm_object_func nvkm_fifo_chan_func = { .dtor = nvkm_fifo_chan_dtor, - .init = nvkm_fifo_chan_init, - .fini = nvkm_fifo_chan_fini, .map = nvkm_fifo_chan_map, }; @@ -514,7 +542,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, struct nvkm_runl *runl; struct nvkm_engn *engn = NULL; struct nvkm_vmm *vmm = NULL; - unsigned long flags; int ret; nvkm_runl_foreach(runl, fifo) { @@ -532,8 +559,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, *func = *fifo->func->chan.func; func->dtor = fn->dtor; - func->init = fn->init; - func->fini = fn->fini; func->engine_ctor = fn->engine_ctor; func->engine_dtor = fn->engine_dtor; func->engine_init = fn->engine_init; @@ -611,23 +636,14 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, } /* Allocate channel ID. */ - if (runl->cgid) { - chan->id = chan->cgrp->id; - runl->chid->data[chan->id] = chan; - set_bit(chan->id, runl->chid->used); - goto temp_hack_until_no_chid_eq_cgid_req; - } - chan->id = nvkm_chid_get(runl->chid, chan); if (chan->id < 0) { RUNL_ERROR(runl, "!chids"); return -ENOSPC; } -temp_hack_until_no_chid_eq_cgid_req: - spin_lock_irqsave(&fifo->lock, flags); - list_add(&chan->head, &fifo->chan); - spin_unlock_irqrestore(&fifo->lock, flags); + if (cgrp->id < 0) + cgrp->id = chan->id; /* determine address of this channel's user registers */ chan->addr = device->func->resource_addr(device, bar) + diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 2ad385914bec..804441f30f44 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -24,8 +24,6 @@ struct nvkm_chan_func { u32 (*doorbell_handle)(struct nvkm_chan *); void *(*dtor)(struct nvkm_fifo_chan *); - void (*init)(struct nvkm_fifo_chan *); - void (*fini)(struct nvkm_fifo_chan *); int (*engine_ctor)(struct nvkm_fifo_chan *, struct nvkm_engine *, struct nvkm_object *); void (*engine_dtor)(struct nvkm_fifo_chan *, struct nvkm_engine *); @@ -44,6 +42,9 @@ void nvkm_chan_del(struct nvkm_chan **); void nvkm_chan_allow(struct nvkm_chan *); void nvkm_chan_block(struct nvkm_chan *); void nvkm_chan_error(struct nvkm_chan *, bool preempt); +void nvkm_chan_insert(struct nvkm_chan *); +void nvkm_chan_remove(struct nvkm_chan *, bool preempt); +void nvkm_chan_remove_locked(struct nvkm_chan *); int nvkm_chan_preempt(struct nvkm_chan *, bool wait); int nvkm_chan_preempt_locked(struct nvkm_chan *, bool wait); int nvkm_chan_cctx_get(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx **, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 100631a44a85..64566b5cc23f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -169,8 +169,6 @@ g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, static const struct nvkm_fifo_chan_func g84_fifo_chan_func = { .dtor = nv50_fifo_chan_dtor, - .init = nv50_fifo_chan_init, - .fini = nv50_fifo_chan_fini, .engine_ctor = g84_fifo_chan_engine_ctor, .engine_dtor = nv50_fifo_chan_engine_dtor, .engine_init = g84_fifo_chan_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h index f7ac1061fa84..3c7b6c0d8cf1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h @@ -9,9 +9,6 @@ struct gf100_fifo_chan { struct nvkm_fifo_chan base; struct gf100_fifo *fifo; - struct list_head head; - bool killed; - #define GF100_FIFO_ENGN_GR 0 #define GF100_FIFO_ENGN_MSPDEC 1 #define GF100_FIFO_ENGN_MSPPP 2 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h index 7a83b8667443..95e788f31590 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h @@ -10,10 +10,6 @@ struct gk104_fifo_chan { struct gk104_fifo *fifo; int runl; - struct nvkm_fifo_cgrp *cgrp; - struct list_head head; - bool killed; - #define GK104_FIFO_ENGN_SW 15 struct gk104_fifo_engn { struct nvkm_gpuobj *inst; @@ -26,8 +22,6 @@ extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func; int gk104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); void *gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *); -void gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *); -void gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *); struct gk104_fifo_engn *gk104_fifo_gpfifo_engine(struct gk104_fifo_chan *, struct nvkm_engine *); int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *, struct nvkm_engine *, struct nvkm_object *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c index 7669d17406c6..5d6f82236c50 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c @@ -183,24 +183,6 @@ nv50_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context); } -void -nv50_fifo_chan_fini(struct nvkm_fifo_chan *base) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - struct nv50_fifo *fifo = chan->fifo; - - nv50_fifo_runlist_update(fifo); -} - -void -nv50_fifo_chan_init(struct nvkm_fifo_chan *base) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - struct nv50_fifo *fifo = chan->fifo; - - nv50_fifo_runlist_update(fifo); -} - void * nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) { @@ -216,8 +198,6 @@ nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) static const struct nvkm_fifo_chan_func nv50_fifo_chan_func = { .dtor = nv50_fifo_chan_dtor, - .init = nv50_fifo_chan_init, - .fini = nv50_fifo_chan_fini, .engine_ctor = nv50_fifo_chan_engine_ctor, .engine_dtor = nv50_fifo_chan_engine_dtor, .engine_init = nv50_fifo_chan_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h index 5d5d9f3d9928..ce7d61e8d297 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h @@ -40,8 +40,6 @@ struct nv50_fifo_chan { int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, const struct nvkm_oclass *, struct nv50_fifo_chan *); void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); -void nv50_fifo_chan_init(struct nvkm_fifo_chan *); -void nv50_fifo_chan_fini(struct nvkm_fifo_chan *); struct nvkm_gpuobj **nv50_fifo_chan_engine(struct nv50_fifo_chan *, struct nvkm_engine *); void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 91b43f17120b..18ec982f4f54 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -125,7 +125,6 @@ g84_fifo_runl_ctor(struct nvkm_fifo *fifo) static const struct nvkm_fifo_func g84_fifo = { .dtor = nv50_fifo_dtor, - .oneinit = nv50_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = nv50_fifo_chid_ctor, .runl_ctor = g84_fifo_runl_ctor, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c index a912e1ba4339..8016a2228e92 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c @@ -50,7 +50,6 @@ g98_fifo_runl_ctor(struct nvkm_fifo *fifo) static const struct nvkm_fifo_func g98_fifo = { .dtor = nv50_fifo_dtor, - .oneinit = nv50_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = nv50_fifo_chid_ctor, .runl_ctor = g98_fifo_runl_ctor, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 4fc9e80b5f69..767507e0e239 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -287,64 +287,38 @@ gf100_runl_pending(struct nvkm_runl *runl) return nvkm_rd32(runl->fifo->engine.subdev.device, 0x00227c) & 0x00100000; } -void -gf100_fifo_runlist_commit(struct gf100_fifo *fifo) +static void +gf100_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count) { - struct gf100_fifo_chan *chan; - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_runl *runl = nvkm_runl_first(&fifo->base); - struct nvkm_memory *cur; - int nr = 0; + struct nvkm_device *device = runl->fifo->engine.subdev.device; + u64 addr = nvkm_memory_addr(memory) + start; int target; - mutex_lock(&fifo->base.mutex); - cur = fifo->runlist.mem[fifo->runlist.active]; - fifo->runlist.active = !fifo->runlist.active; - - nvkm_kmap(cur); - list_for_each_entry(chan, &fifo->chan, head) { - nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid); - nvkm_wo32(cur, (nr * 8) + 4, 0x00000004); - nr++; - } - nvkm_done(cur); - - switch (nvkm_memory_target(cur)) { + switch (nvkm_memory_target(memory)) { case NVKM_MEM_TARGET_VRAM: target = 0; break; case NVKM_MEM_TARGET_NCOH: target = 3; break; default: - mutex_unlock(&fifo->base.mutex); WARN_ON(1); return; } - nvkm_wr32(device, 0x002270, (nvkm_memory_addr(cur) >> 12) | - (target << 28)); - nvkm_wr32(device, 0x002274, 0x01f00000 | nr); - - runl->func->wait(runl); - mutex_unlock(&fifo->base.mutex); -} - -void -gf100_fifo_runlist_remove(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan) -{ - mutex_lock(&fifo->base.mutex); - list_del_init(&chan->head); - mutex_unlock(&fifo->base.mutex); + nvkm_wr32(device, 0x002270, (target << 28) | (addr >> 12)); + nvkm_wr32(device, 0x002274, 0x01f00000 | count); } -void -gf100_fifo_runlist_insert(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan) +static void +gf100_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset) { - mutex_lock(&fifo->base.mutex); - list_add_tail(&chan->head, &fifo->chan); - mutex_unlock(&fifo->base.mutex); + nvkm_wo32(memory, offset + 0, chan->id); + nvkm_wo32(memory, offset + 4, 0x00000004); } static const struct nvkm_runl_func gf100_runl = { + .size = 8, + .update = nv50_runl_update, + .insert_chan = gf100_runl_insert_chan, + .commit = gf100_runl_commit, .wait = nv50_runl_wait, .pending = gf100_runl_pending, .block = gf100_runl_block, @@ -884,16 +858,6 @@ gf100_fifo_oneinit(struct nvkm_fifo *base) struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); int ret; - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, - false, &fifo->runlist.mem[0]); - if (ret) - return ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, - false, &fifo->runlist.mem[1]); - if (ret) - return ret; - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000, 0x1000, false, &fifo->user.mem); if (ret) @@ -914,8 +878,6 @@ gf100_fifo_dtor(struct nvkm_fifo *base) struct nvkm_device *device = fifo->base.engine.subdev.device; nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar); nvkm_memory_unref(&fifo->user.mem); - nvkm_memory_unref(&fifo->runlist.mem[0]); - nvkm_memory_unref(&fifo->runlist.mem[1]); return fifo; } @@ -950,7 +912,6 @@ gf100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) return -ENOMEM; - INIT_LIST_HEAD(&fifo->chan); *pfifo = &fifo->base; return nvkm_fifo_ctor(&gf100_fifo, device, type, inst, &fifo->base); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h index 6d7771f505c6..42a950c00483 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -6,24 +6,12 @@ #include -struct gf100_fifo_chan; struct gf100_fifo { struct nvkm_fifo base; - struct list_head chan; - - struct { - struct nvkm_memory *mem[2]; - int active; - } runlist; - struct { struct nvkm_memory *mem; struct nvkm_vma *bar; } user; }; - -void gf100_fifo_runlist_insert(struct gf100_fifo *, struct gf100_fifo_chan *); -void gf100_fifo_runlist_remove(struct gf100_fifo *, struct gf100_fifo_chan *); -void gf100_fifo_runlist_commit(struct gf100_fifo *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index d8cb2626b188..b5e698a223b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -326,15 +326,14 @@ gk104_runl_pending(struct nvkm_runl *runl) } void -gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, - struct nvkm_memory *mem, int nr) +gk104_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count) { - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_runl *rl = nvkm_runl_get(&fifo->base, runl, 0); + struct nvkm_fifo *fifo = runl->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; + u64 addr = nvkm_memory_addr(memory) + start; int target; - switch (nvkm_memory_target(mem)) { + switch (nvkm_memory_target(memory)) { case NVKM_MEM_TARGET_VRAM: target = 0; break; case NVKM_MEM_TARGET_NCOH: target = 3; break; default: @@ -342,88 +341,25 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, return; } - nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) | - (target << 28)); - nvkm_wr32(device, 0x002274, (runl << 20) | nr); - - rl->func->wait(rl); -} - -void -gk104_fifo_runlist_update(struct gk104_fifo *fifo, int runl) -{ - const struct gk104_fifo_runlist_func *func = fifo->func->runlist; - struct gk104_fifo_chan *chan; - struct nvkm_memory *mem; - struct nvkm_fifo_cgrp *cgrp; - int nr = 0; - - mutex_lock(&fifo->base.mutex); - mem = fifo->runlist[runl].mem[fifo->runlist[runl].next]; - fifo->runlist[runl].next = !fifo->runlist[runl].next; - - nvkm_kmap(mem); - list_for_each_entry(chan, &fifo->runlist[runl].chan, head) { - func->chan(chan, mem, nr++ * func->size); - } - - list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) { - func->cgrp(cgrp, mem, nr++ * func->size); - list_for_each_entry(chan, &cgrp->chan, head) { - func->chan(chan, mem, nr++ * func->size); - } - } - nvkm_done(mem); - - func->commit(fifo, runl, mem, nr); - mutex_unlock(&fifo->base.mutex); -} - -void -gk104_fifo_runlist_remove(struct gk104_fifo *fifo, struct gk104_fifo_chan *chan) -{ - struct nvkm_fifo_cgrp *cgrp = chan->cgrp; - mutex_lock(&fifo->base.mutex); - if (!list_empty(&chan->head)) { - list_del_init(&chan->head); - if (cgrp && !--cgrp->chan_nr) - list_del_init(&cgrp->head); - } - mutex_unlock(&fifo->base.mutex); -} - -void -gk104_fifo_runlist_insert(struct gk104_fifo *fifo, struct gk104_fifo_chan *chan) -{ - struct nvkm_fifo_cgrp *cgrp = chan->cgrp; - mutex_lock(&fifo->base.mutex); - if (cgrp) { - if (!cgrp->chan_nr++) - list_add_tail(&cgrp->head, &fifo->runlist[chan->runl].cgrp); - list_add_tail(&chan->head, &cgrp->chan); - } else { - list_add_tail(&chan->head, &fifo->runlist[chan->runl].chan); - } - mutex_unlock(&fifo->base.mutex); + spin_lock_irq(&fifo->lock); + nvkm_wr32(device, 0x002270, (target << 28) | (addr >> 12)); + nvkm_wr32(device, 0x002274, (runl->id << 20) | count); + spin_unlock_irq(&fifo->lock); } void -gk104_fifo_runlist_chan(struct gk104_fifo_chan *chan, - struct nvkm_memory *memory, u32 offset) +gk104_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset) { - nvkm_wo32(memory, offset + 0, chan->base.chid); + nvkm_wo32(memory, offset + 0, chan->id); nvkm_wo32(memory, offset + 4, 0x00000000); } -const struct gk104_fifo_runlist_func -gk104_fifo_runlist = { - .size = 8, - .chan = gk104_fifo_runlist_chan, - .commit = gk104_fifo_runlist_commit, -}; - static const struct nvkm_runl_func gk104_runl = { + .size = 8, + .update = nv50_runl_update, + .insert_chan = gk104_runl_insert_chan, + .commit = gk104_runl_commit, .wait = nv50_runl_wait, .pending = gk104_runl_pending, .block = gk104_runl_block, @@ -793,7 +729,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) struct nvkm_device *device = subdev->device; struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); struct nvkm_top_device *tdev; - int ret, i, j; + int ret; /* Determine runlist configuration from topology device info. */ list_for_each_entry(tdev, &device->top->device, head) { @@ -811,21 +747,6 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) fifo->runlist_nr = max(fifo->runlist_nr, tdev->runlist + 1); } - for (i = 0; i < fifo->runlist_nr; i++) { - for (j = 0; j < ARRAY_SIZE(fifo->runlist[i].mem); j++) { - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - fifo->base.nr * 2/* TSG+chan */ * - fifo->func->runlist->size, - 0x1000, false, - &fifo->runlist[i].mem[j]); - if (ret) - return ret; - } - - INIT_LIST_HEAD(&fifo->runlist[i].cgrp); - INIT_LIST_HEAD(&fifo->runlist[i].chan); - } - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, fifo->base.nr * 0x200, 0x1000, true, &fifo->user.mem); @@ -845,16 +766,9 @@ gk104_fifo_dtor(struct nvkm_fifo *base) { struct gk104_fifo *fifo = gk104_fifo(base); struct nvkm_device *device = fifo->base.engine.subdev.device; - int i; nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar); nvkm_memory_unref(&fifo->user.mem); - - for (i = 0; i < fifo->runlist_nr; i++) { - nvkm_memory_unref(&fifo->runlist[i].mem[1]); - nvkm_memory_unref(&fifo->runlist[i].mem[0]); - } - return fifo; } @@ -887,7 +801,6 @@ gk104_fifo = { .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &gk104_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gk104_runl, .runq = &gk104_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 64d9b1e857e1..3915b3b9e6bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -20,10 +20,6 @@ struct gk104_fifo { int engine_nr; struct { - struct nvkm_memory *mem[2]; - int next; - struct list_head cgrp; - struct list_head chan; u32 engm; u32 engm_sw; } runlist[16]; @@ -37,27 +33,7 @@ struct gk104_fifo { int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int index, int nr, struct nvkm_fifo **); -void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *); -void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *); -void gk104_fifo_runlist_update(struct gk104_fifo *, int runl); void *gk104_fifo_dtor(struct nvkm_fifo *base); int gk104_fifo_oneinit(struct nvkm_fifo *); void gk104_fifo_init(struct nvkm_fifo *base); - -extern const struct gk104_fifo_runlist_func gk104_fifo_runlist; -void gk104_fifo_runlist_chan(struct gk104_fifo_chan *, - struct nvkm_memory *, u32); -void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl, - struct nvkm_memory *, int); - -extern const struct gk104_fifo_runlist_func gk110_fifo_runlist; -void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, - struct nvkm_memory *, u32); - -extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; - -void gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, - struct nvkm_memory *, u32); -void gv100_fifo_runlist_chan(struct gk104_fifo_chan *, - struct nvkm_memory *, u32); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index f27b7ea23e15..812fefff0925 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -68,24 +68,20 @@ gk110_cgrp = { }; void -gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp, - struct nvkm_memory *memory, u32 offset) +gk110_runl_insert_cgrp(struct nvkm_cgrp *cgrp, struct nvkm_memory *memory, u64 offset) { nvkm_wo32(memory, offset + 0, (cgrp->chan_nr << 26) | (128 << 18) | (3 << 14) | 0x00002000 | cgrp->id); nvkm_wo32(memory, offset + 4, 0x00000000); } -const struct gk104_fifo_runlist_func -gk110_fifo_runlist = { - .size = 8, - .cgrp = gk110_fifo_runlist_cgrp, - .chan = gk104_fifo_runlist_chan, - .commit = gk104_fifo_runlist_commit, -}; - const struct nvkm_runl_func gk110_runl = { + .size = 8, + .update = nv50_runl_update, + .insert_cgrp = gk110_runl_insert_cgrp, + .insert_chan = gk104_runl_insert_chan, + .commit = gk104_runl_commit, .wait = nv50_runl_wait, .pending = gk104_runl_pending, .block = gk104_runl_block, @@ -121,7 +117,6 @@ gk110_fifo = { .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &gk110_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk104_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 9886bd38a212..81d184473f79 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -64,7 +64,6 @@ gk208_fifo = { .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &gk110_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 9177383d5f79..47b7d93f5a04 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -39,7 +39,6 @@ gk20a_fifo = { .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &gk110_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index bf8671bf3892..c0eca7da7d09 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -42,23 +42,19 @@ gm107_chan = { }; static void -gm107_fifo_runlist_chan(struct gk104_fifo_chan *chan, - struct nvkm_memory *memory, u32 offset) +gm107_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset) { - nvkm_wo32(memory, offset + 0, chan->base.chid); - nvkm_wo32(memory, offset + 4, chan->base.inst->addr >> 12); + nvkm_wo32(memory, offset + 0, chan->id); + nvkm_wo32(memory, offset + 4, chan->inst->addr >> 12); } -const struct gk104_fifo_runlist_func -gm107_fifo_runlist = { - .size = 8, - .cgrp = gk110_fifo_runlist_cgrp, - .chan = gm107_fifo_runlist_chan, - .commit = gk104_fifo_runlist_commit, -}; - const struct nvkm_runl_func gm107_runl = { + .size = 8, + .update = nv50_runl_update, + .insert_cgrp = gk110_runl_insert_cgrp, + .insert_chan = gm107_runl_insert_chan, + .commit = gk104_runl_commit, .wait = nv50_runl_wait, .pending = gk104_runl_pending, .block = gk104_runl_block, @@ -145,7 +141,6 @@ gm107_fifo = { .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gm107_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &gm107_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 13c293aba6f2..8be59812797a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -53,7 +53,6 @@ gm200_fifo = { .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gm107_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &gm107_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 7698d640a6f7..a353c6b860ef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -25,12 +25,26 @@ #include "gk104.h" #include "changk104.h" +#include #include #include +static void +gp100_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset) +{ + nvkm_wo32(memory, offset + 0, chan->id | chan->runq << 14); + nvkm_wo32(memory, offset + 4, chan->inst->addr >> 12); +} + static const struct nvkm_runl_func gp100_runl = { + .runqs = 2, + .size = 8, + .update = nv50_runl_update, + .insert_cgrp = gk110_runl_insert_cgrp, + .insert_chan = gp100_runl_insert_chan, + .commit = gk104_runl_commit, .wait = nv50_runl_wait, .pending = gk104_runl_pending, .block = gk104_runl_block, @@ -112,7 +126,6 @@ gp100_fifo = { .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gp100_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &gm107_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gp100_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 77a4f2346f04..871f199ddccf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -127,30 +127,6 @@ gf100_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, return nvkm_memory_map(engn->inst, 0, chan->base.vmm, engn->vma, NULL, 0); } -static void -gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) -{ - struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - struct gf100_fifo *fifo = chan->fifo; - - if (!list_empty(&chan->head) && !chan->killed) { - gf100_fifo_runlist_remove(fifo, chan); - gf100_fifo_runlist_commit(fifo); - } -} - -static void -gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base) -{ - struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - struct gf100_fifo *fifo = chan->fifo; - - if (list_empty(&chan->head) && !chan->killed) { - gf100_fifo_runlist_insert(fifo, chan); - gf100_fifo_runlist_commit(fifo); - } -} - static void * gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) { @@ -160,8 +136,6 @@ gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) static const struct nvkm_fifo_chan_func gf100_fifo_gpfifo_func = { .dtor = gf100_fifo_gpfifo_dtor, - .init = gf100_fifo_gpfifo_init, - .fini = gf100_fifo_gpfifo_fini, .engine_ctor = gf100_fifo_gpfifo_engine_ctor, .engine_dtor = gf100_fifo_gpfifo_engine_dtor, .engine_init = gf100_fifo_gpfifo_engine_init, @@ -197,7 +171,6 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return -ENOMEM; *pobject = &chan->base.object; chan->fifo = fifo; - INIT_LIST_HEAD(&chan->head); ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base, 0x1000, 0x1000, true, args->v0.vmm, 0, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index 9440cf57a1b8..aa3ea7f7f8e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -152,43 +152,16 @@ gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, return nvkm_memory_map(engn->inst, 0, chan->base.vmm, engn->vma, NULL, 0); } -void -gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - struct gk104_fifo *fifo = chan->fifo; - - if (!list_empty(&chan->head)) { - gk104_fifo_runlist_remove(fifo, chan); - gk104_fifo_runlist_update(fifo, chan->runl); - } -} - -void -gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - struct gk104_fifo *fifo = chan->fifo; - - if (list_empty(&chan->head) && !chan->killed) { - gk104_fifo_runlist_insert(fifo, chan); - gk104_fifo_runlist_update(fifo, chan->runl); - } -} - void * gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) { struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - kfree(chan->cgrp); return chan; } const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func = { .dtor = gk104_fifo_gpfifo_dtor, - .init = gk104_fifo_gpfifo_init, - .fini = gk104_fifo_gpfifo_fini, .engine_ctor = gk104_fifo_gpfifo_engine_ctor, .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gk104_fifo_gpfifo_engine_init, @@ -215,7 +188,6 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, *pobject = &chan->base.object; chan->fifo = fifo; chan->runl = runlist; - INIT_LIST_HEAD(&chan->head); ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, 0x1000, 0x1000, true, vmm, 0, fifo->runlist[runlist].engm_sw, @@ -227,18 +199,6 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, *chid = chan->base.chid; *inst = chan->base.inst->addr; - /* Hack to support GPUs where even individual channels should be - * part of a channel group. - */ - if (fifo->func->cgrp.force) { - if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL))) - return -ENOMEM; - chan->cgrp->id = chan->base.chid; - INIT_LIST_HEAD(&chan->cgrp->head); - INIT_LIST_HEAD(&chan->cgrp->chan); - chan->cgrp->chan_nr = 0; - } - /* Clear channel control registers. */ usermem = chan->base.chid * 0x200; ilength = order_base_2(ilength / 8); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 66d6079ff210..428901abdb81 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -105,8 +105,6 @@ gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, static const struct nvkm_fifo_chan_func gv100_fifo_gpfifo = { .dtor = gk104_fifo_gpfifo_dtor, - .init = gk104_fifo_gpfifo_init, - .fini = gk104_fifo_gpfifo_fini, .engine_ctor = gk104_fifo_gpfifo_engine_ctor, .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gv100_fifo_gpfifo_engine_init, @@ -134,7 +132,6 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, *pobject = &chan->base.object; chan->fifo = fifo; chan->runl = runlist; - INIT_LIST_HEAD(&chan->head); ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm, 0, fifo->runlist[runlist].engm, 1, fifo->user.bar->addr, 0x200, @@ -146,18 +143,6 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, *inst = chan->base.inst->addr; *token = chan->base.func->doorbell_handle(&chan->base); - /* Hack to support GPUs where even individual channels should be - * part of a channel group. - */ - if (fifo->func->cgrp.force) { - if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL))) - return -ENOMEM; - chan->cgrp->id = chan->base.chid; - INIT_LIST_HEAD(&chan->cgrp->head); - INIT_LIST_HEAD(&chan->cgrp->chan); - chan->cgrp->chan_nr = 0; - } - /* Clear channel control registers. */ usermem = chan->base.chid * 0x200; ilength = order_base_2(ilength / 8); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c index 1c48a109a2b8..6562bdf39cb0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c @@ -31,8 +31,6 @@ static const struct nvkm_fifo_chan_func tu102_fifo_gpfifo = { .dtor = gk104_fifo_gpfifo_dtor, - .init = gk104_fifo_gpfifo_init, - .fini = gk104_fifo_gpfifo_fini, .engine_ctor = gk104_fifo_gpfifo_engine_ctor, .engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_init = gv100_fifo_gpfifo_engine_init, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 4ff2c75f53ab..29a83ed3404f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -98,22 +98,20 @@ gv100_runl_preempt(struct nvkm_runl *runl) } void -gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan, - struct nvkm_memory *memory, u32 offset) +gv100_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset) { - struct nvkm_memory *usermem = chan->fifo->user.mem; - const u64 user = nvkm_memory_addr(usermem) + (chan->base.chid * 0x200); - const u64 inst = chan->base.inst->addr; + struct nvkm_memory *usermem = gk104_fifo(chan->cgrp->runl->fifo)->user.mem; + const u64 user = nvkm_memory_addr(usermem) + (chan->id * 0x200); + const u64 inst = chan->inst->addr; - nvkm_wo32(memory, offset + 0x0, lower_32_bits(user)); + nvkm_wo32(memory, offset + 0x0, lower_32_bits(user) | chan->runq << 1); nvkm_wo32(memory, offset + 0x4, upper_32_bits(user)); - nvkm_wo32(memory, offset + 0x8, lower_32_bits(inst) | chan->base.chid); + nvkm_wo32(memory, offset + 0x8, lower_32_bits(inst) | chan->id); nvkm_wo32(memory, offset + 0xc, upper_32_bits(inst)); } void -gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp, - struct nvkm_memory *memory, u32 offset) +gv100_runl_insert_cgrp(struct nvkm_cgrp *cgrp, struct nvkm_memory *memory, u64 offset) { nvkm_wo32(memory, offset + 0x0, (128 << 24) | (3 << 16) | 0x00000001); nvkm_wo32(memory, offset + 0x4, cgrp->chan_nr); @@ -121,16 +119,14 @@ gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp, nvkm_wo32(memory, offset + 0xc, 0x00000000); } -static const struct gk104_fifo_runlist_func -gv100_fifo_runlist = { - .size = 16, - .cgrp = gv100_fifo_runlist_cgrp, - .chan = gv100_fifo_runlist_chan, - .commit = gk104_fifo_runlist_commit, -}; - static const struct nvkm_runl_func gv100_runl = { + .runqs = 2, + .size = 16, + .update = nv50_runl_update, + .insert_cgrp = gv100_runl_insert_cgrp, + .insert_chan = gv100_runl_insert_chan, + .commit = gk104_runl_commit, .wait = nv50_runl_wait, .pending = gk104_runl_pending, .block = gk104_runl_block, @@ -401,7 +397,6 @@ gv100_fifo = { .intr_ctxsw_timeout = gv100_fifo_intr_ctxsw_timeout, .mmu_fault = &gv100_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &gv100_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &gv100_runl, .runq = &gv100_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 38d36749862c..6a069e84006c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -82,36 +82,6 @@ const struct nvkm_engn_func nv50_engn_sw = { }; -static void -nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo) -{ - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_memory *cur; - int i, p; - - cur = fifo->runlist[fifo->cur_runlist]; - fifo->cur_runlist = !fifo->cur_runlist; - - nvkm_kmap(cur); - for (i = 0, p = 0; i < fifo->base.nr; i++) { - if (nvkm_rd32(device, 0x002600 + (i * 4)) & 0x80000000) - nvkm_wo32(cur, p++ * 4, i); - } - nvkm_done(cur); - - nvkm_wr32(device, 0x0032f4, nvkm_memory_addr(cur) >> 12); - nvkm_wr32(device, 0x0032ec, p); - nvkm_wr32(device, 0x002500, 0x00000101); -} - -void -nv50_fifo_runlist_update(struct nv50_fifo *fifo) -{ - mutex_lock(&fifo->base.mutex); - nv50_fifo_runlist_update_locked(fifo); - mutex_unlock(&fifo->base.mutex); -} - static bool nv50_runl_pending(struct nvkm_runl *runl) { @@ -132,17 +102,112 @@ nv50_runl_wait(struct nvkm_runl *runl) return -ETIMEDOUT; } +static void +nv50_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count) +{ + struct nvkm_device *device = runl->fifo->engine.subdev.device; + u64 addr = nvkm_memory_addr(memory) + start; + + nvkm_wr32(device, 0x0032f4, addr >> 12); + nvkm_wr32(device, 0x0032ec, count); +} + +static void +nv50_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset) +{ + nvkm_wo32(memory, offset, chan->id); +} + +static struct nvkm_memory * +nv50_runl_alloc(struct nvkm_runl *runl, u32 *offset) +{ + const u32 segment = ALIGN((runl->cgrp_nr + runl->chan_nr) * runl->func->size, 0x1000); + const u32 maxsize = (runl->cgid ? runl->cgid->nr : 0) + runl->chid->nr; + int ret; + + if (unlikely(!runl->mem)) { + ret = nvkm_memory_new(runl->fifo->engine.subdev.device, NVKM_MEM_TARGET_INST, + maxsize * 2 * runl->func->size, 0, false, &runl->mem); + if (ret) { + RUNL_ERROR(runl, "alloc %d\n", ret); + return ERR_PTR(ret); + } + } else { + if (runl->offset + segment >= nvkm_memory_size(runl->mem)) { + ret = runl->func->wait(runl); + if (ret) { + RUNL_DEBUG(runl, "rewind timeout"); + return ERR_PTR(ret); + } + + runl->offset = 0; + } + } + + *offset = runl->offset; + runl->offset += segment; + return runl->mem; +} + +int +nv50_runl_update(struct nvkm_runl *runl) +{ + struct nvkm_memory *memory; + struct nvkm_cgrp *cgrp; + struct nvkm_chan *chan; + u32 start, offset, count; + + /*TODO: prio, interleaving. */ + + RUNL_TRACE(runl, "RAMRL: update cgrps:%d chans:%d", runl->cgrp_nr, runl->chan_nr); + memory = nv50_runl_alloc(runl, &start); + if (IS_ERR(memory)) + return PTR_ERR(memory); + + RUNL_TRACE(runl, "RAMRL: update start:%08x", start); + offset = start; + + nvkm_kmap(memory); + nvkm_runl_foreach_cgrp(cgrp, runl) { + if (cgrp->hw) { + CGRP_TRACE(cgrp, " RAMRL+%08x: chans:%d", offset, cgrp->chan_nr); + runl->func->insert_cgrp(cgrp, memory, offset); + offset += runl->func->size; + } + + nvkm_cgrp_foreach_chan(chan, cgrp) { + CHAN_TRACE(chan, "RAMRL+%08x: [%s]", offset, chan->name); + runl->func->insert_chan(chan, memory, offset); + offset += runl->func->size; + } + } + nvkm_done(memory); + + /*TODO: look into using features on newer HW to guarantee forward progress. */ + list_rotate_left(&runl->cgrps); + + count = (offset - start) / runl->func->size; + RUNL_TRACE(runl, "RAMRL: commit start:%08x count:%d", start, count); + + runl->func->commit(runl, memory, start, count); + return 0; +} + const struct nvkm_runl_func nv50_runl = { + .size = 4, + .update = nv50_runl_update, + .insert_chan = nv50_runl_insert_chan, + .commit = nv50_runl_commit, .wait = nv50_runl_wait, .pending = nv50_runl_pending, }; void -nv50_fifo_init(struct nvkm_fifo *base) +nv50_fifo_init(struct nvkm_fifo *fifo) { - struct nv50_fifo *fifo = nv50_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_runl *runl = nvkm_runl_first(fifo); + struct nvkm_device *device = fifo->engine.subdev.device; int i; nvkm_mask(device, 0x000200, 0x00000100, 0x00000000); @@ -155,7 +220,9 @@ nv50_fifo_init(struct nvkm_fifo *base) for (i = 0; i < 128; i++) nvkm_wr32(device, 0x002600 + (i * 4), 0x00000000); - nv50_fifo_runlist_update_locked(fifo); + + atomic_set(&runl->changed, 1); + runl->func->update(runl); nvkm_wr32(device, 0x003200, 0x00000001); nvkm_wr32(device, 0x003250, 0x00000001); @@ -175,28 +242,10 @@ nv50_fifo_chid_nr(struct nvkm_fifo *fifo) return 128; } -int -nv50_fifo_oneinit(struct nvkm_fifo *base) -{ - struct nv50_fifo *fifo = nv50_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; - int ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, - false, &fifo->runlist[0]); - if (ret) - return ret; - - return nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, - false, &fifo->runlist[1]); -} - void * nv50_fifo_dtor(struct nvkm_fifo *base) { struct nv50_fifo *fifo = nv50_fifo(base); - nvkm_memory_unref(&fifo->runlist[1]); - nvkm_memory_unref(&fifo->runlist[0]); return fifo; } @@ -221,7 +270,6 @@ nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, static const struct nvkm_fifo_func nv50_fifo = { .dtor = nv50_fifo_dtor, - .oneinit = nv50_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = nv50_fifo_chid_ctor, .runl_ctor = nv04_fifo_runl_ctor, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h index db5fb45a3aa5..1573ea430cf3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h @@ -6,17 +6,12 @@ struct nv50_fifo { struct nvkm_fifo base; - struct nvkm_memory *runlist[2]; - int cur_runlist; }; int nv50_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_fifo **); void *nv50_fifo_dtor(struct nvkm_fifo *); -int nv50_fifo_oneinit(struct nvkm_fifo *); -void nv50_fifo_init(struct nvkm_fifo *); -void nv50_fifo_runlist_update(struct nv50_fifo *); int g84_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 48153d8bba32..78c6d2218398 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -10,7 +10,6 @@ struct nvkm_memory; struct nvkm_runl; struct nvkm_runq; struct gk104_fifo; -struct gk104_fifo_chan; struct nvkm_fifo_chan_oclass; struct nvkm_fifo_func { @@ -42,16 +41,6 @@ struct nvkm_fifo_func { void (*pause)(struct nvkm_fifo *, unsigned long *); void (*start)(struct nvkm_fifo *, unsigned long *); - const struct gk104_fifo_runlist_func { - u8 size; - void (*cgrp)(struct nvkm_fifo_cgrp *, - struct nvkm_memory *, u32 offset); - void (*chan)(struct gk104_fifo_chan *, - struct nvkm_memory *, u32 offset); - void (*commit)(struct gk104_fifo *, int runl, - struct nvkm_memory *, int entries); - } *runlist; - const struct nvkm_event_func *nonstall; const struct nvkm_runl_func *runl; @@ -98,7 +87,9 @@ int nv10_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_ctor(struct nvkm_fifo *, int); +void nv50_fifo_init(struct nvkm_fifo *); extern const struct nvkm_runl_func nv50_runl; +int nv50_runl_update(struct nvkm_runl *); int nv50_runl_wait(struct nvkm_runl *); extern const struct nvkm_engn_func nv50_engn_sw; void nv50_chan_unbind(struct nvkm_chan *); @@ -140,6 +131,8 @@ extern const struct nvkm_enum gk104_fifo_mmu_fault_reason[]; extern const struct nvkm_enum gk104_fifo_mmu_fault_hubclient[]; extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[]; int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); +void gk104_runl_insert_chan(struct nvkm_chan *, struct nvkm_memory *, u64); +void gk104_runl_commit(struct nvkm_runl *, struct nvkm_memory *, u32, int); bool gk104_runl_pending(struct nvkm_runl *); void gk104_runl_block(struct nvkm_runl *, u32); void gk104_runl_allow(struct nvkm_runl *, u32); @@ -162,6 +155,7 @@ void gk104_chan_stop(struct nvkm_chan *); int gk110_fifo_chid_ctor(struct nvkm_fifo *, int); extern const struct nvkm_runl_func gk110_runl; extern const struct nvkm_cgrp_func gk110_cgrp; +void gk110_runl_insert_cgrp(struct nvkm_cgrp *, struct nvkm_memory *, u64); extern const struct nvkm_chan_func gk110_chan; void gk110_chan_preempt(struct nvkm_chan *); @@ -180,6 +174,8 @@ extern const struct nvkm_enum gv100_fifo_mmu_fault_access[]; extern const struct nvkm_enum gv100_fifo_mmu_fault_reason[]; extern const struct nvkm_enum gv100_fifo_mmu_fault_hubclient[]; extern const struct nvkm_enum gv100_fifo_mmu_fault_gpcclient[]; +void gv100_runl_insert_cgrp(struct nvkm_cgrp *, struct nvkm_memory *, u64); +void gv100_runl_insert_chan(struct nvkm_chan *, struct nvkm_memory *, u64); void gv100_runl_preempt(struct nvkm_runl *); extern const struct nvkm_runq_func gv100_runq; extern const struct nvkm_engn_func gv100_engn; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index 27c688d11464..e654c1c4f769 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -54,9 +54,6 @@ nvkm_engn_cgrp_get(struct nvkm_engn *engn, unsigned long *pirqflags) return cgrp; } -#include "gf100.h" -#include "gk104.h" - static void nvkm_runl_rc(struct nvkm_runl *runl) { @@ -79,8 +76,10 @@ nvkm_runl_rc(struct nvkm_runl *runl) state = atomic_cmpxchg(&cgrp->rc, NVKM_CGRP_RC_PENDING, NVKM_CGRP_RC_RUNNING); if (state == NVKM_CGRP_RC_PENDING) { /* Disable all channels in them, and remove from runlist. */ - nvkm_cgrp_foreach_chan_safe(chan, ctmp, cgrp) + nvkm_cgrp_foreach_chan_safe(chan, ctmp, cgrp) { nvkm_chan_error(chan, false); + nvkm_chan_remove_locked(chan); + } } } @@ -119,16 +118,14 @@ nvkm_runl_rc(struct nvkm_runl *runl) } /* Submit runlist update, and clear any remaining exception state. */ - if (runl->fifo->engine.subdev.device->card_type < NV_E0) - gf100_fifo_runlist_commit(gf100_fifo(runl->fifo)); - else - gk104_fifo_runlist_update(gk104_fifo(runl->fifo), runl->id); + runl->func->update(runl); if (runl->func->fault_clear) runl->func->fault_clear(runl); /* Unblock runlist processing. */ while (rc--) nvkm_runl_allow(runl); + runl->func->wait(runl); } static void @@ -270,6 +267,16 @@ nvkm_runl_update_pending(struct nvkm_runl *runl) return true; } +void +nvkm_runl_update_locked(struct nvkm_runl *runl, bool wait) +{ + if (atomic_xchg(&runl->changed, 0) && runl->func->update) { + runl->func->update(runl); + if (wait) + runl->func->wait(runl); + } +} + void nvkm_runl_allow(struct nvkm_runl *runl) { @@ -309,6 +316,8 @@ nvkm_runl_del(struct nvkm_runl *runl) { struct nvkm_engn *engn, *engt; + nvkm_memory_unref(&runl->mem); + list_for_each_entry_safe(engn, engt, &runl->engns, head) { list_del(&engn->head); kfree(engn); @@ -395,6 +404,7 @@ nvkm_runl_new(struct nvkm_fifo *fifo, int runi, u32 addr, int id_nr) runl->addr = addr; INIT_LIST_HEAD(&runl->engns); INIT_LIST_HEAD(&runl->cgrps); + atomic_set(&runl->changed, 0); mutex_init(&runl->mutex); INIT_WORK(&runl->work, nvkm_runl_work); atomic_set(&runl->rc_triggered, 0); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index 47bffc7bb7c0..c3b469356d5d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -2,6 +2,7 @@ #define __NVKM_RUNL_H__ #include struct nvkm_cgrp; +struct nvkm_chan; struct nvkm_memory; enum nvkm_subdev_type; @@ -28,6 +29,12 @@ struct nvkm_engn { struct nvkm_runl { const struct nvkm_runl_func { + int runqs; + u8 size; + int (*update)(struct nvkm_runl *); + void (*insert_cgrp)(struct nvkm_cgrp *, struct nvkm_memory *, u64 offset); + void (*insert_chan)(struct nvkm_chan *, struct nvkm_memory *, u64 offset); + void (*commit)(struct nvkm_runl *, struct nvkm_memory *, u32 start, int count); int (*wait)(struct nvkm_runl *); bool (*pending)(struct nvkm_runl *); void (*block)(struct nvkm_runl *, u32 engm); @@ -52,6 +59,9 @@ struct nvkm_runl { struct list_head cgrps; int cgrp_nr; int chan_nr; + atomic_t changed; + struct nvkm_memory *mem; + u32 offset; struct mutex mutex; int blocked; @@ -71,6 +81,7 @@ void nvkm_runl_del(struct nvkm_runl *); void nvkm_runl_fini(struct nvkm_runl *); void nvkm_runl_block(struct nvkm_runl *); void nvkm_runl_allow(struct nvkm_runl *); +void nvkm_runl_update_locked(struct nvkm_runl *, bool wait); bool nvkm_runl_update_pending(struct nvkm_runl *); int nvkm_runl_preempt_wait(struct nvkm_runl *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 724a99a5597f..babadc8641dc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -66,28 +66,25 @@ tu102_runl_pending(struct nvkm_runl *runl) } static void -tu102_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, - struct nvkm_memory *mem, int nr) +tu102_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count) { - struct nvkm_device *device = fifo->base.engine.subdev.device; - u64 addr = nvkm_memory_addr(mem); + struct nvkm_device *device = runl->fifo->engine.subdev.device; + u64 addr = nvkm_memory_addr(memory) + start; /*XXX: target? */ - nvkm_wr32(device, 0x002b00 + (runl * 0x10), lower_32_bits(addr)); - nvkm_wr32(device, 0x002b04 + (runl * 0x10), upper_32_bits(addr)); - nvkm_wr32(device, 0x002b08 + (runl * 0x10), nr); + nvkm_wr32(device, 0x002b00 + (runl->id * 0x10), lower_32_bits(addr)); + nvkm_wr32(device, 0x002b04 + (runl->id * 0x10), upper_32_bits(addr)); + nvkm_wr32(device, 0x002b08 + (runl->id * 0x10), count); } -static const struct gk104_fifo_runlist_func -tu102_fifo_runlist = { - .size = 16, - .cgrp = gv100_fifo_runlist_cgrp, - .chan = gv100_fifo_runlist_chan, - .commit = tu102_fifo_runlist_commit, -}; - static const struct nvkm_runl_func tu102_runl = { + .runqs = 2, + .size = 16, + .update = nv50_runl_update, + .insert_cgrp = gv100_runl_insert_cgrp, + .insert_chan = gv100_runl_insert_chan, + .commit = tu102_runl_commit, .wait = nv50_runl_wait, .pending = tu102_runl_pending, .block = gk104_runl_block, @@ -274,7 +271,6 @@ tu102_fifo = { .intr = tu102_fifo_intr, .mmu_fault = &tu102_fifo_mmu_fault, .engine_id = gk104_fifo_engine_id, - .runlist = &tu102_fifo_runlist, .nonstall = &gf100_fifo_nonstall, .runl = &tu102_runl, .runq = &gv100_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index 1fe7bd6a9aa8..c68ed6f71d4d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -213,14 +213,9 @@ static int nvkm_uchan_fini(struct nvkm_object *object, bool suspend) { struct nvkm_chan *chan = nvkm_uchan(object)->chan; - int ret; nvkm_chan_block(chan); - nvkm_chan_preempt(chan, true); - - ret = chan->object.func->fini(&chan->object, suspend); - if (ret && suspend) - return ret; + nvkm_chan_remove(chan, true); if (chan->func->unbind) chan->func->unbind(chan); @@ -240,8 +235,8 @@ nvkm_uchan_init(struct nvkm_object *object) chan->func->bind(chan); nvkm_chan_allow(chan); - - return chan->object.func->init(&chan->object); + nvkm_chan_insert(chan); + return 0; } static void * -- cgit v1.2.3 From d3e7a4392c82ec2d3c573cdc0fbcc843f3d76b12 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:35 +1000 Subject: drm/nouveau/fifo: add RAMIN info to nvkm_chan_func Currently provided by {chan,dma,gpfifo}*.c, and those are going away. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 4 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 41 ++++++++++++---------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 6 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 8 +++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 6 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 7 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 3 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 1 + 16 files changed, 64 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 2d34f1944d64..02a725d7bf39 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -19,6 +19,8 @@ struct nvkm_chan { struct nvkm_cgrp *cgrp; int runq; + struct nvkm_gpuobj *inst; + struct nvkm_vmm *vmm; union { int id; int chid; }; /*FIXME: remove later */ spinlock_t lock; @@ -31,9 +33,7 @@ struct nvkm_chan { struct nvkm_object object; struct list_head head; - struct nvkm_gpuobj *inst; struct nvkm_gpuobj *push; - struct nvkm_vmm *vmm; u64 addr; u32 size; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 3832a9aad80a..5b6377ec0df0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -602,39 +602,44 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, chan->cgrp = nvkm_cgrp_ref(cgrp); } - /* instance memory */ - ret = nvkm_gpuobj_new(device, size, align, zero, NULL, &chan->inst); - if (ret) + /* Allocate instance block. */ + ret = nvkm_gpuobj_new(device, func->inst->size, 0x1000, func->inst->zero, NULL, + &chan->inst); + if (ret) { + RUNL_DEBUG(runl, "inst %d", ret); return ret; - - /* allocate push buffer ctxdma instance */ - if (push) { - dmaobj = nvkm_dmaobj_search(client, push); - if (IS_ERR(dmaobj)) - return PTR_ERR(dmaobj); - - ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, - &chan->push); - if (ret) - return ret; } - /* channel address space */ - if (hvmm) { + /* Initialise virtual address-space. */ + if (func->inst->vmm) { struct nvkm_vmm *vmm = nvkm_uvmm_search(client, hvmm); if (IS_ERR(vmm)) return PTR_ERR(vmm); - if (vmm->mmu != device->mmu) + if (WARN_ON(vmm->mmu != device->mmu)) return -EINVAL; ret = nvkm_vmm_join(vmm, chan->inst->memory); - if (ret) + if (ret) { + RUNL_DEBUG(runl, "vmm %d", ret); return ret; + } chan->vmm = nvkm_vmm_ref(vmm); } + /* allocate push buffer ctxdma instance */ + if (push) { + dmaobj = nvkm_dmaobj_search(client, push); + if (IS_ERR(dmaobj)) + return PTR_ERR(dmaobj); + + ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, + &chan->push); + if (ret) + return ret; + } + /* Allocate channel ID. */ chan->id = nvkm_chid_get(runl->chid, chan); if (chan->id < 0) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 804441f30f44..0b764d28117e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -16,6 +16,12 @@ struct nvkm_cctx { }; struct nvkm_chan_func { + const struct nvkm_chan_func_inst { + u32 size; + bool zero; + bool vmm; + } *inst; + void (*bind)(struct nvkm_chan *); void (*unbind)(struct nvkm_chan *); void (*start)(struct nvkm_chan *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 18ec982f4f54..beb51dcb8863 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -42,6 +42,7 @@ g84_chan_bind(struct nvkm_chan *chan) const struct nvkm_chan_func g84_chan = { + .inst = &nv50_chan_inst, .bind = g84_chan_bind, .unbind = nv50_chan_unbind, .start = nv50_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 767507e0e239..8d1ffeb10c45 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -82,8 +82,16 @@ gf100_chan_bind(struct nvkm_chan *chan) nvkm_wr32(device, 0x003000 + (chan->id * 8), 0xc0000000 | chan->inst->addr >> 12); } +const struct nvkm_chan_func_inst +gf100_chan_inst = { + .size = 0x1000, + .zero = true, + .vmm = true, +}; + static const struct nvkm_chan_func gf100_chan = { + .inst = &gf100_chan_inst, .bind = gf100_chan_bind, .unbind = gf100_chan_unbind, .start = gf100_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index b5e698a223b6..a7e2b58f5029 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -81,6 +81,7 @@ gk104_chan_bind(struct nvkm_chan *chan) static const struct nvkm_chan_func gk104_chan = { + .inst = &gf100_chan_inst, .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 812fefff0925..5cc48a367c0d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -49,6 +49,7 @@ gk110_chan_preempt(struct nvkm_chan *chan) const struct nvkm_chan_func gk110_chan = { + .inst = &gf100_chan_inst, .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index c0eca7da7d09..f8bc89ac35ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -34,6 +34,7 @@ const struct nvkm_chan_func gm107_chan = { + .inst = &gf100_chan_inst, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 29a83ed3404f..db998c9de3ad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -40,6 +40,7 @@ gv100_chan_doorbell_handle(struct nvkm_chan *chan) static const struct nvkm_chan_func gv100_chan = { + .inst = &gf100_chan_inst, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index a0a28a81f7f4..aeb24f838e3f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -113,8 +113,14 @@ nv04_chan_start(struct nvkm_chan *chan) spin_unlock_irqrestore(&fifo->lock, flags); } +const struct nvkm_chan_func_inst +nv04_chan_inst = { + .size = 0x1000, +}; + static const struct nvkm_chan_func nv04_chan = { + .inst = &nv04_chan_inst, .start = nv04_chan_start, .stop = nv04_chan_stop, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index 8d302cb8ba8c..b9111fcfbcad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -45,6 +45,7 @@ nv10_fifo_ramfc[] = { static const struct nvkm_chan_func nv10_chan = { + .inst = &nv04_chan_inst, .start = nv04_chan_start, .stop = nv04_chan_stop, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index 7b1b90d285c1..e0ad8fabb2d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -54,6 +54,7 @@ nv17_fifo_ramfc[] = { static const struct nvkm_chan_func nv17_chan = { + .inst = &nv04_chan_inst, .start = nv04_chan_start, .stop = nv04_chan_stop, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index 19f7c0407e70..c2d892a7400b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -64,6 +64,7 @@ nv40_fifo_ramfc[] = { static const struct nvkm_chan_func nv40_chan = { + .inst = &nv04_chan_inst, .start = nv04_chan_start, .stop = nv04_chan_stop, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 6a069e84006c..384772d522af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -66,8 +66,15 @@ nv50_chan_bind(struct nvkm_chan *chan) nvkm_wr32(device, 0x002600 + (chan->id * 4), nv50_fifo_chan(chan)->ramfc->addr >> 12); } +const struct nvkm_chan_func_inst +nv50_chan_inst = { + .size = 0x10000, + .vmm = true, +}; + static const struct nvkm_chan_func nv50_chan = { + .inst = &nv50_chan_inst, .bind = nv50_chan_bind, .unbind = nv50_chan_unbind, .start = nv50_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 78c6d2218398..bf8067e97ba2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -80,6 +80,7 @@ void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); extern const struct nvkm_runl_func nv04_runl; extern const struct nvkm_engn_func nv04_engn; extern const struct nvkm_cgrp_func nv04_cgrp; +extern const struct nvkm_chan_func_inst nv04_chan_inst; void nv04_chan_start(struct nvkm_chan *); void nv04_chan_stop(struct nvkm_chan *); @@ -92,6 +93,7 @@ extern const struct nvkm_runl_func nv50_runl; int nv50_runl_update(struct nvkm_runl *); int nv50_runl_wait(struct nvkm_runl *); extern const struct nvkm_engn_func nv50_engn_sw; +extern const struct nvkm_chan_func_inst nv50_chan_inst; void nv50_chan_unbind(struct nvkm_chan *); void nv50_chan_start(struct nvkm_chan *); void nv50_chan_stop(struct nvkm_chan *); @@ -117,6 +119,7 @@ bool gf100_runq_intr(struct nvkm_runq *, struct nvkm_runl *); void gf100_engn_mmu_fault_trigger(struct nvkm_engn *); bool gf100_engn_mmu_fault_triggered(struct nvkm_engn *); extern const struct nvkm_engn_func gf100_engn_sw; +extern const struct nvkm_chan_func_inst gf100_chan_inst; void gf100_chan_preempt(struct nvkm_chan *); int gk104_fifo_chid_nr(struct nvkm_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index babadc8641dc..75e4c0db40bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -49,6 +49,7 @@ tu102_chan_start(struct nvkm_chan *chan) static const struct nvkm_chan_func tu102_chan = { + .inst = &gf100_chan_inst, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = tu102_chan_start, -- cgit v1.2.3 From fbe9f4337c1381710f17df0d74dd588d3d9784b2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:36 +1000 Subject: drm/nouveau/fifo: add USERD info to nvkm_chan_func And use it to cleanup multiple implementations of almost the same thing. - prepares for non-polled / client-provided USERD - only zeroes relevant "registers", rather than entire USERD Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 12 ++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 25 ++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 27 ++++------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 7 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 58 +++++++++++----------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 5 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 36 +++++--------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 6 --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 + .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 14 ++---- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 13 ++--- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 12 ++--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 11 +++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 8 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 8 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 8 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 6 +++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 10 +++- 23 files changed, 157 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 02a725d7bf39..95cb33b53228 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -23,6 +23,11 @@ struct nvkm_chan { struct nvkm_vmm *vmm; union { int id; int chid; }; /*FIXME: remove later */ + struct { + struct nvkm_memory *mem; + u32 base; + } userd; + spinlock_t lock; atomic_t blocked; atomic_t errored; @@ -34,8 +39,6 @@ struct nvkm_chan { struct list_head head; struct nvkm_gpuobj *push; - u64 addr; - u32 size; struct nvkm_fifo_engn engn[NVKM_FIFO_ENGN_NR]; }; @@ -63,6 +66,11 @@ struct nvkm_fifo { u32 chan_msec; } timeout; + struct { + struct nvkm_memory *mem; + struct nvkm_vma *bar1; + } userd; + int nr; spinlock_t lock; struct mutex mutex; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 0cbfb9225e6c..c77af1b3ffa0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -28,7 +28,9 @@ #include "runq.h" #include +#include #include +#include #include #include @@ -243,6 +245,25 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) } } + /* Allocate USERD + BAR1 polling area. */ + if (fifo->func->chan.func->userd->bar == 1) { + struct nvkm_vmm *bar1 = nvkm_bar_bar1_vmm(device); + + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, fifo->chid->nr * + fifo->func->chan.func->userd->size, 0, true, + &fifo->userd.mem); + if (ret) + return ret; + + ret = nvkm_vmm_get(bar1, 12, nvkm_memory_size(fifo->userd.mem), &fifo->userd.bar1); + if (ret) + return ret; + + ret = nvkm_memory_map(fifo->userd.mem, 0, bar1, fifo->userd.bar1, NULL, 0); + if (ret) + return ret; + } + if (fifo->func->oneinit) return fifo->func->oneinit(fifo); @@ -263,6 +284,10 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) struct nvkm_runq *runq, *rtmp; void *data = fifo; + if (fifo->userd.bar1) + nvkm_vmm_put(nvkm_bar_bar1_vmm(engine->subdev.device), &fifo->userd.bar1); + nvkm_memory_unref(&fifo->userd.mem); + list_for_each_entry_safe(runl, runt, &fifo->runls, head) nvkm_runl_del(runl); list_for_each_entry_safe(runq, rtmp, &fifo->runqs, head) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 5b6377ec0df0..0df089b692a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -328,17 +328,6 @@ nvkm_chan_preempt(struct nvkm_chan *chan, bool wait) return ret; } -static int -nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - *type = NVKM_OBJECT_MAP_IO; - *addr = chan->addr; - *size = chan->size; - return 0; -} - void nvkm_chan_remove_locked(struct nvkm_chan *chan) { @@ -445,6 +434,8 @@ nvkm_chan_del(struct nvkm_chan **pchan) if (!chan) return; + nvkm_memory_unref(&chan->userd.mem); + if (chan->cgrp) { nvkm_chid_put(chan->cgrp->runl->chid, chan->id, &chan->cgrp->lock); nvkm_cgrp_unref(&chan->cgrp); @@ -524,7 +515,6 @@ nvkm_chan_get_chid(struct nvkm_engine *engine, int id, unsigned long *pirqflags) static const struct nvkm_object_func nvkm_fifo_chan_func = { .dtor = nvkm_fifo_chan_dtor, - .map = nvkm_fifo_chan_map, }; int @@ -650,9 +640,14 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, if (cgrp->id < 0) cgrp->id = chan->id; - /* determine address of this channel's user registers */ - chan->addr = device->func->resource_addr(device, bar) + - base + user * chan->chid; - chan->size = user; + /* Initialise USERD. */ + if (1) { + chan->userd.mem = nvkm_memory_ref(fifo->userd.mem); + chan->userd.base = chan->id * chan->func->userd->size; + } + + if (chan->func->userd->clear) + chan->func->userd->clear(chan); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 0b764d28117e..54ef137bdfac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -22,6 +22,13 @@ struct nvkm_chan_func { bool vmm; } *inst; + const struct nvkm_chan_func_userd { + int bar; + u32 base; + u32 size; + void (*clear)(struct nvkm_chan *); + } *userd; + void (*bind)(struct nvkm_chan *); void (*unbind)(struct nvkm_chan *); void (*start)(struct nvkm_chan *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index beb51dcb8863..76ba98b4d3bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -43,6 +43,7 @@ g84_chan_bind(struct nvkm_chan *chan) const struct nvkm_chan_func g84_chan = { .inst = &nv50_chan_inst, + .userd = &nv50_chan_userd, .bind = g84_chan_bind, .unbind = nv50_chan_unbind, .start = nv50_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 8d1ffeb10c45..afee42440ff5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -82,6 +82,30 @@ gf100_chan_bind(struct nvkm_chan *chan) nvkm_wr32(device, 0x003000 + (chan->id * 8), 0xc0000000 | chan->inst->addr >> 12); } +void +gf100_chan_userd_clear(struct nvkm_chan *chan) +{ + nvkm_kmap(chan->userd.mem); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x040, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x044, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x048, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x04c, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x050, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x058, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x05c, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x060, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x088, 0x00000000); + nvkm_wo32(chan->userd.mem, chan->userd.base + 0x08c, 0x00000000); + nvkm_done(chan->userd.mem); +} + +static const struct nvkm_chan_func_userd +gf100_chan_userd = { + .bar = 1, + .size = 0x1000, + .clear = gf100_chan_userd_clear, +}; + const struct nvkm_chan_func_inst gf100_chan_inst = { .size = 0x1000, @@ -92,6 +116,7 @@ gf100_chan_inst = { static const struct nvkm_chan_func gf100_chan = { .inst = &gf100_chan_inst, + .userd = &gf100_chan_userd, .bind = gf100_chan_bind, .unbind = gf100_chan_unbind, .start = gf100_chan_start, @@ -807,13 +832,12 @@ gf100_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) } static void -gf100_fifo_init(struct nvkm_fifo *base) +gf100_fifo_init(struct nvkm_fifo *fifo) { - struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; nvkm_mask(device, 0x002200, 0x00000001, 0x00000001); - nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); + nvkm_wr32(device, 0x002254, 0x10000000 | fifo->userd.bar1->addr >> 12); nvkm_wr32(device, 0x002100, 0xffffffff); nvkm_wr32(device, 0x002140, 0x7fffffff); @@ -857,42 +881,16 @@ gf100_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr, &fifo->chid); } -static int -gf100_fifo_oneinit(struct nvkm_fifo *base) -{ - struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); - int ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000, - 0x1000, false, &fifo->user.mem); - if (ret) - return ret; - - ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem), - &fifo->user.bar); - if (ret) - return ret; - - return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0); -} - static void * gf100_fifo_dtor(struct nvkm_fifo *base) { struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; - nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar); - nvkm_memory_unref(&fifo->user.mem); return fifo; } static const struct nvkm_fifo_func gf100_fifo = { .dtor = gf100_fifo_dtor, - .oneinit = gf100_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = gf100_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h index 42a950c00483..6027ee7dce5a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -8,10 +8,5 @@ struct gf100_fifo { struct nvkm_fifo base; - - struct { - struct nvkm_memory *mem; - struct nvkm_vma *bar; - } user; }; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index a7e2b58f5029..61966d433bce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -31,7 +31,6 @@ #include "changk104.h" #include -#include #include #include @@ -79,9 +78,17 @@ gk104_chan_bind(struct nvkm_chan *chan) gk104_chan_bind_inst(chan); } +const struct nvkm_chan_func_userd +gk104_chan_userd = { + .bar = 1, + .size = 0x200, + .clear = gf100_chan_userd_clear, +}; + static const struct nvkm_chan_func gk104_chan = { .inst = &gf100_chan_inst, + .userd = &gk104_chan_userd, .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, .start = gk104_chan_start, @@ -659,12 +666,12 @@ gk104_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) } void -gk104_fifo_init(struct nvkm_fifo *base) +gk104_fifo_init(struct nvkm_fifo *fifo) { - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_device *device = fifo->engine.subdev.device; - nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); + if (fifo->func->chan.func->userd->bar == 1) + nvkm_wr32(device, 0x002254, 0x10000000 | fifo->userd.bar1->addr >> 12); nvkm_wr32(device, 0x002100, 0xffffffff); nvkm_wr32(device, 0x002140, 0x7fffffff); @@ -728,9 +735,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) struct gk104_fifo *fifo = gk104_fifo(base); struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); struct nvkm_top_device *tdev; - int ret; /* Determine runlist configuration from topology device info. */ list_for_each_entry(tdev, &device->top->device, head) { @@ -748,28 +753,13 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) fifo->runlist_nr = max(fifo->runlist_nr, tdev->runlist + 1); } - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - fifo->base.nr * 0x200, 0x1000, true, - &fifo->user.mem); - if (ret) - return ret; - - ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem), - &fifo->user.bar); - if (ret) - return ret; - - return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0); + return 0; } void * gk104_fifo_dtor(struct nvkm_fifo *base) { struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; - - nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar); - nvkm_memory_unref(&fifo->user.mem); return fifo; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 3915b3b9e6bf..3bcf0720f89d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -24,16 +24,10 @@ struct gk104_fifo { u32 engm_sw; } runlist[16]; int runlist_nr; - - struct { - struct nvkm_memory *mem; - struct nvkm_vma *bar; - } user; }; int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int index, int nr, struct nvkm_fifo **); void *gk104_fifo_dtor(struct nvkm_fifo *base); int gk104_fifo_oneinit(struct nvkm_fifo *); -void gk104_fifo_init(struct nvkm_fifo *base); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 5cc48a367c0d..7ff7a435d890 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -50,6 +50,7 @@ gk110_chan_preempt(struct nvkm_chan *chan) const struct nvkm_chan_func gk110_chan = { .inst = &gf100_chan_inst, + .userd = &gk104_chan_userd, .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index f8bc89ac35ab..cc2638018db7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -35,6 +35,7 @@ const struct nvkm_chan_func gm107_chan = { .inst = &gf100_chan_inst, + .userd = &gk104_chan_userd, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 871f199ddccf..1e459afc36ea 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -153,7 +153,7 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, struct nvkm_object *parent = oclass->parent; struct gf100_fifo_chan *chan; u64 usermem, ioffset, ilength; - int ret = -ENOSYS, i; + int ret = -ENOSYS; nvif_ioctl(parent, "create channel gpfifo size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { @@ -181,25 +181,17 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, BIT(GF100_FIFO_ENGN_CE0) | BIT(GF100_FIFO_ENGN_CE1) | BIT(GF100_FIFO_ENGN_SW), - 1, fifo->user.bar->addr, 0x1000, + 0, 0, 0, oclass, &chan->base); if (ret) return ret; args->v0.chid = chan->base.chid; - /* clear channel control registers */ - - usermem = chan->base.chid * 0x1000; + usermem = nvkm_memory_addr(chan->base.userd.mem) + chan->base.userd.base; ioffset = args->v0.ioffset; ilength = order_base_2(args->v0.ilength / 8); - nvkm_kmap(fifo->user.mem); - for (i = 0; i < 0x1000; i += 4) - nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000); - nvkm_done(fifo->user.mem); - usermem = nvkm_memory_addr(fifo->user.mem) + usermem; - /* RAMFC */ nvkm_kmap(chan->base.inst); nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem)); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index aa3ea7f7f8e1..b02ec7c545cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -175,7 +175,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, struct nvkm_object **pobject) { struct gk104_fifo_chan *chan; - int runlist = ffs(*runlists) -1, ret, i; + int runlist = ffs(*runlists) -1, ret; u64 usermem; if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) @@ -191,7 +191,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, 0x1000, 0x1000, true, vmm, 0, fifo->runlist[runlist].engm_sw, - 1, fifo->user.bar->addr, 0x200, + 0, 0, 0, oclass, &chan->base); if (ret) return ret; @@ -199,16 +199,9 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, *chid = chan->base.chid; *inst = chan->base.inst->addr; - /* Clear channel control registers. */ - usermem = chan->base.chid * 0x200; + usermem = nvkm_memory_addr(chan->base.userd.mem) + chan->base.userd.base; ilength = order_base_2(ilength / 8); - nvkm_kmap(fifo->user.mem); - for (i = 0; i < 0x200; i += 4) - nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000); - nvkm_done(fifo->user.mem); - usermem = nvkm_memory_addr(fifo->user.mem) + usermem; - /* RAMFC */ nvkm_kmap(chan->base.inst); nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem)); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 428901abdb81..317787954a3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -119,7 +119,7 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, struct nvkm_object **pobject) { struct gk104_fifo_chan *chan; - int runlist = ffs(*runlists) -1, ret, i; + int runlist = ffs(*runlists) -1, ret; u64 usermem; if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) @@ -134,7 +134,7 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, chan->runl = runlist; ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm, - 0, fifo->runlist[runlist].engm, 1, fifo->user.bar->addr, 0x200, + 0, fifo->runlist[runlist].engm, 0, 0, 0, oclass, &chan->base); if (ret) return ret; @@ -144,15 +144,9 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, *token = chan->base.func->doorbell_handle(&chan->base); /* Clear channel control registers. */ - usermem = chan->base.chid * 0x200; + usermem = nvkm_memory_addr(chan->base.userd.mem) + chan->base.userd.base; ilength = order_base_2(ilength / 8); - nvkm_kmap(fifo->user.mem); - for (i = 0; i < 0x200; i += 4) - nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000); - nvkm_done(fifo->user.mem); - usermem = nvkm_memory_addr(fifo->user.mem) + usermem; - /* RAMFC */ nvkm_kmap(chan->base.inst); nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem)); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index db998c9de3ad..9611bd73c114 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -38,9 +38,17 @@ gv100_chan_doorbell_handle(struct nvkm_chan *chan) return chan->id; } +const struct nvkm_chan_func_userd +gv100_chan_userd = { + .bar = 1, /*FIXME: hw doesn't have poller, flip to user-allocated in uapi commit. */ + .size = 0x200, + .clear = gf100_chan_userd_clear, +}; + static const struct nvkm_chan_func gv100_chan = { .inst = &gf100_chan_inst, + .userd = &gv100_chan_userd, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = gk104_chan_start, @@ -101,8 +109,7 @@ gv100_runl_preempt(struct nvkm_runl *runl) void gv100_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset) { - struct nvkm_memory *usermem = gk104_fifo(chan->cgrp->runl->fifo)->user.mem; - const u64 user = nvkm_memory_addr(usermem) + (chan->id * 0x200); + const u64 user = nvkm_memory_addr(chan->userd.mem) + chan->userd.base; const u64 inst = chan->inst->addr; nvkm_wo32(memory, offset + 0x0, lower_32_bits(user) | chan->runq << 1); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index aeb24f838e3f..f4207100f20c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -113,6 +113,13 @@ nv04_chan_start(struct nvkm_chan *chan) spin_unlock_irqrestore(&fifo->lock, flags); } +const struct nvkm_chan_func_userd +nv04_chan_userd = { + .bar = 0, + .base = 0x800000, + .size = 0x010000, +}; + const struct nvkm_chan_func_inst nv04_chan_inst = { .size = 0x1000, @@ -121,6 +128,7 @@ nv04_chan_inst = { static const struct nvkm_chan_func nv04_chan = { .inst = &nv04_chan_inst, + .userd = &nv04_chan_userd, .start = nv04_chan_start, .stop = nv04_chan_stop, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index b9111fcfbcad..bbad5ffa179b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -46,6 +46,7 @@ nv10_fifo_ramfc[] = { static const struct nvkm_chan_func nv10_chan = { .inst = &nv04_chan_inst, + .userd = &nv04_chan_userd, .start = nv04_chan_start, .stop = nv04_chan_stop, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index e0ad8fabb2d6..b0dfa6f1a1d3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -55,6 +55,7 @@ nv17_fifo_ramfc[] = { static const struct nvkm_chan_func nv17_chan = { .inst = &nv04_chan_inst, + .userd = &nv04_chan_userd, .start = nv04_chan_start, .stop = nv04_chan_stop, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index c2d892a7400b..c2dc2d7abc9d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -62,9 +62,17 @@ nv40_fifo_ramfc[] = { {} }; +static const struct nvkm_chan_func_userd +nv40_chan_userd = { + .bar = 0, + .base = 0xc00000, + .size = 0x001000, +}; + static const struct nvkm_chan_func nv40_chan = { .inst = &nv04_chan_inst, + .userd = &nv40_chan_userd, .start = nv04_chan_start, .stop = nv04_chan_stop, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 384772d522af..24b458048180 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -66,6 +66,13 @@ nv50_chan_bind(struct nvkm_chan *chan) nvkm_wr32(device, 0x002600 + (chan->id * 4), nv50_fifo_chan(chan)->ramfc->addr >> 12); } +const struct nvkm_chan_func_userd +nv50_chan_userd = { + .bar = 0, + .base = 0xc00000, + .size = 0x002000, +}; + const struct nvkm_chan_func_inst nv50_chan_inst = { .size = 0x10000, @@ -75,6 +82,7 @@ nv50_chan_inst = { static const struct nvkm_chan_func nv50_chan = { .inst = &nv50_chan_inst, + .userd = &nv50_chan_userd, .bind = nv50_chan_bind, .unbind = nv50_chan_unbind, .start = nv50_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index bf8067e97ba2..c56deb78e9cc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -81,6 +81,7 @@ extern const struct nvkm_runl_func nv04_runl; extern const struct nvkm_engn_func nv04_engn; extern const struct nvkm_cgrp_func nv04_cgrp; extern const struct nvkm_chan_func_inst nv04_chan_inst; +extern const struct nvkm_chan_func_userd nv04_chan_userd; void nv04_chan_start(struct nvkm_chan *); void nv04_chan_stop(struct nvkm_chan *); @@ -94,6 +95,7 @@ int nv50_runl_update(struct nvkm_runl *); int nv50_runl_wait(struct nvkm_runl *); extern const struct nvkm_engn_func nv50_engn_sw; extern const struct nvkm_chan_func_inst nv50_chan_inst; +extern const struct nvkm_chan_func_userd nv50_chan_userd; void nv50_chan_unbind(struct nvkm_chan *); void nv50_chan_start(struct nvkm_chan *); void nv50_chan_stop(struct nvkm_chan *); @@ -120,10 +122,12 @@ void gf100_engn_mmu_fault_trigger(struct nvkm_engn *); bool gf100_engn_mmu_fault_triggered(struct nvkm_engn *); extern const struct nvkm_engn_func gf100_engn_sw; extern const struct nvkm_chan_func_inst gf100_chan_inst; +void gf100_chan_userd_clear(struct nvkm_chan *); void gf100_chan_preempt(struct nvkm_chan *); int gk104_fifo_chid_nr(struct nvkm_fifo *); int gk104_fifo_runl_ctor(struct nvkm_fifo *); +void gk104_fifo_init(struct nvkm_fifo *); void gk104_fifo_init_pbdmas(struct nvkm_fifo *, u32); irqreturn_t gk104_fifo_intr(struct nvkm_inth *); void gk104_fifo_intr_runlist(struct nvkm_fifo *); @@ -149,6 +153,7 @@ extern const struct nvkm_engn_func gk104_engn; bool gk104_engn_chsw(struct nvkm_engn *); int gk104_engn_cxid(struct nvkm_engn *, bool *cgid); extern const struct nvkm_engn_func gk104_engn_ce; +extern const struct nvkm_chan_func_userd gk104_chan_userd; void gk104_chan_bind(struct nvkm_chan *); void gk104_chan_bind_inst(struct nvkm_chan *); void gk104_chan_unbind(struct nvkm_chan *); @@ -183,6 +188,7 @@ void gv100_runl_preempt(struct nvkm_runl *); extern const struct nvkm_runq_func gv100_runq; extern const struct nvkm_engn_func gv100_engn; extern const struct nvkm_engn_func gv100_engn_ce; +extern const struct nvkm_chan_func_userd gv100_chan_userd; void tu102_fifo_intr_ctxsw_timeout_info(struct nvkm_engn *, u32 info); extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 75e4c0db40bc..42d2975b82aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -50,6 +50,7 @@ tu102_chan_start(struct nvkm_chan *chan) static const struct nvkm_chan_func tu102_chan = { .inst = &gf100_chan_inst, + .userd = &gv100_chan_userd, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = tu102_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index c68ed6f71d4d..74584a29454a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -204,9 +204,17 @@ static int nvkm_uchan_map(struct nvkm_object *object, void *argv, u32 argc, enum nvkm_object_map *type, u64 *addr, u64 *size) { + struct nvkm_device *device = object->engine->subdev.device; struct nvkm_chan *chan = nvkm_uchan(object)->chan; - return chan->object.func->map(&chan->object, argv, argc, type, addr, size); + if (chan->func->userd->bar < 0) + return -ENOSYS; + + *type = NVKM_OBJECT_MAP_IO; + *addr = device->func->resource_addr(device, chan->func->userd->bar) + + chan->func->userd->base + chan->userd.base; + *size = chan->func->userd->size; + return 0; } static int -- cgit v1.2.3 From 3647c53bd7dada9053b46a5ca27eb3f7c5472416 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:36 +1000 Subject: drm/nouveau/fifo: add RAMFC info to nvkm_chan_func - adds support for specifying SUBDEVICE_ID for channel - rounds non-power-of-two GPFIFO sizes down, rather than up Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 7 ++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 22 ++++-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 15 ++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 26 +------ .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.c | 26 +------ .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.h | 3 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c | 27 +------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c | 16 +--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c | 16 +--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c | 17 +--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 60 ++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 34 ++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 34 ++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 + .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c | 18 +---- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 25 +----- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 24 +----- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 23 +----- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c | 16 +--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 32 ++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 90 ++++++++++++++++------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h | 9 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 59 ++++++++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 66 +++++++++++----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 84 +++++++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 54 ++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 3 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 1 + 29 files changed, 488 insertions(+), 321 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 95cb33b53228..1616a329db9e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -28,6 +28,13 @@ struct nvkm_chan { u32 base; } userd; + u32 ramfc_offset; + struct nvkm_gpuobj *ramfc; + struct nvkm_gpuobj *cache; + struct nvkm_gpuobj *eng; + struct nvkm_gpuobj *pgd; + struct nvkm_ramht *ramht; + spinlock_t lock; atomic_t blocked; atomic_t errored; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 0df089b692a9..00680b3ca9ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -29,8 +29,8 @@ #include "priv.h" #include -#include #include +#include #include #include @@ -434,6 +434,15 @@ nvkm_chan_del(struct nvkm_chan **pchan) if (!chan) return; + if (chan->func->ramfc->clear) + chan->func->ramfc->clear(chan); + + nvkm_ramht_del(&chan->ramht); + nvkm_gpuobj_del(&chan->pgd); + nvkm_gpuobj_del(&chan->eng); + nvkm_gpuobj_del(&chan->cache); + nvkm_gpuobj_del(&chan->ramfc); + nvkm_memory_unref(&chan->userd.mem); if (chan->cgrp) { @@ -618,16 +627,17 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, chan->vmm = nvkm_vmm_ref(vmm); } - /* allocate push buffer ctxdma instance */ - if (push) { + /* Allocate HW ctxdma for push buffer. */ + if (func->ramfc->ctxdma) { dmaobj = nvkm_dmaobj_search(client, push); if (IS_ERR(dmaobj)) return PTR_ERR(dmaobj); - ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, - &chan->push); - if (ret) + ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, &chan->push); + if (ret) { + RUNL_DEBUG(runl, "bind %d", ret); return ret; + } } /* Allocate channel ID. */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 54ef137bdfac..6e41eba0a7e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -29,6 +29,21 @@ struct nvkm_chan_func { void (*clear)(struct nvkm_chan *); } *userd; + const struct nvkm_chan_func_ramfc { + const struct nvkm_ramfc_layout { + unsigned bits:6; + unsigned ctxs:5; + unsigned ctxp:8; + unsigned regs:5; + unsigned regp; + } *layout; + int (*write)(struct nvkm_chan *, u64 offset, u64 length, u32 devm, bool priv); + void (*clear)(struct nvkm_chan *); + bool ctxdma; + u32 devm; + bool priv; + } *ramfc; + void (*bind)(struct nvkm_chan *); void (*unbind)(struct nvkm_chan *); void (*start)(struct nvkm_chan *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 64566b5cc23f..f5e3557b9e50 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -182,7 +182,6 @@ g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, const struct nvkm_oclass *oclass, struct nv50_fifo_chan *chan) { - struct nvkm_device *device = fifo->base.engine.subdev.device; int ret; if (!vmm) @@ -206,28 +205,5 @@ g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, BIT(G84_FIFO_ENGN_DMA), 0, 0xc00000, 0x2000, oclass, &chan->base); chan->fifo = fifo; - if (ret) - return ret; - - ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->base.inst, - &chan->eng); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst, - &chan->pgd); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->base.inst, - &chan->cache); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->base.inst, - &chan->ramfc); - if (ret) - return ret; - - return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); + return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c index 5d6f82236c50..0bf59c4e92b9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c @@ -187,11 +187,6 @@ void * nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) { struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - nvkm_ramht_del(&chan->ramht); - nvkm_gpuobj_del(&chan->pgd); - nvkm_gpuobj_del(&chan->eng); - nvkm_gpuobj_del(&chan->cache); - nvkm_gpuobj_del(&chan->ramfc); return chan; } @@ -211,7 +206,6 @@ nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, const struct nvkm_oclass *oclass, struct nv50_fifo_chan *chan) { - struct nvkm_device *device = fifo->base.engine.subdev.device; int ret; if (!vmm) @@ -225,23 +219,5 @@ nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, BIT(NV50_FIFO_ENGN_DMA), 0, 0xc00000, 0x2000, oclass, &chan->base); chan->fifo = fifo; - if (ret) - return ret; - - ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, chan->base.inst, - &chan->ramfc); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(device, 0x1200, 0, true, chan->base.inst, - &chan->eng); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst, - &chan->pgd); - if (ret) - return ret; - - return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); + return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h index ce7d61e8d297..343356a0e5ef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h @@ -9,10 +9,7 @@ struct nv50_fifo_chan { struct nv50_fifo *fifo; struct nvkm_fifo_chan base; - struct nvkm_gpuobj *ramfc; - struct nvkm_gpuobj *cache; struct nvkm_gpuobj *eng; - struct nvkm_gpuobj *pgd; struct nvkm_ramht *ramht; #define NV50_FIFO_ENGN_SW 0 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c index d515cf08fc3b..4220120d8bb8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c @@ -73,15 +73,6 @@ void * nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base) { struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nv04_fifo *fifo = chan->fifo; - struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem; - const struct nv04_fifo_ramfc *c = fifo->ramfc; - - nvkm_kmap(imem->ramfc); - do { - nvkm_wo32(imem->ramfc, chan->ramfc + c->ctxp, 0x00000000); - } while ((++c)->bits); - nvkm_done(imem->ramfc); return chan; } @@ -102,8 +93,6 @@ nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, } *args = data; struct nv04_fifo *fifo = nv04_fifo(base); struct nv04_fifo_chan *chan = NULL; - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_instmem *imem = device->imem; int ret = -ENOSYS; nvif_ioctl(parent, "create channel dma size %d\n", size); @@ -131,20 +120,8 @@ nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return ret; args->v0.chid = chan->base.chid; - chan->ramfc = chan->base.chid * 32; - - nvkm_kmap(imem->ramfc); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x08, chan->base.push->addr >> 4); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x10, - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | -#endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nvkm_done(imem->ramfc); + + chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c index f45655072f9d..aa5893c11203 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c @@ -41,8 +41,6 @@ nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, } *args = data; struct nv04_fifo *fifo = nv04_fifo(base); struct nv04_fifo_chan *chan = NULL; - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_instmem *imem = device->imem; int ret = -ENOSYS; nvif_ioctl(parent, "create channel dma size %d\n", size); @@ -70,20 +68,8 @@ nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return ret; args->v0.chid = chan->base.chid; - chan->ramfc = chan->base.chid * 32; - nvkm_kmap(imem->ramfc); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x14, - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | -#endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nvkm_done(imem->ramfc); + chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c index cd3f9f84ab9c..0a7d145ce5aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c @@ -41,8 +41,6 @@ nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, } *args = data; struct nv04_fifo *fifo = nv04_fifo(base); struct nv04_fifo_chan *chan = NULL; - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_instmem *imem = device->imem; int ret = -ENOSYS; nvif_ioctl(parent, "create channel dma size %d\n", size); @@ -71,20 +69,8 @@ nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return ret; args->v0.chid = chan->base.chid; - chan->ramfc = chan->base.chid * 64; - nvkm_kmap(imem->ramfc); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x14, - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | -#endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nvkm_done(imem->ramfc); + chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c index 2f0dceaf3b01..5e7104457a02 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c @@ -194,8 +194,6 @@ nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, } *args = data; struct nv04_fifo *fifo = nv04_fifo(base); struct nv04_fifo_chan *chan = NULL; - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_instmem *imem = device->imem; int ret = -ENOSYS; nvif_ioctl(parent, "create channel dma size %d\n", size); @@ -224,21 +222,8 @@ nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return ret; args->v0.chid = chan->base.chid; - chan->ramfc = chan->base.chid * 128; - nvkm_kmap(imem->ramfc); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x18, 0x30000000 | - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | -#endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nvkm_wo32(imem->ramfc, chan->ramfc + 0x3c, 0x0001ffff); - nvkm_done(imem->ramfc); + chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 76ba98b4d3bf..6f3f5caaa748 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -25,7 +25,7 @@ #include "chan.h" #include "runl.h" -#include +#include #include "nv50.h" #include "channv50.h" @@ -37,13 +37,69 @@ g84_chan_bind(struct nvkm_chan *chan) { struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; - nvkm_wr32(device, 0x002600 + (chan->id * 4), nv50_fifo_chan(chan)->ramfc->addr >> 8); + nvkm_wr32(device, 0x002600 + (chan->id * 4), chan->ramfc->addr >> 8); } +static int +g84_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + const u32 limit2 = ilog2(length / 8); + int ret; + + ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->inst, &chan->eng); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->inst, &chan->pgd); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->inst, &chan->cache); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->inst, &chan->ramfc); + if (ret) + return ret; + + ret = nvkm_ramht_new(device, 0x8000, 16, chan->inst, &chan->ramht); + if (ret) + return ret; + + nv50_fifo_chan(chan)->eng = chan->eng; + nv50_fifo_chan(chan)->ramht = chan->ramht; + + nvkm_kmap(chan->ramfc); + nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); + nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); + nvkm_wo32(chan->ramfc, 0x48, chan->push->node->offset >> 4); + nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(offset)); + nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(offset) | (limit2 << 16)); + nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); + nvkm_wo32(chan->ramfc, 0x78, 0x00000000); + nvkm_wo32(chan->ramfc, 0x7c, 0x30000000 | devm); + nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->node->offset >> 4)); + nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10); + nvkm_wo32(chan->ramfc, 0x98, chan->inst->addr >> 12); + nvkm_done(chan->ramfc); + return 0; +} + +static const struct nvkm_chan_func_ramfc +g84_chan_ramfc = { + .write = g84_chan_ramfc_write, + .ctxdma = true, + .devm = 0xfff, +}; + const struct nvkm_chan_func g84_chan = { .inst = &nv50_chan_inst, .userd = &nv50_chan_userd, + .ramfc = &g84_chan_ramfc, .bind = g84_chan_bind, .unbind = nv50_chan_unbind, .start = nv50_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index afee42440ff5..351b35d580fd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -82,6 +82,39 @@ gf100_chan_bind(struct nvkm_chan *chan) nvkm_wr32(device, 0x003000 + (chan->id * 8), 0xc0000000 | chan->inst->addr >> 12); } +static int +gf100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + const u64 userd = nvkm_memory_addr(chan->userd.mem) + chan->userd.base; + const u32 limit2 = ilog2(length / 8); + + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x08, lower_32_bits(userd)); + nvkm_wo32(chan->inst, 0x0c, upper_32_bits(userd)); + nvkm_wo32(chan->inst, 0x10, 0x0000face); + nvkm_wo32(chan->inst, 0x30, 0xfffff902); + nvkm_wo32(chan->inst, 0x48, lower_32_bits(offset)); + nvkm_wo32(chan->inst, 0x4c, upper_32_bits(offset) | (limit2 << 16)); + nvkm_wo32(chan->inst, 0x54, 0x00000002); + nvkm_wo32(chan->inst, 0x84, 0x20400000); + nvkm_wo32(chan->inst, 0x94, 0x30000000 | devm); + nvkm_wo32(chan->inst, 0x9c, 0x00000100); + nvkm_wo32(chan->inst, 0xa4, 0x1f1f1f1f); + nvkm_wo32(chan->inst, 0xa8, 0x1f1f1f1f); + nvkm_wo32(chan->inst, 0xac, 0x0000001f); + nvkm_wo32(chan->inst, 0xb8, 0xf8000000); + nvkm_wo32(chan->inst, 0xf8, 0x10003080); /* 0x002310 */ + nvkm_wo32(chan->inst, 0xfc, 0x10000010); /* 0x002350 */ + nvkm_done(chan->inst); + return 0; +} + +static const struct nvkm_chan_func_ramfc +gf100_chan_ramfc = { + .write = gf100_chan_ramfc_write, + .devm = 0xfff, +}; + void gf100_chan_userd_clear(struct nvkm_chan *chan) { @@ -117,6 +150,7 @@ static const struct nvkm_chan_func gf100_chan = { .inst = &gf100_chan_inst, .userd = &gf100_chan_userd, + .ramfc = &gf100_chan_ramfc, .bind = gf100_chan_bind, .unbind = gf100_chan_unbind, .start = gf100_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 61966d433bce..b75e3d089da3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -78,6 +78,39 @@ gk104_chan_bind(struct nvkm_chan *chan) gk104_chan_bind_inst(chan); } +static int +gk104_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + const u64 userd = nvkm_memory_addr(chan->userd.mem) + chan->userd.base; + const u32 limit2 = ilog2(length / 8); + + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x08, lower_32_bits(userd)); + nvkm_wo32(chan->inst, 0x0c, upper_32_bits(userd)); + nvkm_wo32(chan->inst, 0x10, 0x0000face); + nvkm_wo32(chan->inst, 0x30, 0xfffff902); + nvkm_wo32(chan->inst, 0x48, lower_32_bits(offset)); + nvkm_wo32(chan->inst, 0x4c, upper_32_bits(offset) | (limit2 << 16)); + nvkm_wo32(chan->inst, 0x84, 0x20400000); + nvkm_wo32(chan->inst, 0x94, 0x30000000 | devm); + nvkm_wo32(chan->inst, 0x9c, 0x00000100); + nvkm_wo32(chan->inst, 0xac, 0x0000001f); + nvkm_wo32(chan->inst, 0xe4, priv ? 0x00000020 : 0x00000000); + nvkm_wo32(chan->inst, 0xe8, chan->id); + nvkm_wo32(chan->inst, 0xb8, 0xf8000000); + nvkm_wo32(chan->inst, 0xf8, 0x10003080); /* 0x002310 */ + nvkm_wo32(chan->inst, 0xfc, 0x10000010); /* 0x002350 */ + nvkm_done(chan->inst); + return 0; +} + +const struct nvkm_chan_func_ramfc +gk104_chan_ramfc = { + .write = gk104_chan_ramfc_write, + .devm = 0xfff, + .priv = true, +}; + const struct nvkm_chan_func_userd gk104_chan_userd = { .bar = 1, @@ -89,6 +122,7 @@ static const struct nvkm_chan_func gk104_chan = { .inst = &gf100_chan_inst, .userd = &gk104_chan_userd, + .ramfc = &gk104_chan_ramfc, .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 7ff7a435d890..2a617215d924 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -51,6 +51,7 @@ const struct nvkm_chan_func gk110_chan = { .inst = &gf100_chan_inst, .userd = &gk104_chan_userd, + .ramfc = &gk104_chan_ramfc, .bind = gk104_chan_bind, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index cc2638018db7..3764245fbca1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -36,6 +36,7 @@ const struct nvkm_chan_func gm107_chan = { .inst = &gf100_chan_inst, .userd = &gk104_chan_userd, + .ramfc = &gk104_chan_ramfc, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c index 3157a7633231..31022441ee8f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c @@ -65,23 +65,9 @@ g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, args->v0.chid = chan->base.chid; ioffset = args->v0.ioffset; - ilength = order_base_2(args->v0.ilength / 8); + ilength = args->v0.ilength; - nvkm_kmap(chan->ramfc); - nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); - nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); - nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4); - nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset)); - nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); - nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); - nvkm_wo32(chan->ramfc, 0x78, 0x00000000); - nvkm_wo32(chan->ramfc, 0x7c, 0x30000001); - nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->node->offset >> 4)); - nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10); - nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12); - nvkm_done(chan->ramfc); + chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 1e459afc36ea..c43cd0c24a6d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -190,28 +190,9 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, usermem = nvkm_memory_addr(chan->base.userd.mem) + chan->base.userd.base; ioffset = args->v0.ioffset; - ilength = order_base_2(args->v0.ilength / 8); - - /* RAMFC */ - nvkm_kmap(chan->base.inst); - nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem)); - nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem)); - nvkm_wo32(chan->base.inst, 0x10, 0x0000face); - nvkm_wo32(chan->base.inst, 0x30, 0xfffff902); - nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset)); - nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) | - (ilength << 16)); - nvkm_wo32(chan->base.inst, 0x54, 0x00000002); - nvkm_wo32(chan->base.inst, 0x84, 0x20400000); - nvkm_wo32(chan->base.inst, 0x94, 0x30000001); - nvkm_wo32(chan->base.inst, 0x9c, 0x00000100); - nvkm_wo32(chan->base.inst, 0xa4, 0x1f1f1f1f); - nvkm_wo32(chan->base.inst, 0xa8, 0x1f1f1f1f); - nvkm_wo32(chan->base.inst, 0xac, 0x0000001f); - nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000); - nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */ - nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */ - nvkm_done(chan->base.inst); + ilength = args->v0.ilength; + + chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index b02ec7c545cf..77de170c8144 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -176,7 +176,6 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, { struct gk104_fifo_chan *chan; int runlist = ffs(*runlists) -1, ret; - u64 usermem; if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) return -EINVAL; @@ -199,28 +198,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, *chid = chan->base.chid; *inst = chan->base.inst->addr; - usermem = nvkm_memory_addr(chan->base.userd.mem) + chan->base.userd.base; - ilength = order_base_2(ilength / 8); - - /* RAMFC */ - nvkm_kmap(chan->base.inst); - nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem)); - nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem)); - nvkm_wo32(chan->base.inst, 0x10, 0x0000face); - nvkm_wo32(chan->base.inst, 0x30, 0xfffff902); - nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset)); - nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) | - (ilength << 16)); - nvkm_wo32(chan->base.inst, 0x84, 0x20400000); - nvkm_wo32(chan->base.inst, 0x94, 0x30000001); - nvkm_wo32(chan->base.inst, 0x9c, 0x00000100); - nvkm_wo32(chan->base.inst, 0xac, 0x0000001f); - nvkm_wo32(chan->base.inst, 0xe4, priv ? 0x00000020 : 0x00000000); - nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid); - nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000); - nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */ - nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */ - nvkm_done(chan->base.inst); + chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), priv); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 317787954a3e..9a2308be73a2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -120,7 +120,6 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, { struct gk104_fifo_chan *chan; int runlist = ffs(*runlists) -1, ret; - u64 usermem; if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) return -EINVAL; @@ -143,27 +142,7 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, *inst = chan->base.inst->addr; *token = chan->base.func->doorbell_handle(&chan->base); - /* Clear channel control registers. */ - usermem = nvkm_memory_addr(chan->base.userd.mem) + chan->base.userd.base; - ilength = order_base_2(ilength / 8); - - /* RAMFC */ - nvkm_kmap(chan->base.inst); - nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem)); - nvkm_wo32(chan->base.inst, 0x00c, upper_32_bits(usermem)); - nvkm_wo32(chan->base.inst, 0x010, 0x0000face); - nvkm_wo32(chan->base.inst, 0x030, 0x7ffff902); - nvkm_wo32(chan->base.inst, 0x048, lower_32_bits(ioffset)); - nvkm_wo32(chan->base.inst, 0x04c, upper_32_bits(ioffset) | - (ilength << 16)); - nvkm_wo32(chan->base.inst, 0x084, 0x20400000); - nvkm_wo32(chan->base.inst, 0x094, 0x30000001); - nvkm_wo32(chan->base.inst, 0x0e4, priv ? 0x00000020 : 0x00000000); - nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid); - nvkm_wo32(chan->base.inst, 0x0f4, 0x00001000); - nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080); - nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000); - nvkm_done(chan->base.inst); + chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), priv); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c index 410fc9e6c1f9..88ea7c29941e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c @@ -65,21 +65,9 @@ nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, args->v0.chid = chan->base.chid; ioffset = args->v0.ioffset; - ilength = order_base_2(args->v0.ilength / 8); + ilength = args->v0.ilength; - nvkm_kmap(chan->ramfc); - nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); - nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); - nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4); - nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset)); - nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); - nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); - nvkm_wo32(chan->ramfc, 0x78, 0x00000000); - nvkm_wo32(chan->ramfc, 0x7c, 0x30000001); - nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->node->offset >> 4)); - nvkm_done(chan->ramfc); + chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index 9611bd73c114..ffca153a9a28 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -38,6 +38,37 @@ gv100_chan_doorbell_handle(struct nvkm_chan *chan) return chan->id; } +static int +gv100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + const u64 userd = nvkm_memory_addr(chan->userd.mem) + chan->userd.base; + const u32 limit2 = ilog2(length / 8); + + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x008, lower_32_bits(userd)); + nvkm_wo32(chan->inst, 0x00c, upper_32_bits(userd)); + nvkm_wo32(chan->inst, 0x010, 0x0000face); + nvkm_wo32(chan->inst, 0x030, 0x7ffff902); + nvkm_wo32(chan->inst, 0x048, lower_32_bits(offset)); + nvkm_wo32(chan->inst, 0x04c, upper_32_bits(offset) | (limit2 << 16)); + nvkm_wo32(chan->inst, 0x084, 0x20400000); + nvkm_wo32(chan->inst, 0x094, 0x30000000 | devm); + nvkm_wo32(chan->inst, 0x0e4, priv ? 0x00000020 : 0x00000000); + nvkm_wo32(chan->inst, 0x0e8, chan->id); + nvkm_wo32(chan->inst, 0x0f4, 0x00001000 | (priv ? 0x00000100 : 0x00000000)); + nvkm_wo32(chan->inst, 0x0f8, 0x10003080); + nvkm_mo32(chan->inst, 0x218, 0x00000000, 0x00000000); + nvkm_done(chan->inst); + return 0; +} + +const struct nvkm_chan_func_ramfc +gv100_chan_ramfc = { + .write = gv100_chan_ramfc_write, + .devm = 0xfff, + .priv = true, +}; + const struct nvkm_chan_func_userd gv100_chan_userd = { .bar = 1, /*FIXME: hw doesn't have poller, flip to user-allocated in uapi commit. */ @@ -49,6 +80,7 @@ static const struct nvkm_chan_func gv100_chan = { .inst = &gf100_chan_inst, .userd = &gv100_chan_userd, + .ramfc = &gv100_chan_ramfc, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = gk104_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index f4207100f20c..cf8369b8b881 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -38,42 +38,29 @@ #include -static const struct nv04_fifo_ramfc -nv04_fifo_ramfc[] = { - { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, - { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, - { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, - { 16, 16, 0x08, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, - { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_STATE }, - { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, - { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_ENGINE }, - { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_PULL1 }, - {} -}; - void nv04_chan_stop(struct nvkm_chan *chan) { - struct nv04_fifo *fifo = nv04_fifo(chan->cgrp->runl->fifo); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_fifo *fifo = chan->cgrp->runl->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_memory *fctx = device->imem->ramfc; - const struct nv04_fifo_ramfc *c; + const struct nvkm_ramfc_layout *c; unsigned long flags; - u32 data = nv04_fifo_chan(chan)->ramfc; + u32 data = chan->ramfc_offset; u32 chid; /* prevent fifo context switches */ - spin_lock_irqsave(&fifo->base.lock, flags); + spin_lock_irqsave(&fifo->lock, flags); nvkm_wr32(device, NV03_PFIFO_CACHES, 0); /* if this channel is active, replace it with a null context */ - chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.chid->mask; + chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->chid->mask; if (chid == chan->id) { nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0); nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); - c = fifo->ramfc; + c = chan->func->ramfc->layout; nvkm_kmap(fctx); do { u32 rm = ((1ULL << c->bits) - 1) << c->regs; @@ -84,14 +71,14 @@ nv04_chan_stop(struct nvkm_chan *chan) } while ((++c)->bits); nvkm_done(fctx); - c = fifo->ramfc; + c = chan->func->ramfc->layout; do { nvkm_wr32(device, c->regp, 0x00000000); } while ((++c)->bits); nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0); nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0); - nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.chid->mask); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->chid->mask); nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1); nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); } @@ -99,7 +86,7 @@ nv04_chan_stop(struct nvkm_chan *chan) /* restore normal operation, after disabling dma mode */ nvkm_mask(device, NV04_PFIFO_MODE, BIT(chan->id), 0); nvkm_wr32(device, NV03_PFIFO_CACHES, 1); - spin_unlock_irqrestore(&fifo->base.lock, flags); + spin_unlock_irqrestore(&fifo->lock, flags); } void @@ -113,6 +100,59 @@ nv04_chan_start(struct nvkm_chan *chan) spin_unlock_irqrestore(&fifo->lock, flags); } +void +nv04_chan_ramfc_clear(struct nvkm_chan *chan) +{ + struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc; + const struct nvkm_ramfc_layout *c = chan->func->ramfc->layout; + + nvkm_kmap(ramfc); + do { + nvkm_wo32(ramfc, chan->ramfc_offset + c->ctxp, 0x00000000); + } while ((++c)->bits); + nvkm_done(ramfc); +} + +static int +nv04_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc; + const u32 base = chan->id * 32; + + chan->ramfc_offset = base; + + nvkm_kmap(ramfc); + nvkm_wo32(ramfc, base + 0x00, offset); + nvkm_wo32(ramfc, base + 0x04, offset); + nvkm_wo32(ramfc, base + 0x08, chan->push->addr >> 4); + nvkm_wo32(ramfc, base + 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nvkm_done(ramfc); + return 0; +} + +static const struct nvkm_chan_func_ramfc +nv04_chan_ramfc = { + .layout = (const struct nvkm_ramfc_layout[]) { + { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, + { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, + { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, + { 16, 16, 0x08, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, + { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_STATE }, + { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, + { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_ENGINE }, + { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_PULL1 }, + {} + }, + .write = nv04_chan_ramfc_write, + .clear = nv04_chan_ramfc_clear, + .ctxdma = true, +}; + const struct nvkm_chan_func_userd nv04_chan_userd = { .bar = 0, @@ -129,6 +169,7 @@ static const struct nvkm_chan_func nv04_chan = { .inst = &nv04_chan_inst, .userd = &nv04_chan_userd, + .ramfc = &nv04_chan_ramfc, .start = nv04_chan_start, .stop = nv04_chan_stop, }; @@ -476,7 +517,6 @@ nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) return -ENOMEM; - fifo->ramfc = ramfc; *pfifo = &fifo->base; ret = nvkm_fifo_ctor(func, device, type, inst, &fifo->base); @@ -507,5 +547,5 @@ int nv04_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv04_fifo_new_(&nv04_fifo, device, type, inst, 16, nv04_fifo_ramfc, pfifo); + return nv04_fifo_new_(&nv04_fifo, device, type, inst, 0, NULL, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h index 879c686675d6..93248ab24a81 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h @@ -4,17 +4,10 @@ #define nv04_fifo(p) container_of((p), struct nv04_fifo, base) #include "priv.h" -struct nv04_fifo_ramfc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -}; +#define nv04_fifo_ramfc nvkm_ramfc_layout struct nv04_fifo { struct nvkm_fifo base; - const struct nv04_fifo_ramfc *ramfc; }; int nv04_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index bbad5ffa179b..c7dbcd236630 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -21,7 +21,12 @@ * * Authors: Ben Skeggs */ +#include "cgrp.h" #include "chan.h" +#include "runl.h" + +#include +#include #include "nv04.h" #include "channv04.h" @@ -29,24 +34,52 @@ #include -static const struct nv04_fifo_ramfc -nv10_fifo_ramfc[] = { - { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, - { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, - { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, - { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, - { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, - { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE }, - { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, - { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE }, - { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 }, - {} +static int +nv10_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc; + const u32 base = chan->id * 32; + + chan->ramfc_offset = base; + + nvkm_kmap(ramfc); + nvkm_wo32(ramfc, base + 0x00, offset); + nvkm_wo32(ramfc, base + 0x04, offset); + nvkm_wo32(ramfc, base + 0x0c, chan->push->addr >> 4); + nvkm_wo32(ramfc, base + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nvkm_done(ramfc); + return 0; +} + +static const struct nvkm_chan_func_ramfc +nv10_chan_ramfc = { + .layout = (const struct nvkm_ramfc_layout[]) { + { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, + { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, + { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, + { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, + { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, + { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE }, + { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, + { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE }, + { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 }, + {} + }, + .write = nv10_chan_ramfc_write, + .clear = nv04_chan_ramfc_clear, + .ctxdma = true, }; static const struct nvkm_chan_func nv10_chan = { .inst = &nv04_chan_inst, .userd = &nv04_chan_userd, + .ramfc = &nv10_chan_ramfc, .start = nv04_chan_start, .stop = nv04_chan_stop, }; @@ -78,5 +111,5 @@ int nv10_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv04_fifo_new_(&nv10_fifo, device, type, inst, 32, nv10_fifo_ramfc, pfifo); + return nv04_fifo_new_(&nv10_fifo, device, type, inst, 0, NULL, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index b0dfa6f1a1d3..a829b0b08f9b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -21,8 +21,10 @@ * * Authors: Ben Skeggs */ +#include "cgrp.h" #include "chan.h" #include "chid.h" +#include "runl.h" #include "nv04.h" #include "channv04.h" @@ -33,29 +35,57 @@ #include -static const struct nv04_fifo_ramfc -nv17_fifo_ramfc[] = { - { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, - { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, - { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, - { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, - { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, - { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE }, - { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, - { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE }, - { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 }, - { 32, 0, 0x20, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE }, - { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP }, - { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT }, - { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_SEMAPHORE }, - { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE }, - {} +static int +nv17_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc; + const u32 base = chan->id * 64; + + chan->ramfc_offset = base; + + nvkm_kmap(ramfc); + nvkm_wo32(ramfc, base + 0x00, offset); + nvkm_wo32(ramfc, base + 0x04, offset); + nvkm_wo32(ramfc, base + 0x0c, chan->push->addr >> 4); + nvkm_wo32(ramfc, base + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nvkm_done(ramfc); + return 0; +} + +static const struct nvkm_chan_func_ramfc +nv17_chan_ramfc = { + .layout = (const struct nvkm_ramfc_layout[]) { + { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, + { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, + { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, + { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, + { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, + { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE }, + { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, + { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE }, + { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 }, + { 32, 0, 0x20, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE }, + { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP }, + { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT }, + { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_SEMAPHORE }, + { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE }, + {} + }, + .write = nv17_chan_ramfc_write, + .clear = nv04_chan_ramfc_clear, + .ctxdma = true, }; static const struct nvkm_chan_func nv17_chan = { .inst = &nv04_chan_inst, .userd = &nv04_chan_userd, + .ramfc = &nv17_chan_ramfc, .start = nv04_chan_start, .stop = nv04_chan_stop, }; @@ -110,5 +140,5 @@ int nv17_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv04_fifo_new_(&nv17_fifo, device, type, inst, 32, nv17_fifo_ramfc, pfifo); + return nv04_fifo_new_(&nv17_fifo, device, type, inst, 0, NULL, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index c2dc2d7abc9d..faf19ec3b323 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" @@ -35,31 +36,61 @@ #include -static const struct nv04_fifo_ramfc -nv40_fifo_ramfc[] = { - { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, - { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, - { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, - { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, - { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, - { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_STATE }, - { 28, 0, 0x18, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, - { 2, 28, 0x18, 28, 0x002058 }, - { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_ENGINE }, - { 32, 0, 0x20, 0, NV04_PFIFO_CACHE1_PULL1 }, - { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE }, - { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP }, - { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT }, - { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_SEMAPHORE }, - { 32, 0, 0x34, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE }, - { 32, 0, 0x38, 0, NV40_PFIFO_GRCTX_INSTANCE }, - { 17, 0, 0x3c, 0, NV04_PFIFO_DMA_TIMESLICE }, - { 32, 0, 0x40, 0, 0x0032e4 }, - { 32, 0, 0x44, 0, 0x0032e8 }, - { 32, 0, 0x4c, 0, 0x002088 }, - { 32, 0, 0x50, 0, 0x003300 }, - { 32, 0, 0x54, 0, 0x00330c }, - {} +static int +nv40_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc; + const u32 base = chan->id * 128; + + chan->ramfc_offset = base; + nv04_fifo_chan(chan)->ramfc = base; + + nvkm_kmap(ramfc); + nvkm_wo32(ramfc, base + 0x00, offset); + nvkm_wo32(ramfc, base + 0x04, offset); + nvkm_wo32(ramfc, base + 0x0c, chan->push->addr >> 4); + nvkm_wo32(ramfc, base + 0x18, 0x30000000 | + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nvkm_wo32(ramfc, base + 0x3c, 0x0001ffff); + nvkm_done(ramfc); + return 0; +} + +static const struct nvkm_chan_func_ramfc +nv40_chan_ramfc = { + .layout = (const struct nvkm_ramfc_layout[]) { + { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, + { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, + { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, + { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, + { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, + { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_STATE }, + { 28, 0, 0x18, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, + { 2, 28, 0x18, 28, 0x002058 }, + { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_ENGINE }, + { 32, 0, 0x20, 0, NV04_PFIFO_CACHE1_PULL1 }, + { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE }, + { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP }, + { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT }, + { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_SEMAPHORE }, + { 32, 0, 0x34, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE }, + { 32, 0, 0x38, 0, NV40_PFIFO_GRCTX_INSTANCE }, + { 17, 0, 0x3c, 0, NV04_PFIFO_DMA_TIMESLICE }, + { 32, 0, 0x40, 0, 0x0032e4 }, + { 32, 0, 0x44, 0, 0x0032e8 }, + { 32, 0, 0x4c, 0, 0x002088 }, + { 32, 0, 0x50, 0, 0x003300 }, + { 32, 0, 0x54, 0, 0x00330c }, + {} + }, + .write = nv40_chan_ramfc_write, + .clear = nv04_chan_ramfc_clear, + .ctxdma = true, }; static const struct nvkm_chan_func_userd @@ -73,6 +104,7 @@ static const struct nvkm_chan_func nv40_chan = { .inst = &nv04_chan_inst, .userd = &nv40_chan_userd, + .ramfc = &nv40_chan_ramfc, .start = nv04_chan_start, .stop = nv04_chan_stop, }; @@ -157,5 +189,5 @@ int nv40_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv04_fifo_new_(&nv40_fifo, device, type, inst, 32, nv40_fifo_ramfc, pfifo); + return nv04_fifo_new_(&nv40_fifo, device, type, inst, 0, NULL, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 24b458048180..7d5c0d026967 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -26,7 +26,7 @@ #include "chid.h" #include "runl.h" -#include +#include #include #include "nv50.h" @@ -63,9 +63,58 @@ nv50_chan_bind(struct nvkm_chan *chan) { struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; - nvkm_wr32(device, 0x002600 + (chan->id * 4), nv50_fifo_chan(chan)->ramfc->addr >> 12); + nvkm_wr32(device, 0x002600 + (chan->id * 4), chan->ramfc->addr >> 12); } +static int +nv50_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; + const u32 limit2 = ilog2(length / 8); + int ret; + + ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, chan->inst, &chan->ramfc); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x1200, 0, true, chan->inst, &chan->eng); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->inst, &chan->pgd); + if (ret) + return ret; + + ret = nvkm_ramht_new(device, 0x8000, 16, chan->inst, &chan->ramht); + if (ret) + return ret; + + nv50_fifo_chan(chan)->eng = chan->eng; + nv50_fifo_chan(chan)->ramht = chan->ramht; + + nvkm_kmap(chan->ramfc); + nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); + nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); + nvkm_wo32(chan->ramfc, 0x48, chan->push->node->offset >> 4); + nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(offset)); + nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(offset) | (limit2 << 16)); + nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); + nvkm_wo32(chan->ramfc, 0x78, 0x00000000); + nvkm_wo32(chan->ramfc, 0x7c, 0x30000000 | devm); + nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->node->offset >> 4)); + nvkm_done(chan->ramfc); + return 0; +} + +static const struct nvkm_chan_func_ramfc +nv50_chan_ramfc = { + .write = nv50_chan_ramfc_write, + .ctxdma = true, + .devm = 0xfff, +}; + const struct nvkm_chan_func_userd nv50_chan_userd = { .bar = 0, @@ -83,6 +132,7 @@ static const struct nvkm_chan_func nv50_chan = { .inst = &nv50_chan_inst, .userd = &nv50_chan_userd, + .ramfc = &nv50_chan_ramfc, .bind = nv50_chan_bind, .unbind = nv50_chan_unbind, .start = nv50_chan_start, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index c56deb78e9cc..43f248a109f6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -82,6 +82,7 @@ extern const struct nvkm_engn_func nv04_engn; extern const struct nvkm_cgrp_func nv04_cgrp; extern const struct nvkm_chan_func_inst nv04_chan_inst; extern const struct nvkm_chan_func_userd nv04_chan_userd; +void nv04_chan_ramfc_clear(struct nvkm_chan *); void nv04_chan_start(struct nvkm_chan *); void nv04_chan_stop(struct nvkm_chan *); @@ -154,6 +155,7 @@ bool gk104_engn_chsw(struct nvkm_engn *); int gk104_engn_cxid(struct nvkm_engn *, bool *cgid); extern const struct nvkm_engn_func gk104_engn_ce; extern const struct nvkm_chan_func_userd gk104_chan_userd; +extern const struct nvkm_chan_func_ramfc gk104_chan_ramfc; void gk104_chan_bind(struct nvkm_chan *); void gk104_chan_bind_inst(struct nvkm_chan *); void gk104_chan_unbind(struct nvkm_chan *); @@ -189,6 +191,7 @@ extern const struct nvkm_runq_func gv100_runq; extern const struct nvkm_engn_func gv100_engn; extern const struct nvkm_engn_func gv100_engn_ce; extern const struct nvkm_chan_func_userd gv100_chan_userd; +extern const struct nvkm_chan_func_ramfc gv100_chan_ramfc; void tu102_fifo_intr_ctxsw_timeout_info(struct nvkm_engn *, u32 info); extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 42d2975b82aa..a8452eee2949 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -51,6 +51,7 @@ static const struct nvkm_chan_func tu102_chan = { .inst = &gf100_chan_inst, .userd = &gv100_chan_userd, + .ramfc = &gv100_chan_ramfc, .bind = gk104_chan_bind_inst, .unbind = gk104_chan_unbind, .start = tu102_chan_start, -- cgit v1.2.3 From 8ab849d6dd4c2eb8880096e53e91dfb6ca37b589 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:37 +1000 Subject: drm/nouveau/fifo: add new engine context handling Builds on the context tracking that was added earlier. - marks engine context PTEs as 'priv' where possible Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 9 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c | 35 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h | 6 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 128 ++------------------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 109 ----------------- .../gpu/drm/nouveau/nvkm/engine/fifo/changf100.h | 4 - .../gpu/drm/nouveau/nvkm/engine/fifo/changk104.h | 13 -- .../gpu/drm/nouveau/nvkm/engine/fifo/channv04.h | 2 - .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.c | 131 --------------------- .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.h | 4 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c | 119 ------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 75 ++++++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 60 +++++++--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 81 +++++++++---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 5 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 100 ---------------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 123 ------------------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 78 ------------ .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c | 4 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 43 ++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 15 --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 46 +++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 58 ++++++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h | 2 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 4 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 25 +++- 39 files changed, 382 insertions(+), 930 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 1616a329db9e..da8abcbeb965 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -8,11 +8,6 @@ struct nvkm_fault_data; #define NVKM_FIFO_ENGN_NR 16 -struct nvkm_fifo_engn { - struct nvkm_object *object; - int refcount; -}; - struct nvkm_chan { const struct nvkm_chan_func *func; char name[64]; @@ -41,13 +36,10 @@ struct nvkm_chan { struct list_head cctxs; - struct nvkm_fifo *fifo; struct nvkm_object object; struct list_head head; struct nvkm_gpuobj *push; - - struct nvkm_fifo_engn engn[NVKM_FIFO_ENGN_NR]; }; struct nvkm_chan *nvkm_chan_get_chid(struct nvkm_engine *, int id, unsigned long *irqflags); @@ -78,7 +70,6 @@ struct nvkm_fifo { struct nvkm_vma *bar1; } userd; - int nr; spinlock_t lock; struct mutex mutex; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index c77af1b3ffa0..9362afe37f3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -318,7 +318,7 @@ int nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo *fifo) { - int ret, nr; + int ret; fifo->func = func; INIT_LIST_HEAD(&fifo->runqs); @@ -335,9 +335,6 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, if (ret) return ret; - nr = func->chid_nr(fifo); - fifo->nr = nr; - if (func->nonstall) { ret = nvkm_event_init(func->nonstall, &fifo->engine.subdev, 1, 1, &fifo->nonstall.event); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c index ac42dfc9d4cc..ea53fb3d5d06 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c @@ -25,6 +25,7 @@ #include "runl.h" #include "priv.h" +#include #include static void @@ -37,6 +38,7 @@ nvkm_cgrp_ectx_put(struct nvkm_cgrp *cgrp, struct nvkm_ectx **pectx) if (refcount_dec_and_test(&ectx->refs)) { CGRP_TRACE(cgrp, "dtor ectx %d[%s]", engn->id, engn->engine->subdev.name); + nvkm_object_del(&ectx->object); list_del(&ectx->head); kfree(ectx); } @@ -49,6 +51,11 @@ static int nvkm_cgrp_ectx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_ectx **pectx, struct nvkm_chan *chan, struct nvkm_client *client) { + struct nvkm_engine *engine = engn->engine; + struct nvkm_oclass cclass = { + .client = client, + .engine = engine, + }; struct nvkm_ectx *ectx; int ret = 0; @@ -67,7 +74,18 @@ nvkm_cgrp_ectx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_e ectx->engn = engn; refcount_set(&ectx->refs, 1); + refcount_set(&ectx->uses, 0); list_add_tail(&ectx->head, &cgrp->ectxs); + + /* Allocate the HW structures. */ + if (engine->func->fifo.cclass) + ret = engine->func->fifo.cclass(chan, &cclass, &ectx->object); + else if (engine->func->cclass) + ret = nvkm_object_new_(engine->func->cclass, &cclass, NULL, 0, &ectx->object); + + if (ret) + nvkm_cgrp_ectx_put(cgrp, pectx); + return ret; } @@ -81,6 +99,8 @@ nvkm_cgrp_vctx_put(struct nvkm_cgrp *cgrp, struct nvkm_vctx **pvctx) if (refcount_dec_and_test(&vctx->refs)) { CGRP_TRACE(cgrp, "dtor vctx %d[%s]", engn->id, engn->engine->subdev.name); + nvkm_vmm_put(vctx->vmm, &vctx->vma); + nvkm_gpuobj_del(&vctx->inst); nvkm_cgrp_ectx_put(cgrp, &vctx->ectx); if (vctx->vmm) { @@ -130,6 +150,21 @@ nvkm_cgrp_vctx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_c vctx->vmm = nvkm_vmm_ref(chan->vmm); refcount_set(&vctx->refs, 1); list_add_tail(&vctx->head, &cgrp->vctxs); + + /* MMU on some GPUs needs to know engine usage for TLB invalidation. */ + if (vctx->vmm) + atomic_inc(&vctx->vmm->engref[engn->engine->subdev.type]); + + /* Allocate the HW structures. */ + if (engn->func->bind) { + ret = nvkm_object_bind(vctx->ectx->object, NULL, 0, &vctx->inst); + if (ret == 0 && engn->func->ctor) + ret = engn->func->ctor(engn, vctx); + } + + if (ret) + nvkm_cgrp_vctx_put(cgrp, pvctx); + return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h index be9fbe9fab37..5f6abd59a6ff 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h @@ -10,12 +10,18 @@ struct nvkm_vctx { struct nvkm_vmm *vmm; refcount_t refs; + struct nvkm_gpuobj *inst; + struct nvkm_vma *vma; + struct list_head head; }; struct nvkm_ectx { struct nvkm_engn *engn; refcount_t refs; + refcount_t uses; + + struct nvkm_object *object; struct list_head head; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 00680b3ca9ab..a35439dda054 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -28,7 +28,6 @@ #include "runl.h" #include "priv.h" -#include #include #include #include @@ -46,94 +45,15 @@ struct nvkm_fifo_chan_object { int hash; }; -static struct nvkm_fifo_engn * -nvkm_fifo_chan_engn(struct nvkm_fifo_chan *chan, struct nvkm_engine *engine) -{ - int engi = chan->fifo->func->engine_id(chan->fifo, engine); - if (engi >= 0) - return &chan->engn[engi]; - return NULL; -} - -static int -nvkm_fifo_chan_child_fini(struct nvkm_oproxy *base, bool suspend) -{ - struct nvkm_fifo_chan_object *object = - container_of(base, typeof(*object), oproxy); - struct nvkm_engine *engine = object->oproxy.object->engine; - struct nvkm_fifo_chan *chan = object->chan; - struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine); - const char *name = engine->subdev.name; - int ret = 0; - - if (chan->func->engine_fini) { - ret = chan->func->engine_fini(chan, engine, suspend); - if (ret) { - nvif_error(&chan->object, - "detach %s failed, %d\n", name, ret); - return ret; - } - } - - if (engn->object) { - ret = nvkm_object_fini(engn->object, suspend); - if (ret && suspend) - return ret; - } - - nvif_trace(&chan->object, "detached %s\n", name); - return ret; -} - -static int -nvkm_fifo_chan_child_init(struct nvkm_oproxy *base) -{ - struct nvkm_fifo_chan_object *object = - container_of(base, typeof(*object), oproxy); - struct nvkm_engine *engine = object->oproxy.object->engine; - struct nvkm_fifo_chan *chan = object->chan; - struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine); - const char *name = engine->subdev.name; - int ret; - - if (engn->object) { - ret = nvkm_object_init(engn->object); - if (ret) - return ret; - } - - if (chan->func->engine_init) { - ret = chan->func->engine_init(chan, engine); - if (ret) { - nvif_error(&chan->object, - "attach %s failed, %d\n", name, ret); - return ret; - } - } - - nvif_trace(&chan->object, "attached %s\n", name); - return 0; -} - static void nvkm_fifo_chan_child_del(struct nvkm_oproxy *base) { struct nvkm_fifo_chan_object *object = container_of(base, typeof(*object), oproxy); - struct nvkm_engine *engine = object->oproxy.base.engine; struct nvkm_fifo_chan *chan = object->chan; - struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine); if (chan->func->object_dtor) chan->func->object_dtor(chan, object->hash); - - if (!--engn->refcount) { - if (chan->func->engine_dtor) - chan->func->engine_dtor(chan, engine); - nvkm_object_del(&engn->object); - if (chan->vmm) - atomic_dec(&chan->vmm->engref[engine->subdev.type]); - } } static const struct nvkm_oproxy_func @@ -147,7 +67,8 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, { struct nvkm_engine *engine = oclass->engine; struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent); - struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine); + struct nvkm_ectx *engn = nvkm_list_find(engn, &chan->cgrp->ectxs, head, + engn->engn->engine == engine); struct nvkm_fifo_chan_object *object; int ret = 0; @@ -157,33 +78,6 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, object->chan = chan; *pobject = &object->oproxy.base; - if (!engn->refcount++) { - struct nvkm_oclass cclass = { - .client = oclass->client, - .engine = oclass->engine, - }; - - if (chan->vmm) - atomic_inc(&chan->vmm->engref[engine->subdev.type]); - - if (engine->func->fifo.cclass) { - ret = engine->func->fifo.cclass(chan, &cclass, - &engn->object); - } else - if (engine->func->cclass) { - ret = nvkm_object_new_(engine->func->cclass, &cclass, - NULL, 0, &engn->object); - } - if (ret) - return ret; - - if (chan->func->engine_ctor) { - ret = chan->func->engine_ctor(chan, oclass->engine, - engn->object); - if (ret) - return ret; - } - } ret = oclass->base.ctor(&(const struct nvkm_oclass) { .base = oclass->base, @@ -210,10 +104,16 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, } void -nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct nvkm_cctx *cctx) +nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_cctx *cctx) { struct nvkm_cgrp *cgrp = chan->cgrp; struct nvkm_runl *runl = cgrp->runl; + struct nvkm_engine *engine = engn->engine; + + if (!engn->func->bind) + return; + + CHAN_TRACE(chan, "%sbind cctx %d[%s]", cctx ? "" : "un", engn->id, engine->subdev.name); /* Prevent any channel in channel group from being rescheduled, kick them * off host and any engine(s) they're loaded on. @@ -225,10 +125,7 @@ nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct n nvkm_chan_preempt(chan, true); /* Update context pointer. */ - if (cctx) - nvkm_fifo_chan_child_init(nvkm_oproxy(oproxy->object)); - else - nvkm_fifo_chan_child_fini(nvkm_oproxy(oproxy->object), false); + engn->func->bind(engn, cctx, chan); /* Resume normal operation. */ if (cgrp->hw) @@ -558,10 +455,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, *func = *fifo->func->chan.func; func->dtor = fn->dtor; - func->engine_ctor = fn->engine_ctor; - func->engine_dtor = fn->engine_dtor; - func->engine_init = fn->engine_init; - func->engine_fini = fn->engine_fini; func->object_ctor = fn->object_ctor; func->object_dtor = fn->object_dtor; @@ -572,7 +465,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, atomic_set(&chan->errored, 0); nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); - chan->fifo = fifo; INIT_LIST_HEAD(&chan->cctxs); INIT_LIST_HEAD(&chan->head); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 6e41eba0a7e2..bb142593d8b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -52,12 +52,6 @@ struct nvkm_chan_func { u32 (*doorbell_handle)(struct nvkm_chan *); void *(*dtor)(struct nvkm_fifo_chan *); - int (*engine_ctor)(struct nvkm_fifo_chan *, struct nvkm_engine *, - struct nvkm_object *); - void (*engine_dtor)(struct nvkm_fifo_chan *, struct nvkm_engine *); - int (*engine_init)(struct nvkm_fifo_chan *, struct nvkm_engine *); - int (*engine_fini)(struct nvkm_fifo_chan *, struct nvkm_engine *, - bool suspend); int (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *); void (*object_dtor)(struct nvkm_fifo_chan *, int); }; @@ -78,8 +72,7 @@ int nvkm_chan_preempt_locked(struct nvkm_chan *, bool wait); int nvkm_chan_cctx_get(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx **, struct nvkm_client * /*TODO: remove need for this */); void nvkm_chan_cctx_put(struct nvkm_chan *, struct nvkm_cctx **); -struct nvkm_oproxy; -void nvkm_chan_cctx_bind(struct nvkm_chan *, struct nvkm_oproxy *, struct nvkm_cctx *); +void nvkm_chan_cctx_bind(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx *); #define CHAN_PRCLI(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a) #define CHAN_PRINT(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:"f, (c)->id, ##a) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index f5e3557b9e50..359d8b5b124c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -30,111 +30,6 @@ #include -static int -g84_fifo_chan_engine_addr(struct nvkm_engine *engine) -{ - switch (engine->subdev.type) { - case NVKM_ENGINE_DMAOBJ: - case NVKM_ENGINE_SW : return -1; - case NVKM_ENGINE_GR : return 0x0020; - case NVKM_ENGINE_VP : - case NVKM_ENGINE_MSPDEC: return 0x0040; - case NVKM_ENGINE_MPEG : - case NVKM_ENGINE_MSPPP : return 0x0060; - case NVKM_ENGINE_BSP : - case NVKM_ENGINE_MSVLD : return 0x0080; - case NVKM_ENGINE_CIPHER: - case NVKM_ENGINE_SEC : return 0x00a0; - case NVKM_ENGINE_CE : return 0x00c0; - default: - WARN_ON(1); - return -1; - } -} - -static int -g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, bool suspend) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - struct nv50_fifo *fifo = chan->fifo; - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 engn, save; - int offset; - bool done; - - offset = g84_fifo_chan_engine_addr(engine); - if (offset < 0) - return 0; - - engn = fifo->base.func->engine_id(&fifo->base, engine) - 1; - save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn); - nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12); - done = nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x0032fc) != 0xffffffff) - break; - ) >= 0; - nvkm_wr32(device, 0x002520, save); - if (!done) { - nvkm_error(subdev, "channel %d [%s] unload timeout\n", - chan->base.chid, chan->base.object.client->name); - if (suspend) - return -EBUSY; - } - - nvkm_kmap(chan->eng); - nvkm_wo32(chan->eng, offset + 0x00, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x04, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x08, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); - nvkm_done(chan->eng); - return 0; -} - - -static int -g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - struct nvkm_gpuobj *engn = *nv50_fifo_chan_engine(chan, engine); - u64 limit, start; - int offset; - - offset = g84_fifo_chan_engine_addr(engine); - if (offset < 0) - return 0; - limit = engn->addr + engn->size - 1; - start = engn->addr; - - nvkm_kmap(chan->eng); - nvkm_wo32(chan->eng, offset + 0x00, 0x00190000); - nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit)); - nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start)); - nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 | - upper_32_bits(start)); - nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); - nvkm_done(chan->eng); - return 0; -} - -static int -g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, - struct nvkm_object *object) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - - if (g84_fifo_chan_engine_addr(engine) < 0) - return 0; - - return nvkm_object_bind(object, NULL, 0, nv50_fifo_chan_engine(chan, engine)); -} - static int g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, struct nvkm_object *object) @@ -169,10 +64,6 @@ g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, static const struct nvkm_fifo_chan_func g84_fifo_chan_func = { .dtor = nv50_fifo_chan_dtor, - .engine_ctor = g84_fifo_chan_engine_ctor, - .engine_dtor = nv50_fifo_chan_engine_dtor, - .engine_init = g84_fifo_chan_engine_init, - .engine_fini = g84_fifo_chan_engine_fini, .object_ctor = g84_fifo_chan_object_ctor, .object_dtor = nv50_fifo_chan_object_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h index 3c7b6c0d8cf1..739cd750742e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h @@ -16,10 +16,6 @@ struct gf100_fifo_chan { #define GF100_FIFO_ENGN_CE0 4 #define GF100_FIFO_ENGN_CE1 5 #define GF100_FIFO_ENGN_SW 15 - struct gf100_fifo_engn { - struct nvkm_gpuobj *inst; - struct nvkm_vma *vma; - } engn[NVKM_FIFO_ENGN_NR]; }; extern const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h index 95e788f31590..2043f06f500b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h @@ -11,10 +11,6 @@ struct gk104_fifo_chan { int runl; #define GK104_FIFO_ENGN_SW 15 - struct gk104_fifo_engn { - struct nvkm_gpuobj *inst; - struct nvkm_vma *vma; - } engn[NVKM_FIFO_ENGN_NR]; }; extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func; @@ -22,11 +18,6 @@ extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func; int gk104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); void *gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *); -struct gk104_fifo_engn *gk104_fifo_gpfifo_engine(struct gk104_fifo_chan *, struct nvkm_engine *); -int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *, struct nvkm_engine *, - struct nvkm_object *); -void gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *, - struct nvkm_engine *); int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); @@ -34,10 +25,6 @@ int gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *, struct gk104_fifo *, u64 *, u16 *, u64, u64, u64, u64 *, bool, u32 *, const struct nvkm_oclass *, struct nvkm_object **); -int gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *, - struct nvkm_engine *); -int gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *, - struct nvkm_engine *, bool); int tu102_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h index 837f9f7f69ce..5ebfa2241750 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h @@ -8,12 +8,10 @@ struct nv04_fifo_chan { struct nvkm_fifo_chan base; struct nv04_fifo *fifo; - u32 ramfc; #define NV04_FIFO_ENGN_SW 0 #define NV04_FIFO_ENGN_GR 1 #define NV04_FIFO_ENGN_MPEG 2 #define NV04_FIFO_ENGN_DMA 3 - struct nvkm_gpuobj *engn[NVKM_FIFO_ENGN_NR]; }; extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c index 0bf59c4e92b9..cb5606041499 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c @@ -28,133 +28,6 @@ #include #include -static int -nv50_fifo_chan_engine_addr(struct nvkm_engine *engine) -{ - switch (engine->subdev.type) { - case NVKM_ENGINE_DMAOBJ: - case NVKM_ENGINE_SW : return -1; - case NVKM_ENGINE_GR : return 0x0000; - case NVKM_ENGINE_MPEG : return 0x0060; - default: - WARN_ON(1); - return -1; - } -} - -struct nvkm_gpuobj ** -nv50_fifo_chan_engine(struct nv50_fifo_chan *chan, struct nvkm_engine *engine) -{ - int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine); - if (engi >= 0) - return &chan->engn[engi]; - return NULL; -} - -static int -nv50_fifo_chan_engine_fini(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, bool suspend) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - struct nv50_fifo *fifo = chan->fifo; - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int offset, ret = 0; - u32 me; - - offset = nv50_fifo_chan_engine_addr(engine); - if (offset < 0) - return 0; - - /* HW bug workaround: - * - * PFIFO will hang forever if the connected engines don't report - * that they've processed the context switch request. - * - * In order for the kickoff to work, we need to ensure all the - * connected engines are in a state where they can answer. - * - * Newer chipsets don't seem to suffer from this issue, and well, - * there's also a "ignore these engines" bitmask reg we can use - * if we hit the issue there.. - */ - me = nvkm_mask(device, 0x00b860, 0x00000001, 0x00000001); - - /* do the kickoff... */ - nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x0032fc) != 0xffffffff) - break; - ) < 0) { - nvkm_error(subdev, "channel %d [%s] unload timeout\n", - chan->base.chid, chan->base.object.client->name); - if (suspend) - ret = -EBUSY; - } - nvkm_wr32(device, 0x00b860, me); - - if (ret == 0) { - nvkm_kmap(chan->eng); - nvkm_wo32(chan->eng, offset + 0x00, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x04, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x08, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); - nvkm_done(chan->eng); - } - - return ret; -} - -static int -nv50_fifo_chan_engine_init(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - struct nvkm_gpuobj *engn = *nv50_fifo_chan_engine(chan, engine); - u64 limit, start; - int offset; - - offset = nv50_fifo_chan_engine_addr(engine); - if (offset < 0) - return 0; - limit = engn->addr + engn->size - 1; - start = engn->addr; - - nvkm_kmap(chan->eng); - nvkm_wo32(chan->eng, offset + 0x00, 0x00190000); - nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit)); - nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start)); - nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 | - upper_32_bits(start)); - nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); - nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); - nvkm_done(chan->eng); - return 0; -} - -void -nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - nvkm_gpuobj_del(nv50_fifo_chan_engine(chan, engine)); -} - -static int -nv50_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, - struct nvkm_object *object) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - - if (nv50_fifo_chan_engine_addr(engine) < 0) - return 0; - - return nvkm_object_bind(object, NULL, 0, nv50_fifo_chan_engine(chan, engine)); -} - void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *base, int cookie) { @@ -193,10 +66,6 @@ nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) static const struct nvkm_fifo_chan_func nv50_fifo_chan_func = { .dtor = nv50_fifo_chan_dtor, - .engine_ctor = nv50_fifo_chan_engine_ctor, - .engine_dtor = nv50_fifo_chan_engine_dtor, - .engine_init = nv50_fifo_chan_engine_init, - .engine_fini = nv50_fifo_chan_engine_fini, .object_ctor = nv50_fifo_chan_object_ctor, .object_dtor = nv50_fifo_chan_object_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h index 343356a0e5ef..ced832c7f425 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h @@ -9,7 +9,6 @@ struct nv50_fifo_chan { struct nv50_fifo *fifo; struct nvkm_fifo_chan base; - struct nvkm_gpuobj *eng; struct nvkm_ramht *ramht; #define NV50_FIFO_ENGN_SW 0 @@ -31,14 +30,11 @@ struct nv50_fifo_chan { #define G84_FIFO_ENGN_BSP 6 #define G84_FIFO_ENGN_MSVLD 6 #define G84_FIFO_ENGN_DMA 7 - struct nvkm_gpuobj *engn[NVKM_FIFO_ENGN_NR]; }; int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, const struct nvkm_oclass *, struct nv50_fifo_chan *); void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); -struct nvkm_gpuobj **nv50_fifo_chan_engine(struct nv50_fifo_chan *, struct nvkm_engine *); -void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int); int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c index 5e7104457a02..ca6fd8a5af6b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c @@ -31,121 +31,6 @@ #include #include -static bool -nv40_fifo_dma_engine(struct nvkm_engine *engine, u32 *reg, u32 *ctx) -{ - switch (engine->subdev.type) { - case NVKM_ENGINE_DMAOBJ: - case NVKM_ENGINE_SW: - return false; - case NVKM_ENGINE_GR: - *reg = 0x0032e0; - *ctx = 0x38; - return true; - case NVKM_ENGINE_MPEG: - if (engine->subdev.device->chipset < 0x44) - return false; - *reg = 0x00330c; - *ctx = 0x54; - return true; - default: - WARN_ON(1); - return false; - } -} - -static struct nvkm_gpuobj ** -nv40_fifo_dma_engn(struct nv04_fifo_chan *chan, struct nvkm_engine *engine) -{ - int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine); - if (engi >= 0) - return &chan->engn[engi]; - return NULL; -} - -static int -nv40_fifo_dma_engine_fini(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, bool suspend) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nv04_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_instmem *imem = device->imem; - unsigned long flags; - u32 reg, ctx; - int chid; - - if (!nv40_fifo_dma_engine(engine, ®, &ctx)) - return 0; - - spin_lock_irqsave(&fifo->base.lock, flags); - nvkm_mask(device, 0x002500, 0x00000001, 0x00000000); - - chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1); - if (chid == chan->base.chid) - nvkm_wr32(device, reg, 0x00000000); - nvkm_kmap(imem->ramfc); - nvkm_wo32(imem->ramfc, chan->ramfc + ctx, 0x00000000); - nvkm_done(imem->ramfc); - - nvkm_mask(device, 0x002500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&fifo->base.lock, flags); - return 0; -} - -static int -nv40_fifo_dma_engine_init(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nv04_fifo *fifo = chan->fifo; - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_instmem *imem = device->imem; - unsigned long flags; - u32 inst, reg, ctx; - int chid; - - if (!nv40_fifo_dma_engine(engine, ®, &ctx)) - return 0; - inst = (*nv40_fifo_dma_engn(chan, engine))->addr >> 4; - - spin_lock_irqsave(&fifo->base.lock, flags); - nvkm_mask(device, 0x002500, 0x00000001, 0x00000000); - - chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1); - if (chid == chan->base.chid) - nvkm_wr32(device, reg, inst); - nvkm_kmap(imem->ramfc); - nvkm_wo32(imem->ramfc, chan->ramfc + ctx, inst); - nvkm_done(imem->ramfc); - - nvkm_mask(device, 0x002500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&fifo->base.lock, flags); - return 0; -} - -static void -nv40_fifo_dma_engine_dtor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - nvkm_gpuobj_del(nv40_fifo_dma_engn(chan, engine)); -} - -static int -nv40_fifo_dma_engine_ctor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, - struct nvkm_object *object) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - u32 reg, ctx; - - if (!nv40_fifo_dma_engine(engine, ®, &ctx)) - return 0; - - return nvkm_object_bind(object, NULL, 0, nv40_fifo_dma_engn(chan, engine)); -} - static int nv40_fifo_dma_object_ctor(struct nvkm_fifo_chan *base, struct nvkm_object *object) @@ -176,10 +61,6 @@ nv40_fifo_dma_object_ctor(struct nvkm_fifo_chan *base, static const struct nvkm_fifo_chan_func nv40_fifo_dma_func = { .dtor = nv04_fifo_dma_dtor, - .engine_ctor = nv40_fifo_dma_engine_ctor, - .engine_dtor = nv40_fifo_dma_engine_dtor, - .engine_init = nv40_fifo_dma_engine_init, - .engine_fini = nv40_fifo_dma_engine_fini, .object_ctor = nv40_fifo_dma_object_ctor, .object_dtor = nv04_fifo_dma_object_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 6f3f5caaa748..2bc835f2ef74 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -26,6 +26,7 @@ #include "runl.h" #include +#include #include "nv50.h" #include "channv50.h" @@ -67,7 +68,6 @@ g84_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, b if (ret) return ret; - nv50_fifo_chan(chan)->eng = chan->eng; nv50_fifo_chan(chan)->ramht = chan->ramht; nvkm_kmap(chan->ramfc); @@ -106,8 +106,58 @@ g84_chan = { .stop = nv50_chan_stop, }; +static void +g84_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->cgrp->runl->fifo->engine.subdev; + struct nvkm_device *device = subdev->device; + u64 start = 0, limit = 0; + u32 flags = 0, ptr0, save; + + switch (engn->engine->subdev.type) { + case NVKM_ENGINE_GR : ptr0 = 0x0020; break; + case NVKM_ENGINE_VP : + case NVKM_ENGINE_MSPDEC: ptr0 = 0x0040; break; + case NVKM_ENGINE_MPEG : + case NVKM_ENGINE_MSPPP : ptr0 = 0x0060; break; + case NVKM_ENGINE_BSP : + case NVKM_ENGINE_MSVLD : ptr0 = 0x0080; break; + case NVKM_ENGINE_CIPHER: + case NVKM_ENGINE_SEC : ptr0 = 0x00a0; break; + case NVKM_ENGINE_CE : ptr0 = 0x00c0; break; + default: + WARN_ON(1); + return; + } + + if (!cctx) { + save = nvkm_mask(device, 0x002520, 0x0000003f, BIT(engn->id - 1)); + nvkm_wr32(device, 0x0032fc, chan->inst->addr >> 12); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x0032fc) != 0xffffffff) + break; + ); + nvkm_wr32(device, 0x002520, save); + } else { + flags = 0x00190000; + start = cctx->vctx->inst->addr; + limit = start + cctx->vctx->inst->size - 1; + } + + nvkm_kmap(chan->eng); + nvkm_wo32(chan->eng, ptr0 + 0x00, flags); + nvkm_wo32(chan->eng, ptr0 + 0x04, lower_32_bits(limit)); + nvkm_wo32(chan->eng, ptr0 + 0x08, lower_32_bits(start)); + nvkm_wo32(chan->eng, ptr0 + 0x0c, upper_32_bits(limit) << 24 | + lower_32_bits(start)); + nvkm_wo32(chan->eng, ptr0 + 0x10, 0x00000000); + nvkm_wo32(chan->eng, ptr0 + 0x14, 0x00000000); + nvkm_done(chan->eng); +} + const struct nvkm_engn_func g84_engn = { + .bind = g84_ectx_bind, }; static void @@ -138,28 +188,6 @@ g84_fifo_nonstall = { .fini = g84_fifo_nonstall_block, }; -int -g84_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) -{ - switch (engine->subdev.type) { - case NVKM_ENGINE_SW : return G84_FIFO_ENGN_SW; - case NVKM_ENGINE_GR : return G84_FIFO_ENGN_GR; - case NVKM_ENGINE_MPEG : - case NVKM_ENGINE_MSPPP : return G84_FIFO_ENGN_MPEG; - case NVKM_ENGINE_CE : return G84_FIFO_ENGN_CE0; - case NVKM_ENGINE_VP : - case NVKM_ENGINE_MSPDEC: return G84_FIFO_ENGN_VP; - case NVKM_ENGINE_CIPHER: - case NVKM_ENGINE_SEC : return G84_FIFO_ENGN_CIPHER; - case NVKM_ENGINE_BSP : - case NVKM_ENGINE_MSVLD : return G84_FIFO_ENGN_BSP; - case NVKM_ENGINE_DMAOBJ: return G84_FIFO_ENGN_DMA; - default: - WARN_ON(1); - return -1; - } -} - static int g84_fifo_runl_ctor(struct nvkm_fifo *fifo) { @@ -188,7 +216,6 @@ g84_fifo = { .runl_ctor = g84_fifo_runl_ctor, .init = nv50_fifo_init, .intr = nv04_fifo_intr, - .engine_id = g84_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .nonstall = &g84_fifo_nonstall, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c index 8016a2228e92..b2634f21d320 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c @@ -55,7 +55,6 @@ g98_fifo = { .runl_ctor = g98_fifo_runl_ctor, .init = nv50_fifo_init, .intr = nv04_fifo_intr, - .engine_id = g84_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .nonstall = &g84_fifo_nonstall, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 351b35d580fd..2e2626168bf2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -158,6 +158,47 @@ gf100_chan = { .preempt = gf100_chan_preempt, }; +static void +gf100_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) +{ + u64 addr = 0ULL; + u32 ptr0; + + switch (engn->engine->subdev.type) { + case NVKM_ENGINE_SW : return; + case NVKM_ENGINE_GR : ptr0 = 0x0210; break; + case NVKM_ENGINE_CE : ptr0 = 0x0230 + (engn->engine->subdev.inst * 0x10); break; + case NVKM_ENGINE_MSPDEC: ptr0 = 0x0250; break; + case NVKM_ENGINE_MSPPP : ptr0 = 0x0260; break; + case NVKM_ENGINE_MSVLD : ptr0 = 0x0270; break; + default: + WARN_ON(1); + return; + } + + if (cctx) { + addr = cctx->vctx->vma->addr; + addr |= 4ULL; + } + + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, ptr0 + 0, lower_32_bits(addr)); + nvkm_wo32(chan->inst, ptr0 + 4, upper_32_bits(addr)); + nvkm_done(chan->inst); +} + +static int +gf100_ectx_ctor(struct nvkm_engn *engn, struct nvkm_vctx *vctx) +{ + int ret; + + ret = nvkm_vmm_get(vctx->vmm, 12, vctx->inst->size, &vctx->vma); + if (ret) + return ret; + + return nvkm_memory_map(vctx->inst, 0, vctx->vmm, vctx->vma, NULL, 0); +} + bool gf100_engn_mmu_fault_triggered(struct nvkm_engn *engn) { @@ -250,6 +291,8 @@ gf100_engn = { .cxid = gf100_engn_cxid, .mmu_fault_trigger = gf100_engn_mmu_fault_trigger, .mmu_fault_triggered = gf100_engn_mmu_fault_triggered, + .ctor = gf100_ectx_ctor, + .bind = gf100_ectx_bind, }; const struct nvkm_engn_func @@ -422,22 +465,6 @@ gf100_fifo_nonstall = { .fini = gf100_fifo_nonstall_block, }; -static int -gf100_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) -{ - switch (engine->subdev.type) { - case NVKM_ENGINE_GR : return GF100_FIFO_ENGN_GR; - case NVKM_ENGINE_MSPDEC: return GF100_FIFO_ENGN_MSPDEC; - case NVKM_ENGINE_MSPPP : return GF100_FIFO_ENGN_MSPPP; - case NVKM_ENGINE_MSVLD : return GF100_FIFO_ENGN_MSVLD; - case NVKM_ENGINE_CE : return GF100_FIFO_ENGN_CE0 + engine->subdev.inst; - case NVKM_ENGINE_SW : return GF100_FIFO_ENGN_SW; - default: - WARN_ON(1); - return -1; - } -} - static const struct nvkm_enum gf100_fifo_mmu_fault_engine[] = { { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR }, @@ -935,7 +962,6 @@ gf100_fifo = { .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gf100_fifo_mmu_fault, - .engine_id = gf100_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gf100_runl, .runq = &gf100_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index b75e3d089da3..6130f492f48a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -35,6 +35,7 @@ #include #include +#include void gk104_chan_stop(struct nvkm_chan *chan) @@ -130,6 +131,63 @@ gk104_chan = { .preempt = gf100_chan_preempt, }; +static void +gk104_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) +{ + u32 ptr0, ptr1 = 0; + u64 addr = 0ULL; + + switch (engn->engine->subdev.type) { + case NVKM_ENGINE_SW : return; + case NVKM_ENGINE_GR : ptr0 = 0x0210; break; + case NVKM_ENGINE_SEC : ptr0 = 0x0220; break; + case NVKM_ENGINE_MSPDEC: ptr0 = 0x0250; break; + case NVKM_ENGINE_MSPPP : ptr0 = 0x0260; break; + case NVKM_ENGINE_MSVLD : ptr0 = 0x0270; break; + case NVKM_ENGINE_VIC : ptr0 = 0x0280; break; + case NVKM_ENGINE_MSENC : ptr0 = 0x0290; break; + case NVKM_ENGINE_NVDEC : + ptr1 = 0x0270; + ptr0 = 0x0210; + break; + case NVKM_ENGINE_NVENC : + if (!engn->engine->subdev.inst) + ptr1 = 0x0290; + ptr0 = 0x0210; + break; + default: + WARN_ON(1); + return; + } + + if (cctx) { + addr = cctx->vctx->vma->addr; + addr |= 4ULL; + } + + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, ptr0 + 0, lower_32_bits(addr)); + nvkm_wo32(chan->inst, ptr0 + 4, upper_32_bits(addr)); + if (ptr1) { + nvkm_wo32(chan->inst, ptr1 + 0, lower_32_bits(addr)); + nvkm_wo32(chan->inst, ptr1 + 4, upper_32_bits(addr)); + } + nvkm_done(chan->inst); +} + +int +gk104_ectx_ctor(struct nvkm_engn *engn, struct nvkm_vctx *vctx) +{ + struct gf100_vmm_map_v0 args = { .priv = 1 }; + int ret; + + ret = nvkm_vmm_get(vctx->vmm, 12, vctx->inst->size, &vctx->vma); + if (ret) + return ret; + + return nvkm_memory_map(vctx->inst, 0, vctx->vmm, vctx->vma, &args, sizeof(args)); +} + /*TODO: clean this up */ struct gk104_engn_status { bool busy; @@ -216,6 +274,8 @@ gk104_engn = { .cxid = gk104_engn_cxid, .mmu_fault_trigger = gf100_engn_mmu_fault_trigger, .mmu_fault_triggered = gf100_engn_mmu_fault_triggered, + .ctor = gk104_ectx_ctor, + .bind = gk104_ectx_bind, }; const struct nvkm_engn_func @@ -410,24 +470,6 @@ gk104_runl = { .preempt_pending = gf100_runl_preempt_pending, }; -int -gk104_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - int engn; - - if (engine->subdev.type == NVKM_ENGINE_SW) - return GK104_FIFO_ENGN_SW; - - for (engn = 0; engn < fifo->engine_nr && engine; engn++) { - if (fifo->engine[engn].engine == engine) - return engn; - } - - WARN_ON(1); - return -1; -} - static const struct nvkm_enum gk104_fifo_mmu_fault_engine[] = { { 0x00, "GR", NULL, NVKM_ENGINE_GR }, @@ -778,8 +820,6 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) if (engn < 0) continue; - fifo->engine[engn].engine = nvkm_device_engine(device, tdev->type, tdev->inst); - fifo->engine_nr = max(fifo->engine_nr, engn + 1); fifo->runlist[tdev->runlist].engm |= BIT(engn); fifo->runlist[tdev->runlist].engm_sw |= BIT(engn); if (tdev->type == NVKM_ENGINE_GR) @@ -825,7 +865,6 @@ gk104_fifo = { .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gk104_runl, .runq = &gk104_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 3bcf0720f89d..97fc9ccc2930 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -14,11 +14,6 @@ struct gk104_fifo { const struct gk104_fifo_func *func; struct nvkm_fifo base; - struct { - struct nvkm_engine *engine; - } engine[16]; - int engine_nr; - struct { u32 engm; u32 engm_sw; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 2a617215d924..2afbaf42572d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -119,7 +119,6 @@ gk110_fifo = { .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk104_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 81d184473f79..3727be30d7f4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -63,7 +63,6 @@ gk208_fifo = { .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index 47b7d93f5a04..eda1446dce27 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -38,7 +38,6 @@ gk20a_fifo = { .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit, .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gk104_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gk110_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 3764245fbca1..1089062313cc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -143,7 +143,6 @@ gm107_fifo = { .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gm107_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 8be59812797a..286c1098b665 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -52,7 +52,6 @@ gm200_fifo = { .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit, .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gm107_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gm107_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index a353c6b860ef..45d536d448f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -125,7 +125,6 @@ gp100_fifo = { .intr_mmu_fault_unit = gp100_fifo_intr_mmu_fault_unit, .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout, .mmu_fault = &gp100_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gp100_runl, .runq = &gk208_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index c43cd0c24a6d..6ba4335d40bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -31,102 +31,6 @@ #include #include -static u32 -gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) -{ - switch (engine->subdev.type) { - case NVKM_ENGINE_SW : return 0; - case NVKM_ENGINE_GR : return 0x0210; - case NVKM_ENGINE_CE : return 0x0230 + (engine->subdev.inst * 0x10); - case NVKM_ENGINE_MSPDEC: return 0x0250; - case NVKM_ENGINE_MSPPP : return 0x0260; - case NVKM_ENGINE_MSVLD : return 0x0270; - default: - WARN_ON(1); - return 0; - } -} - -static struct gf100_fifo_engn * -gf100_fifo_gpfifo_engine(struct gf100_fifo_chan *chan, struct nvkm_engine *engine) -{ - int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine); - if (engi >= 0) - return &chan->engn[engi]; - return NULL; -} - -static int -gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, bool suspend) -{ - const u32 offset = gf100_fifo_gpfifo_engine_addr(engine); - struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - struct nvkm_gpuobj *inst = chan->base.inst; - int ret = 0; - - if (offset) { - nvkm_kmap(inst); - nvkm_wo32(inst, offset + 0x00, 0x00000000); - nvkm_wo32(inst, offset + 0x04, 0x00000000); - nvkm_done(inst); - } - - return ret; -} - -static int -gf100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - const u32 offset = gf100_fifo_gpfifo_engine_addr(engine); - struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine); - struct nvkm_gpuobj *inst = chan->base.inst; - - if (offset) { - nvkm_kmap(inst); - nvkm_wo32(inst, offset + 0x00, lower_32_bits(engn->vma->addr) | 4); - nvkm_wo32(inst, offset + 0x04, upper_32_bits(engn->vma->addr)); - nvkm_done(inst); - } - - return 0; -} - -static void -gf100_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine); - nvkm_vmm_put(chan->base.vmm, &engn->vma); - nvkm_gpuobj_del(&engn->inst); -} - -static int -gf100_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, - struct nvkm_object *object) -{ - struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine); - int ret; - - if (!gf100_fifo_gpfifo_engine_addr(engine)) - return 0; - - ret = nvkm_object_bind(object, NULL, 0, &engn->inst); - if (ret) - return ret; - - ret = nvkm_vmm_get(chan->base.vmm, 12, engn->inst->size, &engn->vma); - if (ret) - return ret; - - return nvkm_memory_map(engn->inst, 0, chan->base.vmm, engn->vma, NULL, 0); -} - static void * gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) { @@ -136,10 +40,6 @@ gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) static const struct nvkm_fifo_chan_func gf100_fifo_gpfifo_func = { .dtor = gf100_fifo_gpfifo_dtor, - .engine_ctor = gf100_fifo_gpfifo_engine_ctor, - .engine_dtor = gf100_fifo_gpfifo_engine_dtor, - .engine_init = gf100_fifo_gpfifo_engine_init, - .engine_fini = gf100_fifo_gpfifo_engine_fini, }; static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index 77de170c8144..28a7a5eae72c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -33,125 +33,6 @@ #include #include -static u32 -gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) -{ - switch (engine->subdev.type) { - case NVKM_ENGINE_SW : - case NVKM_ENGINE_CE : return 0; - case NVKM_ENGINE_GR : return 0x0210; - case NVKM_ENGINE_SEC : return 0x0220; - case NVKM_ENGINE_MSPDEC: return 0x0250; - case NVKM_ENGINE_MSPPP : return 0x0260; - case NVKM_ENGINE_MSVLD : return 0x0270; - case NVKM_ENGINE_VIC : return 0x0280; - case NVKM_ENGINE_MSENC : return 0x0290; - case NVKM_ENGINE_NVDEC : return 0x02100270; - case NVKM_ENGINE_NVENC : - if (engine->subdev.inst) - return 0x0210; - return 0x02100290; - default: - WARN_ON(1); - return 0; - } -} - -struct gk104_fifo_engn * -gk104_fifo_gpfifo_engine(struct gk104_fifo_chan *chan, struct nvkm_engine *engine) -{ - int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine); - if (engi >= 0) - return &chan->engn[engi]; - return NULL; -} - -static int -gk104_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, bool suspend) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - struct nvkm_gpuobj *inst = chan->base.inst; - u32 offset = gk104_fifo_gpfifo_engine_addr(engine); - - if (offset) { - nvkm_kmap(inst); - nvkm_wo32(inst, (offset & 0xffff) + 0x00, 0x00000000); - nvkm_wo32(inst, (offset & 0xffff) + 0x04, 0x00000000); - if ((offset >>= 16)) { - nvkm_wo32(inst, offset + 0x00, 0x00000000); - nvkm_wo32(inst, offset + 0x04, 0x00000000); - } - nvkm_done(inst); - } - - return 0; -} - -static int -gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine); - struct nvkm_gpuobj *inst = chan->base.inst; - u32 offset = gk104_fifo_gpfifo_engine_addr(engine); - - if (offset) { - u32 datalo = lower_32_bits(engn->vma->addr) | 0x00000004; - u32 datahi = upper_32_bits(engn->vma->addr); - nvkm_kmap(inst); - nvkm_wo32(inst, (offset & 0xffff) + 0x00, datalo); - nvkm_wo32(inst, (offset & 0xffff) + 0x04, datahi); - if ((offset >>= 16)) { - nvkm_wo32(inst, offset + 0x00, datalo); - nvkm_wo32(inst, offset + 0x04, datahi); - } - nvkm_done(inst); - } - - return 0; -} - -void -gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine); - nvkm_vmm_put(chan->base.vmm, &engn->vma); - nvkm_gpuobj_del(&engn->inst); -} - -int -gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, - struct nvkm_object *object) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine); - int ret; - - if (!gk104_fifo_gpfifo_engine_addr(engine)) { - if (engine->subdev.type != NVKM_ENGINE_CE || - engine->subdev.device->card_type < GV100) - return 0; - } - - ret = nvkm_object_bind(object, NULL, 0, &engn->inst); - if (ret) - return ret; - - if (!gk104_fifo_gpfifo_engine_addr(engine)) - return 0; - - ret = nvkm_vmm_get(chan->base.vmm, 12, engn->inst->size, &engn->vma); - if (ret) - return ret; - - return nvkm_memory_map(engn->inst, 0, chan->base.vmm, engn->vma, NULL, 0); -} - void * gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) { @@ -162,10 +43,6 @@ gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func = { .dtor = gk104_fifo_gpfifo_dtor, - .engine_ctor = gk104_fifo_gpfifo_engine_ctor, - .engine_dtor = gk104_fifo_gpfifo_engine_dtor, - .engine_init = gk104_fifo_gpfifo_engine_init, - .engine_fini = gk104_fifo_gpfifo_engine_fini, }; static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 9a2308be73a2..3c2c76bcbe79 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -28,87 +28,9 @@ #include #include -static int -gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid) -{ - const u32 mask = ce ? 0x00020000 : 0x00010000; - const u32 data = valid ? mask : 0x00000000; - - if (1) { - /* Update engine context validity. */ - nvkm_kmap(chan->base.inst); - nvkm_mo32(chan->base.inst, 0x0ac, mask, data); - nvkm_done(chan->base.inst); - } - - return 0; -} - -int -gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine, bool suspend) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - struct nvkm_gpuobj *inst = chan->base.inst; - int ret; - - if (engine->subdev.type == NVKM_ENGINE_CE) { - ret = gv100_fifo_gpfifo_engine_valid(chan, true, false); - if (ret && suspend) - return ret; - - nvkm_kmap(inst); - nvkm_wo32(chan->base.inst, 0x220, 0x00000000); - nvkm_wo32(chan->base.inst, 0x224, 0x00000000); - nvkm_done(inst); - return ret; - } - - ret = gv100_fifo_gpfifo_engine_valid(chan, false, false); - if (ret && suspend) - return ret; - - nvkm_kmap(inst); - nvkm_wo32(inst, 0x0210, 0x00000000); - nvkm_wo32(inst, 0x0214, 0x00000000); - nvkm_done(inst); - return ret; -} - -int -gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, - struct nvkm_engine *engine) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine); - struct nvkm_gpuobj *inst = chan->base.inst; - - if (engine->subdev.type == NVKM_ENGINE_CE) { - const u64 bar2 = nvkm_memory_bar2(engn->inst->memory); - - nvkm_kmap(inst); - nvkm_wo32(chan->base.inst, 0x220, lower_32_bits(bar2)); - nvkm_wo32(chan->base.inst, 0x224, upper_32_bits(bar2)); - nvkm_done(inst); - - return gv100_fifo_gpfifo_engine_valid(chan, true, true); - } - - nvkm_kmap(inst); - nvkm_wo32(inst, 0x210, lower_32_bits(engn->vma->addr) | 0x00000004); - nvkm_wo32(inst, 0x214, upper_32_bits(engn->vma->addr)); - nvkm_done(inst); - - return gv100_fifo_gpfifo_engine_valid(chan, false, true); -} - static const struct nvkm_fifo_chan_func gv100_fifo_gpfifo = { .dtor = gk104_fifo_gpfifo_dtor, - .engine_ctor = gk104_fifo_gpfifo_engine_ctor, - .engine_dtor = gk104_fifo_gpfifo_engine_dtor, - .engine_init = gv100_fifo_gpfifo_engine_init, - .engine_fini = gv100_fifo_gpfifo_engine_fini, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c index 6562bdf39cb0..62a0f9664a9d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c @@ -31,10 +31,6 @@ static const struct nvkm_fifo_chan_func tu102_fifo_gpfifo = { .dtor = gk104_fifo_gpfifo_dtor, - .engine_ctor = gk104_fifo_gpfifo_engine_ctor, - .engine_dtor = gk104_fifo_gpfifo_engine_dtor, - .engine_init = gv100_fifo_gpfifo_engine_init, - .engine_fini = gv100_fifo_gpfifo_engine_fini, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index ffca153a9a28..d55dfc93c61e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -89,16 +89,58 @@ gv100_chan = { .doorbell_handle = gv100_chan_doorbell_handle, }; +void +gv100_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) +{ + u64 addr = 0ULL; + + if (cctx) { + addr = cctx->vctx->vma->addr; + addr |= 4ULL; + } + + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x210, lower_32_bits(addr)); + nvkm_wo32(chan->inst, 0x214, upper_32_bits(addr)); + nvkm_mo32(chan->inst, 0x0ac, 0x00010000, cctx ? 0x00010000 : 0x00000000); + nvkm_done(chan->inst); +} + const struct nvkm_engn_func gv100_engn = { .chsw = gk104_engn_chsw, .cxid = gk104_engn_cxid, + .ctor = gk104_ectx_ctor, + .bind = gv100_ectx_bind, }; +void +gv100_ectx_ce_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) +{ + const u64 bar2 = cctx ? nvkm_memory_bar2(cctx->vctx->inst->memory) : 0ULL; + + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x220, lower_32_bits(bar2)); + nvkm_wo32(chan->inst, 0x224, upper_32_bits(bar2)); + nvkm_mo32(chan->inst, 0x0ac, 0x00020000, cctx ? 0x00020000 : 0x00000000); + nvkm_done(chan->inst); +} + +int +gv100_ectx_ce_ctor(struct nvkm_engn *engn, struct nvkm_vctx *vctx) +{ + if (nvkm_memory_bar2(vctx->inst->memory) == ~0ULL) + return -EFAULT; + + return 0; +} + const struct nvkm_engn_func gv100_engn_ce = { .chsw = gk104_engn_chsw, .cxid = gk104_engn_cxid, + .ctor = gv100_ectx_ce_ctor, + .bind = gv100_ectx_ce_bind, }; static bool @@ -436,7 +478,6 @@ gv100_fifo = { .intr = gk104_fifo_intr, .intr_ctxsw_timeout = gv100_fifo_intr_ctxsw_timeout, .mmu_fault = &gv100_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &gv100_runl, .runq = &gv100_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index cf8369b8b881..08de6ee612ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -234,20 +234,6 @@ const struct nvkm_runl_func nv04_runl = { }; -int -nv04_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine) -{ - switch (engine->subdev.type) { - case NVKM_ENGINE_SW : return NV04_FIFO_ENGN_SW; - case NVKM_ENGINE_GR : return NV04_FIFO_ENGN_GR; - case NVKM_ENGINE_MPEG : return NV04_FIFO_ENGN_MPEG; - case NVKM_ENGINE_DMAOBJ: return NV04_FIFO_ENGN_DMA; - default: - WARN_ON(1); - return 0; - } -} - static const char * nv_dma_state_err(u32 state) { @@ -533,7 +519,6 @@ nv04_fifo = { .runl_ctor = nv04_fifo_runl_ctor, .init = nv04_fifo_init, .intr = nv04_fifo_intr, - .engine_id = nv04_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv04_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index c7dbcd236630..9658ac3dac91 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -97,7 +97,6 @@ nv10_fifo = { .runl_ctor = nv04_fifo_runl_ctor, .init = nv04_fifo_init, .intr = nv04_fifo_intr, - .engine_id = nv04_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv04_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index a829b0b08f9b..fb0b106eb09b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -126,7 +126,6 @@ nv17_fifo = { .runl_ctor = nv04_fifo_runl_ctor, .init = nv17_fifo_init, .intr = nv04_fifo_intr, - .engine_id = nv04_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv04_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index faf19ec3b323..f27ca3e7bb27 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -43,7 +43,6 @@ nv40_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, const u32 base = chan->id * 128; chan->ramfc_offset = base; - nv04_fifo_chan(chan)->ramfc = base; nvkm_kmap(ramfc); nvkm_wo32(ramfc, base + 0x00, offset); @@ -109,8 +108,52 @@ nv40_chan = { .stop = nv04_chan_stop, }; +static void +nv40_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) +{ + struct nvkm_fifo *fifo = chan->cgrp->runl->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_memory *ramfc = device->imem->ramfc; + u32 inst = 0x00000000, reg, ctx; + int chid; + + switch (engn->engine->subdev.type) { + case NVKM_ENGINE_GR: + reg = 0x0032e0; + ctx = 0x38; + break; + case NVKM_ENGINE_MPEG: + if (WARN_ON(device->chipset < 0x44)) + return; + reg = 0x00330c; + ctx = 0x54; + break; + default: + WARN_ON(1); + return; + } + + if (cctx) + inst = cctx->vctx->inst->addr >> 4; + + spin_lock_irq(&fifo->lock); + nvkm_mask(device, 0x002500, 0x00000001, 0x00000000); + + chid = nvkm_rd32(device, 0x003204) & (fifo->chid->nr - 1); + if (chid == chan->id) + nvkm_wr32(device, reg, inst); + + nvkm_kmap(ramfc); + nvkm_wo32(ramfc, chan->ramfc_offset + ctx, inst); + nvkm_done(ramfc); + + nvkm_mask(device, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irq(&fifo->lock); +} + static const struct nvkm_engn_func nv40_engn = { + .bind = nv40_ectx_bind, }; static const struct nvkm_engn_func @@ -175,7 +218,6 @@ nv40_fifo = { .runl_ctor = nv04_fifo_runl_ctor, .init = nv40_fifo_init, .intr = nv04_fifo_intr, - .engine_id = nv04_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv04_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 7d5c0d026967..f068a27d9338 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -89,7 +89,6 @@ nv50_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, if (ret) return ret; - nv50_fifo_chan(chan)->eng = chan->eng; nv50_fifo_chan(chan)->ramht = chan->ramht; nvkm_kmap(chan->ramfc); @@ -139,8 +138,64 @@ nv50_chan = { .stop = nv50_chan_stop, }; +static void +nv50_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->cgrp->runl->fifo->engine.subdev; + struct nvkm_device *device = subdev->device; + u64 start = 0, limit = 0; + u32 flags = 0, ptr0, save; + + switch (engn->engine->subdev.type) { + case NVKM_ENGINE_GR : ptr0 = 0x0000; break; + case NVKM_ENGINE_MPEG : ptr0 = 0x0060; break; + default: + WARN_ON(1); + return; + } + + if (!cctx) { + /* HW bug workaround: + * + * PFIFO will hang forever if the connected engines don't report + * that they've processed the context switch request. + * + * In order for the kickoff to work, we need to ensure all the + * connected engines are in a state where they can answer. + * + * Newer chipsets don't seem to suffer from this issue, and well, + * there's also a "ignore these engines" bitmask reg we can use + * if we hit the issue there.. + */ + save = nvkm_mask(device, 0x00b860, 0x00000001, 0x00000001); + + /* Tell engines to save out contexts. */ + nvkm_wr32(device, 0x0032fc, chan->inst->addr >> 12); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x0032fc) != 0xffffffff) + break; + ); + nvkm_wr32(device, 0x00b860, save); + } else { + flags = 0x00190000; + start = cctx->vctx->inst->addr; + limit = start + cctx->vctx->inst->size - 1; + } + + nvkm_kmap(chan->eng); + nvkm_wo32(chan->eng, ptr0 + 0x00, flags); + nvkm_wo32(chan->eng, ptr0 + 0x04, lower_32_bits(limit)); + nvkm_wo32(chan->eng, ptr0 + 0x08, lower_32_bits(start)); + nvkm_wo32(chan->eng, ptr0 + 0x0c, upper_32_bits(limit) << 24 | + lower_32_bits(start)); + nvkm_wo32(chan->eng, ptr0 + 0x10, 0x00000000); + nvkm_wo32(chan->eng, ptr0 + 0x14, 0x00000000); + nvkm_done(chan->eng); +} + static const struct nvkm_engn_func nv50_engn = { + .bind = nv50_ectx_bind, }; const struct nvkm_engn_func @@ -340,7 +395,6 @@ nv50_fifo = { .runl_ctor = nv04_fifo_runl_ctor, .init = nv50_fifo_init, .intr = nv04_fifo_intr, - .engine_id = nv04_fifo_engine_id, .pause = nv04_fifo_pause, .start = nv04_fifo_start, .runl = &nv50_runl, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h index 1573ea430cf3..3c6d67906730 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h @@ -12,6 +12,4 @@ int nv50_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvk struct nvkm_fifo **); void *nv50_fifo_dtor(struct nvkm_fifo *); - -int g84_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 43f248a109f6..13b218518984 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -4,11 +4,13 @@ #define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine) #include #include +struct nvkm_cctx; struct nvkm_cgrp; struct nvkm_engn; struct nvkm_memory; struct nvkm_runl; struct nvkm_runq; +struct nvkm_vctx; struct gk104_fifo; struct nvkm_fifo_chan_oclass; @@ -37,7 +39,6 @@ struct nvkm_fifo_func { const struct nvkm_enum *gpcclient; } *mmu_fault; - int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *); void (*pause)(struct nvkm_fifo *, unsigned long *); void (*start)(struct nvkm_fifo *, unsigned long *); @@ -74,7 +75,6 @@ int nv04_fifo_chid_ctor(struct nvkm_fifo *, int); int nv04_fifo_runl_ctor(struct nvkm_fifo *); void nv04_fifo_init(struct nvkm_fifo *); irqreturn_t nv04_fifo_intr(struct nvkm_inth *); -int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); extern const struct nvkm_runl_func nv04_runl; @@ -138,7 +138,6 @@ extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault; extern const struct nvkm_enum gk104_fifo_mmu_fault_reason[]; extern const struct nvkm_enum gk104_fifo_mmu_fault_hubclient[]; extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[]; -int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *); void gk104_runl_insert_chan(struct nvkm_chan *, struct nvkm_memory *, u64); void gk104_runl_commit(struct nvkm_runl *, struct nvkm_memory *, u32, int); bool gk104_runl_pending(struct nvkm_runl *); @@ -153,6 +152,7 @@ bool gk104_runq_idle(struct nvkm_runq *); extern const struct nvkm_engn_func gk104_engn; bool gk104_engn_chsw(struct nvkm_engn *); int gk104_engn_cxid(struct nvkm_engn *, bool *cgid); +int gk104_ectx_ctor(struct nvkm_engn *, struct nvkm_vctx *); extern const struct nvkm_engn_func gk104_engn_ce; extern const struct nvkm_chan_func_userd gk104_chan_userd; extern const struct nvkm_chan_func_ramfc gk104_chan_ramfc; @@ -189,7 +189,10 @@ void gv100_runl_insert_chan(struct nvkm_chan *, struct nvkm_memory *, u64); void gv100_runl_preempt(struct nvkm_runl *); extern const struct nvkm_runq_func gv100_runq; extern const struct nvkm_engn_func gv100_engn; +void gv100_ectx_bind(struct nvkm_engn *, struct nvkm_cctx *, struct nvkm_chan *); extern const struct nvkm_engn_func gv100_engn_ce; +int gv100_ectx_ce_ctor(struct nvkm_engn *, struct nvkm_vctx *); +void gv100_ectx_ce_bind(struct nvkm_engn *, struct nvkm_cctx *, struct nvkm_chan *); extern const struct nvkm_chan_func_userd gv100_chan_userd; extern const struct nvkm_chan_func_ramfc gv100_chan_ramfc; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index c3b469356d5d..86bca72c68bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -1,9 +1,11 @@ #ifndef __NVKM_RUNL_H__ #define __NVKM_RUNL_H__ #include +struct nvkm_cctx; struct nvkm_cgrp; struct nvkm_chan; struct nvkm_memory; +struct nvkm_vctx; enum nvkm_subdev_type; struct nvkm_engn { @@ -12,6 +14,8 @@ struct nvkm_engn { int (*cxid)(struct nvkm_engn *, bool *cgid); void (*mmu_fault_trigger)(struct nvkm_engn *); bool (*mmu_fault_triggered)(struct nvkm_engn *); + int (*ctor)(struct nvkm_engn *, struct nvkm_vctx *); + void (*bind)(struct nvkm_engn *, struct nvkm_cctx *, struct nvkm_chan *); } *func; struct nvkm_runl *runl; int id; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index a8452eee2949..608db9b8dc11 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -273,7 +273,6 @@ tu102_fifo = { .init_pbdmas = tu102_fifo_init_pbdmas, .intr = tu102_fifo_intr, .mmu_fault = &tu102_fifo_mmu_fault, - .engine_id = gk104_fifo_engine_id, .nonstall = &gf100_fifo_nonstall, .runl = &tu102_runl, .runq = &gv100_runq, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index 74584a29454a..f35bdd245233 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -25,6 +25,7 @@ #include "chid.h" #include "runl.h" +#include #include #include @@ -74,10 +75,17 @@ nvkm_uchan_object_fini_1(struct nvkm_oproxy *oproxy, bool suspend) struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy); struct nvkm_chan *chan = uobj->chan; struct nvkm_cctx *cctx = uobj->cctx; + struct nvkm_ectx *ectx = cctx->vctx->ectx; + + if (!ectx->object) + return 0; /* Unbind engine context from channel, if no longer required. */ if (refcount_dec_and_mutex_lock(&cctx->uses, &chan->cgrp->mutex)) { - nvkm_chan_cctx_bind(chan, oproxy, NULL); + nvkm_chan_cctx_bind(chan, ectx->engn, NULL); + + if (refcount_dec_and_test(&ectx->uses)) + nvkm_object_fini(ectx->object, false); mutex_unlock(&chan->cgrp->mutex); } @@ -90,14 +98,24 @@ nvkm_uchan_object_init_0(struct nvkm_oproxy *oproxy) struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy); struct nvkm_chan *chan = uobj->chan; struct nvkm_cctx *cctx = uobj->cctx; + struct nvkm_ectx *ectx = cctx->vctx->ectx; int ret = 0; + if (!ectx->object) + return 0; + /* Bind engine context to channel, if it hasn't been already. */ if (!refcount_inc_not_zero(&cctx->uses)) { mutex_lock(&chan->cgrp->mutex); if (!refcount_inc_not_zero(&cctx->uses)) { + if (!refcount_inc_not_zero(&ectx->uses)) { + ret = nvkm_object_init(ectx->object); + if (ret == 0) + refcount_set(&ectx->uses, 1); + } + if (ret == 0) { - nvkm_chan_cctx_bind(chan, oproxy, cctx); + nvkm_chan_cctx_bind(chan, ectx->engn, cctx); refcount_set(&cctx->uses, 1); } } @@ -112,6 +130,9 @@ nvkm_uchan_object_dtor(struct nvkm_oproxy *oproxy) { struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy); + if (!uobj->cctx) + return; + nvkm_chan_cctx_put(uobj->chan, &uobj->cctx); } -- cgit v1.2.3 From 7ac293328122075a2afc40a4089e7afc6cbc26eb Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:37 +1000 Subject: drm/nouveau/fifo: add new engine object handling Simplifies the GPU-specific code, completing the switch to newer HALs. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 66 ---------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 4 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 34 ----------- .../gpu/drm/nouveau/nvkm/engine/fifo/changf100.h | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/changk104.h | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/channv04.h | 2 - .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.c | 31 ---------- .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.h | 4 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c | 41 -------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c | 31 ---------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 4 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 27 +++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 18 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 18 +++++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 3 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 3 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 29 ++++++++-- 22 files changed, 94 insertions(+), 228 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index a35439dda054..4f99e5bf4e7f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -39,70 +39,6 @@ const struct nvkm_event_func nvkm_chan_event = { }; -struct nvkm_fifo_chan_object { - struct nvkm_oproxy oproxy; - struct nvkm_fifo_chan *chan; - int hash; -}; - -static void -nvkm_fifo_chan_child_del(struct nvkm_oproxy *base) -{ - struct nvkm_fifo_chan_object *object = - container_of(base, typeof(*object), oproxy); - struct nvkm_fifo_chan *chan = object->chan; - - if (chan->func->object_dtor) - chan->func->object_dtor(chan, object->hash); -} - -static const struct nvkm_oproxy_func -nvkm_fifo_chan_child_func = { - .dtor[0] = nvkm_fifo_chan_child_del, -}; - -int -nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_engine *engine = oclass->engine; - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent); - struct nvkm_ectx *engn = nvkm_list_find(engn, &chan->cgrp->ectxs, head, - engn->engn->engine == engine); - struct nvkm_fifo_chan_object *object; - int ret = 0; - - if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) - return -ENOMEM; - nvkm_oproxy_ctor(&nvkm_fifo_chan_child_func, oclass, &object->oproxy); - object->chan = chan; - *pobject = &object->oproxy.base; - - - ret = oclass->base.ctor(&(const struct nvkm_oclass) { - .base = oclass->base, - .engn = oclass->engn, - .handle = oclass->handle, - .object = oclass->object, - .client = oclass->client, - .parent = engn->object ? - engn->object : - oclass->parent, - .engine = engine, - }, data, size, &object->oproxy.object); - if (ret) - return ret; - - if (chan->func->object_ctor) { - object->hash = - chan->func->object_ctor(chan, object->oproxy.object); - if (object->hash < 0) - return object->hash; - } - - return 0; -} - void nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_cctx *cctx) { @@ -455,8 +391,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, *func = *fifo->func->chan.func; func->dtor = fn->dtor; - func->object_ctor = fn->object_ctor; - func->object_dtor = fn->object_dtor; chan->func = func; chan->id = -1; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index bb142593d8b6..836f9ecb13c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -52,8 +52,6 @@ struct nvkm_chan_func { u32 (*doorbell_handle)(struct nvkm_chan *); void *(*dtor)(struct nvkm_fifo_chan *); - int (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *); - void (*object_dtor)(struct nvkm_fifo_chan *, int); }; int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, @@ -78,6 +76,4 @@ void nvkm_chan_cctx_bind(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cct #define CHAN_PRINT(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:"f, (c)->id, ##a) #define CHAN_ERROR(c,f,a...) CHAN_PRCLI((c), ERROR, err, " "f"\n", ##a) #define CHAN_TRACE(c,f,a...) CHAN_PRINT((c), TRACE, info, " "f"\n", ##a) - -int nvkm_fifo_chan_child_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 359d8b5b124c..fc266af2cf53 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -30,42 +30,9 @@ #include -static int -g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, - struct nvkm_object *object) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - u32 handle = object->handle; - u32 context; - - switch (object->engine->subdev.type) { - case NVKM_ENGINE_DMAOBJ: - case NVKM_ENGINE_SW : context = 0x00000000; break; - case NVKM_ENGINE_GR : context = 0x00100000; break; - case NVKM_ENGINE_MPEG : - case NVKM_ENGINE_MSPPP : context = 0x00200000; break; - case NVKM_ENGINE_ME : - case NVKM_ENGINE_CE : context = 0x00300000; break; - case NVKM_ENGINE_VP : - case NVKM_ENGINE_MSPDEC: context = 0x00400000; break; - case NVKM_ENGINE_CIPHER: - case NVKM_ENGINE_SEC : - case NVKM_ENGINE_VIC : context = 0x00500000; break; - case NVKM_ENGINE_BSP : - case NVKM_ENGINE_MSVLD : context = 0x00600000; break; - default: - WARN_ON(1); - return -EINVAL; - } - - return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context); -} - static const struct nvkm_fifo_chan_func g84_fifo_chan_func = { .dtor = nv50_fifo_chan_dtor, - .object_ctor = g84_fifo_chan_object_ctor, - .object_dtor = nv50_fifo_chan_object_dtor, }; int @@ -95,6 +62,5 @@ g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, BIT(G84_FIFO_ENGN_MSVLD) | BIT(G84_FIFO_ENGN_DMA), 0, 0xc00000, 0x2000, oclass, &chan->base); - chan->fifo = fifo; return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h index 739cd750742e..e94c16b0efb6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h @@ -7,7 +7,6 @@ struct gf100_fifo_chan { struct nvkm_fifo_chan base; - struct gf100_fifo *fifo; #define GF100_FIFO_ENGN_GR 0 #define GF100_FIFO_ENGN_MSPDEC 1 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h index 2043f06f500b..3450f6349db3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h @@ -7,7 +7,6 @@ struct gk104_fifo_chan { struct nvkm_fifo_chan base; - struct gk104_fifo *fifo; int runl; #define GK104_FIFO_ENGN_SW 15 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h index 5ebfa2241750..5a1717888978 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h @@ -7,7 +7,6 @@ struct nv04_fifo_chan { struct nvkm_fifo_chan base; - struct nv04_fifo *fifo; #define NV04_FIFO_ENGN_SW 0 #define NV04_FIFO_ENGN_GR 1 #define NV04_FIFO_ENGN_MPEG 2 @@ -16,7 +15,6 @@ struct nv04_fifo_chan { extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func; void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *); -void nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *, int); extern const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass; extern const struct nvkm_fifo_chan_oclass nv10_fifo_dma_oclass; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c index cb5606041499..0ad6354b9ccc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c @@ -28,34 +28,6 @@ #include #include -void -nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *base, int cookie) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - nvkm_ramht_remove(chan->ramht, cookie); -} - -static int -nv50_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, - struct nvkm_object *object) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - u32 handle = object->handle; - u32 context; - - switch (object->engine->subdev.type) { - case NVKM_ENGINE_DMAOBJ: - case NVKM_ENGINE_SW : context = 0x00000000; break; - case NVKM_ENGINE_GR : context = 0x00100000; break; - case NVKM_ENGINE_MPEG : context = 0x00200000; break; - default: - WARN_ON(1); - return -EINVAL; - } - - return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context); -} - void * nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) { @@ -66,8 +38,6 @@ nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) static const struct nvkm_fifo_chan_func nv50_fifo_chan_func = { .dtor = nv50_fifo_chan_dtor, - .object_ctor = nv50_fifo_chan_object_ctor, - .object_dtor = nv50_fifo_chan_object_dtor, }; int @@ -87,6 +57,5 @@ nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, BIT(NV50_FIFO_ENGN_MPEG) | BIT(NV50_FIFO_ENGN_DMA), 0, 0xc00000, 0x2000, oclass, &chan->base); - chan->fifo = fifo; return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h index ced832c7f425..ea4ec3bc4b8a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h @@ -6,11 +6,8 @@ #include "nv50.h" struct nv50_fifo_chan { - struct nv50_fifo *fifo; struct nvkm_fifo_chan base; - struct nvkm_ramht *ramht; - #define NV50_FIFO_ENGN_SW 0 #define NV50_FIFO_ENGN_GR 1 #define NV50_FIFO_ENGN_MPEG 2 @@ -35,7 +32,6 @@ struct nv50_fifo_chan { int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, const struct nvkm_oclass *, struct nv50_fifo_chan *); void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); -void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int); int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, const struct nvkm_oclass *, struct nv50_fifo_chan *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c index 4220120d8bb8..41f7f22ed935 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c @@ -31,44 +31,6 @@ #include #include -void -nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *base, int cookie) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem; - - mutex_lock(&chan->fifo->base.mutex); - nvkm_ramht_remove(imem->ramht, cookie); - mutex_unlock(&chan->fifo->base.mutex); -} - -static int -nv04_fifo_dma_object_ctor(struct nvkm_fifo_chan *base, - struct nvkm_object *object) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem; - u32 context = 0x80000000 | chan->base.chid << 24; - u32 handle = object->handle; - int hash; - - switch (object->engine->subdev.type) { - case NVKM_ENGINE_DMAOBJ: - case NVKM_ENGINE_SW : context |= 0x00000000; break; - case NVKM_ENGINE_GR : context |= 0x00010000; break; - case NVKM_ENGINE_MPEG : context |= 0x00020000; break; - default: - WARN_ON(1); - return -EINVAL; - } - - mutex_lock(&chan->fifo->base.mutex); - hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4, - handle, context); - mutex_unlock(&chan->fifo->base.mutex); - return hash; -} - void * nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base) { @@ -79,8 +41,6 @@ nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base) const struct nvkm_fifo_chan_func nv04_fifo_dma_func = { .dtor = nv04_fifo_dma_dtor, - .object_ctor = nv04_fifo_dma_object_ctor, - .object_dtor = nv04_fifo_dma_object_dtor, }; static int @@ -115,7 +75,6 @@ nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, BIT(NV04_FIFO_ENGN_GR) | BIT(NV04_FIFO_ENGN_DMA), 0, 0x800000, 0x10000, oclass, &chan->base); - chan->fifo = fifo; if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c index aa5893c11203..49a000fabc5a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c @@ -63,7 +63,6 @@ nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, BIT(NV04_FIFO_ENGN_GR) | BIT(NV04_FIFO_ENGN_DMA), 0, 0x800000, 0x10000, oclass, &chan->base); - chan->fifo = fifo; if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c index 0a7d145ce5aa..cad8c5ec8dbb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c @@ -64,7 +64,6 @@ nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, BIT(NV04_FIFO_ENGN_MPEG) | /* NV31- */ BIT(NV04_FIFO_ENGN_DMA), 0, 0x800000, 0x10000, oclass, &chan->base); - chan->fifo = fifo; if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c index ca6fd8a5af6b..e922e4a5ab1a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c @@ -31,38 +31,8 @@ #include #include -static int -nv40_fifo_dma_object_ctor(struct nvkm_fifo_chan *base, - struct nvkm_object *object) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem; - u32 context = chan->base.chid << 23; - u32 handle = object->handle; - int hash; - - switch (object->engine->subdev.type) { - case NVKM_ENGINE_DMAOBJ: - case NVKM_ENGINE_SW : context |= 0x00000000; break; - case NVKM_ENGINE_GR : context |= 0x00100000; break; - case NVKM_ENGINE_MPEG : context |= 0x00200000; break; - default: - WARN_ON(1); - return -EINVAL; - } - - mutex_lock(&chan->fifo->base.mutex); - hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4, - handle, context); - mutex_unlock(&chan->fifo->base.mutex); - return hash; -} - static const struct nvkm_fifo_chan_func nv40_fifo_dma_func = { - .dtor = nv04_fifo_dma_dtor, - .object_ctor = nv40_fifo_dma_object_ctor, - .object_dtor = nv04_fifo_dma_object_dtor, }; static int @@ -98,7 +68,6 @@ nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, BIT(NV04_FIFO_ENGN_MPEG) | BIT(NV04_FIFO_ENGN_DMA), 0, 0xc00000, 0x1000, oclass, &chan->base); - chan->fifo = fifo; if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index 2bc835f2ef74..bc72c536f60d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -68,8 +68,6 @@ g84_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, b if (ret) return ret; - nv50_fifo_chan(chan)->ramht = chan->ramht; - nvkm_kmap(chan->ramfc); nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); @@ -158,6 +156,8 @@ g84_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan * const struct nvkm_engn_func g84_engn = { .bind = g84_ectx_bind, + .ramht_add = nv50_eobj_ramht_add, + .ramht_del = nv50_eobj_ramht_del, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index 6ba4335d40bc..f87a54e2f575 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -70,7 +70,6 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) return -ENOMEM; *pobject = &chan->base.object; - chan->fifo = fifo; ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base, 0x1000, 0x1000, true, args->v0.vmm, 0, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index 28a7a5eae72c..5036edb62dbd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -62,7 +62,6 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) return -ENOMEM; *pobject = &chan->base.object; - chan->fifo = fifo; chan->runl = runlist; ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c index 3c2c76bcbe79..a97ec53d7e6e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -51,7 +51,6 @@ gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) return -ENOMEM; *pobject = &chan->base.object; - chan->fifo = fifo; chan->runl = runlist; ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 08de6ee612ce..73ae205fc6ba 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -178,8 +178,35 @@ const struct nvkm_cgrp_func nv04_cgrp = { }; +void +nv04_eobj_ramht_del(struct nvkm_chan *chan, int hash) +{ + struct nvkm_fifo *fifo = chan->cgrp->runl->fifo; + struct nvkm_instmem *imem = fifo->engine.subdev.device->imem; + + mutex_lock(&fifo->mutex); + nvkm_ramht_remove(imem->ramht, hash); + mutex_unlock(&fifo->mutex); +} + +static int +nv04_eobj_ramht_add(struct nvkm_engn *engn, struct nvkm_object *eobj, struct nvkm_chan *chan) +{ + struct nvkm_fifo *fifo = chan->cgrp->runl->fifo; + struct nvkm_instmem *imem = fifo->engine.subdev.device->imem; + u32 context = 0x80000000 | chan->id << 24 | engn->id << 16; + int hash; + + mutex_lock(&fifo->mutex); + hash = nvkm_ramht_insert(imem->ramht, eobj, chan->id, 4, eobj->handle, context); + mutex_unlock(&fifo->mutex); + return hash; +} + const struct nvkm_engn_func nv04_engn = { + .ramht_add = nv04_eobj_ramht_add, + .ramht_del = nv04_eobj_ramht_del, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index f27ca3e7bb27..7574be50d959 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -108,6 +108,20 @@ nv40_chan = { .stop = nv04_chan_stop, }; +static int +nv40_eobj_ramht_add(struct nvkm_engn *engn, struct nvkm_object *eobj, struct nvkm_chan *chan) +{ + struct nvkm_fifo *fifo = chan->cgrp->runl->fifo; + struct nvkm_instmem *imem = fifo->engine.subdev.device->imem; + u32 context = chan->id << 23 | engn->id << 20; + int hash; + + mutex_lock(&fifo->mutex); + hash = nvkm_ramht_insert(imem->ramht, eobj, chan->id, 4, eobj->handle, context); + mutex_unlock(&fifo->mutex); + return hash; +} + static void nv40_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) { @@ -154,10 +168,14 @@ nv40_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan static const struct nvkm_engn_func nv40_engn = { .bind = nv40_ectx_bind, + .ramht_add = nv40_eobj_ramht_add, + .ramht_del = nv04_eobj_ramht_del, }; static const struct nvkm_engn_func nv40_engn_sw = { + .ramht_add = nv40_eobj_ramht_add, + .ramht_del = nv04_eobj_ramht_del, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index f068a27d9338..829c52a44a36 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -34,6 +34,18 @@ #include +void +nv50_eobj_ramht_del(struct nvkm_chan *chan, int hash) +{ + nvkm_ramht_remove(chan->ramht, hash); +} + +int +nv50_eobj_ramht_add(struct nvkm_engn *engn, struct nvkm_object *eobj, struct nvkm_chan *chan) +{ + return nvkm_ramht_insert(chan->ramht, eobj, 0, 4, eobj->handle, engn->id << 20); +} + void nv50_chan_stop(struct nvkm_chan *chan) { @@ -89,8 +101,6 @@ nv50_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, if (ret) return ret; - nv50_fifo_chan(chan)->ramht = chan->ramht; - nvkm_kmap(chan->ramfc); nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); @@ -196,10 +206,14 @@ nv50_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan static const struct nvkm_engn_func nv50_engn = { .bind = nv50_ectx_bind, + .ramht_add = nv50_eobj_ramht_add, + .ramht_del = nv50_eobj_ramht_del, }; const struct nvkm_engn_func nv50_engn_sw = { + .ramht_add = nv50_eobj_ramht_add, + .ramht_del = nv50_eobj_ramht_del, }; static bool diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 13b218518984..a5df5e2d9d4b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -85,6 +85,7 @@ extern const struct nvkm_chan_func_userd nv04_chan_userd; void nv04_chan_ramfc_clear(struct nvkm_chan *); void nv04_chan_start(struct nvkm_chan *); void nv04_chan_stop(struct nvkm_chan *); +void nv04_eobj_ramht_del(struct nvkm_chan *, int); int nv10_fifo_chid_nr(struct nvkm_fifo *); @@ -101,6 +102,8 @@ void nv50_chan_unbind(struct nvkm_chan *); void nv50_chan_start(struct nvkm_chan *); void nv50_chan_stop(struct nvkm_chan *); void nv50_chan_preempt(struct nvkm_chan *); +int nv50_eobj_ramht_add(struct nvkm_engn *, struct nvkm_object *, struct nvkm_chan *); +void nv50_eobj_ramht_del(struct nvkm_chan *, int); extern const struct nvkm_event_func g84_fifo_nonstall; extern const struct nvkm_engn_func g84_engn; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index 86bca72c68bc..5159b64377c5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -5,6 +5,7 @@ struct nvkm_cctx; struct nvkm_cgrp; struct nvkm_chan; struct nvkm_memory; +struct nvkm_object; struct nvkm_vctx; enum nvkm_subdev_type; @@ -16,6 +17,8 @@ struct nvkm_engn { bool (*mmu_fault_triggered)(struct nvkm_engn *); int (*ctor)(struct nvkm_engn *, struct nvkm_vctx *); void (*bind)(struct nvkm_engn *, struct nvkm_cctx *, struct nvkm_chan *); + int (*ramht_add)(struct nvkm_engn *, struct nvkm_object *, struct nvkm_chan *); + void (*ramht_del)(struct nvkm_chan *, int hash); } *func; struct nvkm_runl *runl; int id; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index f35bdd245233..1a89c9313662 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -67,6 +67,7 @@ struct nvkm_uobj { struct nvkm_oproxy oproxy; struct nvkm_chan *chan; struct nvkm_cctx *cctx; + int hash; }; static int @@ -129,10 +130,15 @@ static void nvkm_uchan_object_dtor(struct nvkm_oproxy *oproxy) { struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy); + struct nvkm_engn *engn; if (!uobj->cctx) return; + engn = uobj->cctx->vctx->ectx->engn; + if (engn->func->ramht_del) + engn->func->ramht_del(uobj->chan, uobj->hash); + nvkm_chan_cctx_put(uobj->chan, &uobj->cctx); } @@ -151,7 +157,6 @@ nvkm_uchan_object_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_cgrp *cgrp = chan->cgrp; struct nvkm_engn *engn; struct nvkm_uobj *uobj; - struct nvkm_oclass _oclass; int ret; /* Lookup host engine state for target engine. */ @@ -173,9 +178,25 @@ nvkm_uchan_object_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, return ret; /* Allocate HW object. */ - _oclass = *oclass; - _oclass.parent = &chan->object; - return nvkm_fifo_chan_child_new(&_oclass, argv, argc, &uobj->oproxy.object); + ret = oclass->base.ctor(&(const struct nvkm_oclass) { + .base = oclass->base, + .engn = oclass->engn, + .handle = oclass->handle, + .object = oclass->object, + .client = oclass->client, + .parent = uobj->cctx->vctx->ectx->object ?: oclass->parent, + .engine = engn->engine, + }, argv, argc, &uobj->oproxy.object); + if (ret) + return ret; + + if (engn->func->ramht_add) { + uobj->hash = engn->func->ramht_add(engn, uobj->oproxy.object, uobj->chan); + if (uobj->hash < 0) + return uobj->hash; + } + + return 0; } static int -- cgit v1.2.3 From 06db7fded6dec88772a65c5a39af12ba4dc2ad38 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:38 +1000 Subject: drm/nouveau/fifo: add new channel classes Exposes a bunch of the new features that became possible as a result of the earlier commits. DRM will build on this in the future to add support for features such as SCG ("async compute") and multi-device rendering, as part of the work necessary to be able to write a half- decent vulkan driver - finally. For the moment, this just crudely ports DRM to the API changes. - channel class interfaces now the same for all HW classes - channel group class exposed (SCG) - channel runqueue selector exposed (SCG) - channel sub-device id control exposed (multi-device rendering) - channel names in logging will reflect creating process, not fd owner - explicit USERD allocation required by VOLTA_CHANNEL_GPFIFO_A and newer - drm is smarter about determining the appropriate channel class to use Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvif/cl006b.h | 12 -- drivers/gpu/drm/nouveau/include/nvif/cl506e.h | 13 -- drivers/gpu/drm/nouveau/include/nvif/cl506f.h | 14 -- drivers/gpu/drm/nouveau/include/nvif/cl826e.h | 13 -- drivers/gpu/drm/nouveau/include/nvif/cl826f.h | 14 -- drivers/gpu/drm/nouveau/include/nvif/cl906f.h | 13 -- drivers/gpu/drm/nouveau/include/nvif/cla06f.h | 15 -- drivers/gpu/drm/nouveau/include/nvif/class.h | 28 +-- drivers/gpu/drm/nouveau/include/nvif/clc36f.h | 16 -- drivers/gpu/drm/nouveau/include/nvif/if0020.h | 32 +++ drivers/gpu/drm/nouveau/include/nvif/if0021.h | 16 ++ drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 7 +- drivers/gpu/drm/nouveau/nouveau_abi16.c | 1 - drivers/gpu/drm/nouveau/nouveau_chan.c | 222 +++++++++------------ drivers/gpu/drm/nouveau/nouveau_chan.h | 3 + drivers/gpu/drm/nouveau/nouveau_dma.c | 8 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 16 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 30 ++- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 97 ++++----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 13 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 66 ------ .../gpu/drm/nouveau/nvkm/engine/fifo/changf100.h | 21 -- .../gpu/drm/nouveau/nvkm/engine/fifo/changk104.h | 30 --- .../gpu/drm/nouveau/nvkm/engine/fifo/channv04.h | 23 --- .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.c | 61 ------ .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.h | 41 ---- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c | 90 --------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c | 78 -------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c | 79 -------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c | 83 -------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c | 18 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 23 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 12 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 59 +----- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 28 --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 10 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 8 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 9 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c | 77 ------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 101 ---------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 110 ---------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c | 100 ---------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c | 77 ------- .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c | 66 ------ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 13 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 26 +-- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h | 15 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 7 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 7 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 7 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 34 +--- drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h | 15 -- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 17 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c | 19 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c | 125 ++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c | 101 ++++++++-- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c | 2 +- 63 files changed, 524 insertions(+), 1763 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/cl006b.h delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/cl506e.h delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/cl506f.h delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/cl826e.h delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/cl826f.h delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/cl906f.h delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/cla06f.h delete mode 100644 drivers/gpu/drm/nouveau/include/nvif/clc36f.h create mode 100644 drivers/gpu/drm/nouveau/include/nvif/if0021.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl006b.h b/drivers/gpu/drm/nouveau/include/nvif/cl006b.h deleted file mode 100644 index c960c449e430..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl006b.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL006B_H__ -#define __NVIF_CL006B_H__ - -struct nv03_channel_dma_v0 { - __u8 version; - __u8 chid; - __u8 pad02[2]; - __u32 offset; - __u64 pushbuf; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h deleted file mode 100644 index 9df289c7a84f..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL506E_H__ -#define __NVIF_CL506E_H__ - -struct nv50_channel_dma_v0 { - __u8 version; - __u8 chid; - __u8 pad02[6]; - __u64 vmm; - __u64 pushbuf; - __u64 offset; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h deleted file mode 100644 index 327c96a994bb..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL506F_H__ -#define __NVIF_CL506F_H__ - -struct nv50_channel_gpfifo_v0 { - __u8 version; - __u8 chid; - __u8 pad02[2]; - __u32 ilength; - __u64 ioffset; - __u64 pushbuf; - __u64 vmm; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h deleted file mode 100644 index ef3033b836f0..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL826E_H__ -#define __NVIF_CL826E_H__ - -struct g82_channel_dma_v0 { - __u8 version; - __u8 chid; - __u8 pad02[6]; - __u64 vmm; - __u64 pushbuf; - __u64 offset; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h deleted file mode 100644 index c5d5e56b04cc..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL826F_H__ -#define __NVIF_CL826F_H__ - -struct g82_channel_gpfifo_v0 { - __u8 version; - __u8 chid; - __u8 pad02[2]; - __u32 ilength; - __u64 ioffset; - __u64 pushbuf; - __u64 vmm; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h deleted file mode 100644 index 5ccc8fd8c458..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL906F_H__ -#define __NVIF_CL906F_H__ - -struct fermi_channel_gpfifo_v0 { - __u8 version; - __u8 chid; - __u8 pad02[2]; - __u32 ilength; - __u64 ioffset; - __u64 vmm; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h deleted file mode 100644 index 10449accd3e8..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CLA06F_H__ -#define __NVIF_CLA06F_H__ - -struct kepler_channel_gpfifo_a_v0 { - __u8 version; - __u8 priv; - __u16 chid; - __u32 ilength; - __u64 ioffset; - __u64 runlist; - __u64 vmm; - __u64 inst; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index e9d9f314a744..ceea074b064b 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -70,23 +70,23 @@ #define MAXWELL_FAULT_BUFFER_A /* clb069.h */ 0x0000b069 #define VOLTA_FAULT_BUFFER_A /* clb069.h */ 0x0000c369 -#define NV03_CHANNEL_DMA /* cl506b.h */ 0x0000006b -#define NV10_CHANNEL_DMA /* cl506b.h */ 0x0000006e -#define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e -#define NV40_CHANNEL_DMA /* cl506b.h */ 0x0000406e +#define NV03_CHANNEL_DMA /* if0020.h */ 0x0000006b +#define NV10_CHANNEL_DMA /* if0020.h */ 0x0000006e +#define NV17_CHANNEL_DMA /* if0020.h */ 0x0000176e +#define NV40_CHANNEL_DMA /* if0020.h */ 0x0000406e #define KEPLER_CHANNEL_GROUP_A /* if0021.h */ 0x0000a06c -#define NV50_CHANNEL_GPFIFO /* cl506f.h */ 0x0000506f -#define G82_CHANNEL_GPFIFO /* cl826f.h */ 0x0000826f -#define FERMI_CHANNEL_GPFIFO /* cl906f.h */ 0x0000906f -#define KEPLER_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000a06f -#define KEPLER_CHANNEL_GPFIFO_B /* cla06f.h */ 0x0000a16f -#define MAXWELL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000b06f -#define PASCAL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000c06f -#define VOLTA_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c36f -#define TURING_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c46f -#define AMPERE_CHANNEL_GPFIFO_B /* clc36f.h */ 0x0000c76f +#define NV50_CHANNEL_GPFIFO /* if0020.h */ 0x0000506f +#define G82_CHANNEL_GPFIFO /* if0020.h */ 0x0000826f +#define FERMI_CHANNEL_GPFIFO /* if0020.h */ 0x0000906f +#define KEPLER_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000a06f +#define KEPLER_CHANNEL_GPFIFO_B /* if0020.h */ 0x0000a16f +#define MAXWELL_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000b06f +#define PASCAL_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c06f +#define VOLTA_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c36f +#define TURING_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c46f +#define AMPERE_CHANNEL_GPFIFO_B /* if0020.h */ 0x0000c76f #define NV50_DISP /* if0010.h */ 0x00005070 #define G82_DISP /* if0010.h */ 0x00008270 diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h deleted file mode 100644 index cdf6708e1d9a..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CLC36F_H__ -#define __NVIF_CLC36F_H__ - -struct volta_channel_gpfifo_a_v0 { - __u8 version; - __u8 priv; - __u16 chid; - __u32 ilength; - __u64 ioffset; - __u64 runlist; - __u64 vmm; - __u64 inst; - __u32 token; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0020.h b/drivers/gpu/drm/nouveau/include/nvif/if0020.h index 1893b8aa0abb..085e0ae8a450 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0020.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0020.h @@ -2,6 +2,38 @@ #ifndef __NVIF_IF0020_H__ #define __NVIF_IF0020_H__ +union nvif_chan_args { + struct nvif_chan_v0 { + __u8 version; + __u8 namelen; + __u8 runlist; + __u8 runq; + __u8 priv; + __u8 pad05; + __u16 devm; + __u64 vmm; + + __u64 ctxdma; + __u64 offset; + __u64 length; + + __u64 huserd; + __u64 ouserd; + + __u32 token; + __u16 chid; + __u8 pad3e; +#define NVIF_CHAN_V0_INST_APER_VRAM 0 +#define NVIF_CHAN_V0_INST_APER_HOST 1 +#define NVIF_CHAN_V0_INST_APER_NCOH 2 +#define NVIF_CHAN_V0_INST_APER_INST 0xff + __u8 aper; + __u64 inst; + + __u8 name[]; + } v0; +}; + union nvif_chan_event_args { struct nvif_chan_event_v0 { __u8 version; diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0021.h b/drivers/gpu/drm/nouveau/include/nvif/if0021.h new file mode 100644 index 000000000000..5013def90455 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0021.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0021_H__ +#define __NVIF_IF0021_H__ + +union nvif_cgrp_args { + struct nvif_cgrp_v0 { + __u8 version; + __u8 namelen; + __u8 runlist; + __u8 pad03[3]; + __u16 cgid; + __u64 vmm; + __u8 name[]; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index da8abcbeb965..c71f412bbb7f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -16,7 +16,8 @@ struct nvkm_chan { struct nvkm_gpuobj *inst; struct nvkm_vmm *vmm; - union { int id; int chid; }; /*FIXME: remove later */ + struct nvkm_gpuobj *push; + int id; struct { struct nvkm_memory *mem; @@ -35,11 +36,7 @@ struct nvkm_chan { atomic_t errored; struct list_head cctxs; - - struct nvkm_object object; - struct list_head head; - struct nvkm_gpuobj *push; }; struct nvkm_chan *nvkm_chan_get_chid(struct nvkm_engine *, int id, unsigned long *irqflags); diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 9237ef328b9f..82dab51d8aeb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include "nouveau_drv.h" diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 5b7042d94e80..efd6cf46921b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -25,13 +25,7 @@ #include #include -#include -#include -#include -#include -#include #include -#include #include "nouveau_drv.h" #include "nouveau_dma.h" @@ -101,6 +95,7 @@ nouveau_channel_del(struct nouveau_channel **pchan) nvif_object_dtor(&chan->vram); nvif_event_dtor(&chan->kill); nvif_object_dtor(&chan->user); + nvif_mem_dtor(&chan->mem_userd); nvif_object_dtor(&chan->push.ctxdma); nouveau_vma_del(&chan->push.vma); nouveau_bo_unmap(chan->push.buffer); @@ -250,134 +245,112 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, } static int -nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, - u64 runlist, bool priv, struct nouveau_channel **pchan) +nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool priv, u64 runm, + struct nouveau_channel **pchan) { - static const u16 oclasses[] = { AMPERE_CHANNEL_GPFIFO_B, - TURING_CHANNEL_GPFIFO_A, - VOLTA_CHANNEL_GPFIFO_A, - PASCAL_CHANNEL_GPFIFO_A, - MAXWELL_CHANNEL_GPFIFO_A, - KEPLER_CHANNEL_GPFIFO_B, - KEPLER_CHANNEL_GPFIFO_A, - FERMI_CHANNEL_GPFIFO, - G82_CHANNEL_GPFIFO, - NV50_CHANNEL_GPFIFO, - 0 }; - const u16 *oclass = oclasses; - union { - struct nv50_channel_gpfifo_v0 nv50; - struct fermi_channel_gpfifo_v0 fermi; - struct kepler_channel_gpfifo_a_v0 kepler; - struct volta_channel_gpfifo_a_v0 volta; + static const struct { + s32 oclass; + int version; + } hosts[] = { + { AMPERE_CHANNEL_GPFIFO_B, 0 }, + { TURING_CHANNEL_GPFIFO_A, 0 }, + { VOLTA_CHANNEL_GPFIFO_A, 0 }, + { PASCAL_CHANNEL_GPFIFO_A, 0 }, + { MAXWELL_CHANNEL_GPFIFO_A, 0 }, + { KEPLER_CHANNEL_GPFIFO_B, 0 }, + { KEPLER_CHANNEL_GPFIFO_A, 0 }, + { FERMI_CHANNEL_GPFIFO , 0 }, + { G82_CHANNEL_GPFIFO , 0 }, + { NV50_CHANNEL_GPFIFO , 0 }, + { NV40_CHANNEL_DMA , 0 }, + { NV17_CHANNEL_DMA , 0 }, + { NV10_CHANNEL_DMA , 0 }, + { NV03_CHANNEL_DMA , 0 }, + {} + }; + struct { + struct nvif_chan_v0 chan; + char name[TASK_COMM_LEN+16]; } args; + struct nouveau_cli *cli = (void *)device->object.client; struct nouveau_channel *chan; - u32 size; - int ret; + const u64 plength = 0x10000; + const u64 ioffset = plength; + const u64 ilength = 0x02000; + char name[TASK_COMM_LEN]; + int cid, ret; + u64 size; + + cid = nvif_mclass(&device->object, hosts); + if (cid < 0) + return cid; + + if (hosts[cid].oclass < NV50_CHANNEL_GPFIFO) + size = plength; + else + size = ioffset + ilength; /* allocate dma push buffer */ - ret = nouveau_channel_prep(drm, device, 0x12000, &chan); + ret = nouveau_channel_prep(drm, device, size, &chan); *pchan = chan; if (ret) return ret; /* create channel object */ - do { - if (oclass[0] >= VOLTA_CHANNEL_GPFIFO_A) { - args.volta.version = 0; - args.volta.ilength = 0x02000; - args.volta.ioffset = 0x10000 + chan->push.addr; - args.volta.runlist = runlist; - args.volta.vmm = nvif_handle(&chan->vmm->vmm.object); - args.volta.priv = priv; - size = sizeof(args.volta); - } else - if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) { - args.kepler.version = 0; - args.kepler.ilength = 0x02000; - args.kepler.ioffset = 0x10000 + chan->push.addr; - args.kepler.runlist = runlist; - args.kepler.vmm = nvif_handle(&chan->vmm->vmm.object); - args.kepler.priv = priv; - size = sizeof(args.kepler); - } else - if (oclass[0] >= FERMI_CHANNEL_GPFIFO) { - args.fermi.version = 0; - args.fermi.ilength = 0x02000; - args.fermi.ioffset = 0x10000 + chan->push.addr; - args.fermi.vmm = nvif_handle(&chan->vmm->vmm.object); - size = sizeof(args.fermi); - } else { - args.nv50.version = 0; - args.nv50.ilength = 0x02000; - args.nv50.ioffset = 0x10000 + chan->push.addr; - args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma); - args.nv50.vmm = nvif_handle(&chan->vmm->vmm.object); - size = sizeof(args.nv50); - } - - ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0, - *oclass++, &args, size, &chan->user); - if (ret == 0) { - if (chan->user.oclass >= VOLTA_CHANNEL_GPFIFO_A) { - chan->chid = args.volta.chid; - chan->inst = args.volta.inst; - chan->token = args.volta.token; - } else - if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) { - chan->chid = args.kepler.chid; - chan->inst = args.kepler.inst; - } else - if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) { - chan->chid = args.fermi.chid; - } else { - chan->chid = args.nv50.chid; - } + args.chan.version = 0; + args.chan.namelen = sizeof(args.name); + args.chan.runlist = __ffs64(runm); + args.chan.runq = 0; + args.chan.priv = priv; + args.chan.devm = BIT(0); + if (hosts[cid].oclass < NV50_CHANNEL_GPFIFO) { + args.chan.vmm = 0; + args.chan.ctxdma = nvif_handle(&chan->push.ctxdma); + args.chan.offset = chan->push.addr; + args.chan.length = 0; + } else { + args.chan.vmm = nvif_handle(&chan->vmm->vmm.object); + if (hosts[cid].oclass < FERMI_CHANNEL_GPFIFO) + args.chan.ctxdma = nvif_handle(&chan->push.ctxdma); + else + args.chan.ctxdma = 0; + args.chan.offset = ioffset + chan->push.addr; + args.chan.length = ilength; + } + args.chan.huserd = 0; + args.chan.ouserd = 0; + + /* allocate userd */ + if (hosts[cid].oclass >= VOLTA_CHANNEL_GPFIFO_A) { + ret = nvif_mem_ctor(&cli->mmu, "abi16ChanUSERD", NVIF_CLASS_MEM_GF100, + NVIF_MEM_VRAM | NVIF_MEM_COHERENT | NVIF_MEM_MAPPABLE, + 0, PAGE_SIZE, NULL, 0, &chan->mem_userd); + if (ret) return ret; - } - } while (*oclass); - nouveau_channel_del(pchan); - return ret; -} + args.chan.huserd = nvif_handle(&chan->mem_userd.object); + args.chan.ouserd = 0; -static int -nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, - struct nouveau_channel **pchan) -{ - static const u16 oclasses[] = { NV40_CHANNEL_DMA, - NV17_CHANNEL_DMA, - NV10_CHANNEL_DMA, - NV03_CHANNEL_DMA, - 0 }; - const u16 *oclass = oclasses; - struct nv03_channel_dma_v0 args; - struct nouveau_channel *chan; - int ret; + chan->userd = &chan->mem_userd.object; + } else { + chan->userd = &chan->user; + } - /* allocate dma push buffer */ - ret = nouveau_channel_prep(drm, device, 0x10000, &chan); - *pchan = chan; - if (ret) - return ret; + get_task_comm(name, current); + snprintf(args.name, sizeof(args.name), "%s[%d]", name, task_pid_nr(current)); - /* create channel object */ - args.version = 0; - args.pushbuf = nvif_handle(&chan->push.ctxdma); - args.offset = chan->push.addr; - - do { - ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0, - *oclass++, &args, sizeof(args), - &chan->user); - if (ret == 0) { - chan->chid = args.chid; - return ret; - } - } while (ret && *oclass); + ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0, hosts[cid].oclass, + &args, sizeof(args), &chan->user); + if (ret) { + nouveau_channel_del(pchan); + return ret; + } - nouveau_channel_del(pchan); - return ret; + chan->runlist = args.chan.runlist; + chan->chid = args.chan.chid; + chan->inst = args.chan.inst; + chan->token = args.chan.token; + return 0; } static int @@ -388,7 +361,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) struct nv_dma_v0 args = {}; int ret, i; - ret = nvif_object_map(&chan->user, NULL, 0); + ret = nvif_object_map(chan->userd, NULL, 0); if (ret) return ret; @@ -518,15 +491,10 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, struct nouveau_cli *cli = (void *)device->object.client; int ret; - /* hack until fencenv50 is fixed, and agp access relaxed */ - ret = nouveau_channel_ind(drm, device, runm, priv, pchan); + ret = nouveau_channel_ctor(drm, device, priv, runm, pchan); if (ret) { - NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret); - ret = nouveau_channel_dma(drm, device, pchan); - if (ret) { - NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret); - return ret; - } + NV_PRINTK(dbg, cli, "channel create, %d\n", ret); + return ret; } ret = nouveau_channel_init(*pchan, vram, gart); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 40467e8c9668..e06a8ffed31a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -16,6 +16,9 @@ struct nouveau_channel { struct nouveau_drm *drm; struct nouveau_vmm *vmm; + struct nvif_mem mem_userd; + struct nvif_object *userd; + int runlist; int chid; u64 inst; diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index ddb75d80bc53..b90cac6d5772 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -42,9 +42,9 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout) { uint64_t val; - val = nvif_rd32(&chan->user, chan->user_get); + val = nvif_rd32(chan->userd, chan->user_get); if (chan->user_get_hi) - val |= (uint64_t)nvif_rd32(&chan->user, chan->user_get_hi) << 32; + val |= (uint64_t)nvif_rd32(chan->userd, chan->user_get_hi) << 32; /* reset counter as long as GET is still advancing, this is * to avoid misdetecting a GPU lockup if the GPU happens to @@ -86,7 +86,7 @@ nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length) /* Flush writes. */ nouveau_bo_rd32(pb, 0); - nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put); + nvif_wr32(chan->userd, 0x8c, chan->dma.ib_put); if (user->func && user->func->doorbell) user->func->doorbell(user, chan->token); chan->dma.ib_free--; @@ -98,7 +98,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count) uint32_t cnt = 0, prev_get = 0; while (chan->dma.ib_free < count) { - uint32_t get = nvif_rd32(&chan->user, 0x88); + uint32_t get = nvif_rd32(chan->userd, 0x88); if (get != prev_get) { prev_get = get; cnt = 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 4a533b080445..61be972f8385 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -50,7 +50,6 @@ #include #include -#include #include "nouveau_drv.h" #include "nouveau_dma.h" diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index eb82da7e7d87..f9aad4cf8271 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -25,19 +25,5 @@ nvkm-y += nvkm/engine/fifo/gv100.o nvkm-y += nvkm/engine/fifo/tu102.o nvkm-y += nvkm/engine/fifo/ga102.o -nvkm-y += nvkm/engine/fifo/channv50.o -nvkm-y += nvkm/engine/fifo/chang84.o - -nvkm-y += nvkm/engine/fifo/dmanv04.o -nvkm-y += nvkm/engine/fifo/dmanv10.o -nvkm-y += nvkm/engine/fifo/dmanv17.o -nvkm-y += nvkm/engine/fifo/dmanv40.o - -nvkm-y += nvkm/engine/fifo/gpfifonv50.o -nvkm-y += nvkm/engine/fifo/gpfifog84.o -nvkm-y += nvkm/engine/fifo/gpfifogf100.o -nvkm-y += nvkm/engine/fifo/gpfifogk104.o -nvkm-y += nvkm/engine/fifo/gpfifogv100.o -nvkm-y += nvkm/engine/fifo/gpfifotu102.o - +nvkm-y += nvkm/engine/fifo/ucgrp.o nvkm-y += nvkm/engine/fifo/uchan.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 9362afe37f3e..61534a8a33d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -59,6 +59,9 @@ nvkm_fifo_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass { struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine); + if (oclass->engn == &fifo->func->cgrp.user) + return nvkm_ucgrp_new(fifo, oclass, argv, argc, pobject); + if (oclass->engn == &fifo->func->chan.user) return nvkm_uchan_new(fifo, NULL, oclass, argv, argc, pobject); @@ -75,9 +78,20 @@ static int nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, const struct nvkm_device_oclass **class) { struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine); + const struct nvkm_fifo_func_cgrp *cgrp = &fifo->func->cgrp; const struct nvkm_fifo_func_chan *chan = &fifo->func->chan; int c = 0; + /* *_CHANNEL_GROUP_* */ + if (cgrp->user.oclass) { + if (c++ == index) { + oclass->base = cgrp->user; + oclass->engn = &fifo->func->cgrp.user; + *class = &nvkm_fifo_class; + return 0; + } + } + /* *_CHANNEL_DMA, *_CHANNEL_GPFIFO_* */ if (chan->user.oclass) { if (c++ == index) { @@ -264,9 +278,6 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) return ret; } - if (fifo->func->oneinit) - return fifo->func->oneinit(fifo); - return 0; } @@ -282,7 +293,6 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) struct nvkm_fifo *fifo = nvkm_fifo(engine); struct nvkm_runl *runl, *runt; struct nvkm_runq *runq, *rtmp; - void *data = fifo; if (fifo->userd.bar1) nvkm_vmm_put(nvkm_bar_bar1_vmm(engine->subdev.device), &fifo->userd.bar1); @@ -296,11 +306,9 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) nvkm_chid_unref(&fifo->cgid); nvkm_chid_unref(&fifo->chid); - if (fifo->func->dtor) - data = fifo->func->dtor(fifo); nvkm_event_fini(&fifo->nonstall.event); mutex_destroy(&fifo->mutex); - return data; + return fifo; } static const struct nvkm_engine_func @@ -315,11 +323,15 @@ nvkm_fifo = { }; int -nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_fifo *fifo) +nvkm_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { + struct nvkm_fifo *fifo; int ret; + if (!(fifo = *pfifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) + return -ENOMEM; + fifo->func = func; INIT_LIST_HEAD(&fifo->runqs); INIT_LIST_HEAD(&fifo->runls); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 4f99e5bf4e7f..b7c9d6115bce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -28,7 +28,6 @@ #include "runl.h" #include "priv.h" -#include #include #include #include @@ -283,16 +282,6 @@ nvkm_chan_del(struct nvkm_chan **pchan) nvkm_cgrp_unref(&chan->cgrp); } - chan = nvkm_object_dtor(&chan->object); - kfree(chan); -} - -static void * -nvkm_fifo_chan_dtor(struct nvkm_object *object) -{ - struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); - void *data = chan->func->dtor(chan); - if (chan->vmm) { nvkm_vmm_part(chan->vmm, chan->inst->memory); nvkm_vmm_unref(&chan->vmm); @@ -300,8 +289,7 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object) nvkm_gpuobj_del(&chan->push); nvkm_gpuobj_del(&chan->inst); - kfree(chan->func); - return data; + kfree(chan); } void @@ -354,51 +342,42 @@ nvkm_chan_get_chid(struct nvkm_engine *engine, int id, unsigned long *pirqflags) return NULL; } -static const struct nvkm_object_func -nvkm_fifo_chan_func = { - .dtor = nvkm_fifo_chan_dtor, -}; - int -nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, - struct nvkm_fifo *fifo, u32 size, u32 align, bool zero, - u64 hvmm, u64 push, u32 engm, int bar, u32 base, - u32 user, const struct nvkm_oclass *oclass, - struct nvkm_fifo_chan *chan) +nvkm_chan_new_(const struct nvkm_chan_func *func, struct nvkm_runl *runl, int runq, + struct nvkm_cgrp *cgrp, const char *name, bool priv, u32 devm, struct nvkm_vmm *vmm, + struct nvkm_dmaobj *dmaobj, u64 offset, u64 length, + struct nvkm_memory *userd, u64 ouserd, struct nvkm_chan **pchan) { - struct nvkm_chan_func *func; - struct nvkm_client *client = oclass->client; + struct nvkm_fifo *fifo = runl->fifo; struct nvkm_device *device = fifo->engine.subdev.device; - struct nvkm_dmaobj *dmaobj; - struct nvkm_cgrp *cgrp = NULL; - struct nvkm_runl *runl; - struct nvkm_engn *engn = NULL; - struct nvkm_vmm *vmm = NULL; + struct nvkm_chan *chan; int ret; - nvkm_runl_foreach(runl, fifo) { - engn = nvkm_runl_find_engn(engn, runl, engm & BIT(engn->id)); - if (engn) - break; - } - - if (!engn) + /* Validate arguments against class requirements. */ + if ((runq && runq >= runl->func->runqs) || + (!func->inst->vmm != !vmm) || + ((func->userd->bar < 0) == !userd) || + (!func->ramfc->ctxdma != !dmaobj) || + ((func->ramfc->devm < devm) && devm != BIT(0)) || + (!func->ramfc->priv && priv)) { + RUNL_DEBUG(runl, "args runq:%d:%d vmm:%d:%p userd:%d:%p " + "push:%d:%p devm:%08x:%08x priv:%d:%d", + runl->func->runqs, runq, func->inst->vmm, vmm, + func->userd->bar < 0, userd, func->ramfc->ctxdma, dmaobj, + func->ramfc->devm, devm, func->ramfc->priv, priv); return -EINVAL; + } - /*FIXME: temp kludge to ease transition, remove later */ - if (!(func = kmalloc(sizeof(*func), GFP_KERNEL))) + if (!(chan = *pchan = kzalloc(sizeof(*chan), GFP_KERNEL))) return -ENOMEM; - *func = *fifo->func->chan.func; - func->dtor = fn->dtor; - chan->func = func; + strscpy(chan->name, name, sizeof(chan->name)); + chan->runq = runq; chan->id = -1; spin_lock_init(&chan->lock); atomic_set(&chan->blocked, 1); atomic_set(&chan->errored, 0); - - nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); INIT_LIST_HEAD(&chan->cctxs); INIT_LIST_HEAD(&chan->head); @@ -437,10 +416,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, /* Initialise virtual address-space. */ if (func->inst->vmm) { - struct nvkm_vmm *vmm = nvkm_uvmm_search(client, hvmm); - if (IS_ERR(vmm)) - return PTR_ERR(vmm); - if (WARN_ON(vmm->mmu != device->mmu)) return -EINVAL; @@ -455,10 +430,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, /* Allocate HW ctxdma for push buffer. */ if (func->ramfc->ctxdma) { - dmaobj = nvkm_dmaobj_search(client, push); - if (IS_ERR(dmaobj)) - return PTR_ERR(dmaobj); - ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, &chan->push); if (ret) { RUNL_DEBUG(runl, "bind %d", ret); @@ -477,7 +448,20 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, cgrp->id = chan->id; /* Initialise USERD. */ - if (1) { + if (func->userd->bar < 0) { + if (ouserd + chan->func->userd->size >= nvkm_memory_size(userd)) { + RUNL_DEBUG(runl, "ouserd %llx", ouserd); + return -EINVAL; + } + + ret = nvkm_memory_kmap(userd, &chan->userd.mem); + if (ret) { + RUNL_DEBUG(runl, "userd %d", ret); + return ret; + } + + chan->userd.base = ouserd; + } else { chan->userd.mem = nvkm_memory_ref(fifo->userd.mem); chan->userd.base = chan->id * chan->func->userd->size; } @@ -485,5 +469,12 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn, if (chan->func->userd->clear) chan->func->userd->clear(chan); + /* Initialise RAMFC. */ + ret = chan->func->ramfc->write(chan, offset, length, devm, priv); + if (ret) { + RUNL_DEBUG(runl, "ramfc %d", ret); + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h index 836f9ecb13c6..85b94f699128 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -1,9 +1,10 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_CHAN_H__ #define __NVKM_CHAN_H__ -#define nvkm_chan(p) container_of((p), struct nvkm_chan, object) /*FIXME: remove later */ #include +struct nvkm_dmaobj; struct nvkm_engn; +struct nvkm_runl; extern const struct nvkm_event_func nvkm_chan_event; @@ -50,14 +51,12 @@ struct nvkm_chan_func { void (*stop)(struct nvkm_chan *); void (*preempt)(struct nvkm_chan *); u32 (*doorbell_handle)(struct nvkm_chan *); - - void *(*dtor)(struct nvkm_fifo_chan *); }; -int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, - u32 size, u32 align, bool zero, u64 vm, u64 push, - u32 engm, int bar, u32 base, u32 user, - const struct nvkm_oclass *, struct nvkm_fifo_chan *); +int nvkm_chan_new_(const struct nvkm_chan_func *, struct nvkm_runl *, int runq, struct nvkm_cgrp *, + const char *name, bool priv, u32 devm, struct nvkm_vmm *, struct nvkm_dmaobj *, + u64 offset, u64 length, struct nvkm_memory *userd, u64 userd_bar1, + struct nvkm_chan **); void nvkm_chan_del(struct nvkm_chan **); void nvkm_chan_allow(struct nvkm_chan *); void nvkm_chan_block(struct nvkm_chan *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c deleted file mode 100644 index fc266af2cf53..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include -#include -#include -#include - -#include - -static const struct nvkm_fifo_chan_func -g84_fifo_chan_func = { - .dtor = nv50_fifo_chan_dtor, -}; - -int -g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, - const struct nvkm_oclass *oclass, - struct nv50_fifo_chan *chan) -{ - int ret; - - if (!vmm) - return -EINVAL; - - ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base, - 0x10000, 0x1000, false, vmm, push, - BIT(G84_FIFO_ENGN_SW) | - BIT(G84_FIFO_ENGN_GR) | - BIT(G84_FIFO_ENGN_MPEG) | - BIT(G84_FIFO_ENGN_MSPPP) | - BIT(G84_FIFO_ENGN_ME) | - BIT(G84_FIFO_ENGN_CE0) | - BIT(G84_FIFO_ENGN_VP) | - BIT(G84_FIFO_ENGN_MSPDEC) | - BIT(G84_FIFO_ENGN_CIPHER) | - BIT(G84_FIFO_ENGN_SEC) | - BIT(G84_FIFO_ENGN_VIC) | - BIT(G84_FIFO_ENGN_BSP) | - BIT(G84_FIFO_ENGN_MSVLD) | - BIT(G84_FIFO_ENGN_DMA), - 0, 0xc00000, 0x2000, oclass, &chan->base); - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h deleted file mode 100644 index e94c16b0efb6..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __GF100_FIFO_CHAN_H__ -#define __GF100_FIFO_CHAN_H__ -#define gf100_fifo_chan(p) container_of((p), struct gf100_fifo_chan, base) -#include "chan.h" -#include "gf100.h" - -struct gf100_fifo_chan { - struct nvkm_fifo_chan base; - -#define GF100_FIFO_ENGN_GR 0 -#define GF100_FIFO_ENGN_MSPDEC 1 -#define GF100_FIFO_ENGN_MSPPP 2 -#define GF100_FIFO_ENGN_MSVLD 3 -#define GF100_FIFO_ENGN_CE0 4 -#define GF100_FIFO_ENGN_CE1 5 -#define GF100_FIFO_ENGN_SW 15 -}; - -extern const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h deleted file mode 100644 index 3450f6349db3..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __GK104_FIFO_CHAN_H__ -#define __GK104_FIFO_CHAN_H__ -#define gk104_fifo_chan(p) container_of((p), struct gk104_fifo_chan, base) -#include "chan.h" -#include "gk104.h" - -struct gk104_fifo_chan { - struct nvkm_fifo_chan base; - int runl; - -#define GK104_FIFO_ENGN_SW 15 -}; - -extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func; - -int gk104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, - void *data, u32 size, struct nvkm_object **); -void *gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *); - -int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, - void *data, u32 size, struct nvkm_object **); -int gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *, - struct gk104_fifo *, u64 *, u16 *, u64, u64, u64, - u64 *, bool, u32 *, const struct nvkm_oclass *, - struct nvkm_object **); - -int tu102_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, - void *data, u32 size, struct nvkm_object **); -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h deleted file mode 100644 index 5a1717888978..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV04_FIFO_CHAN_H__ -#define __NV04_FIFO_CHAN_H__ -#define nv04_fifo_chan(p) container_of((p), struct nv04_fifo_chan, base) -#include "chan.h" -#include "nv04.h" - -struct nv04_fifo_chan { - struct nvkm_fifo_chan base; -#define NV04_FIFO_ENGN_SW 0 -#define NV04_FIFO_ENGN_GR 1 -#define NV04_FIFO_ENGN_MPEG 2 -#define NV04_FIFO_ENGN_DMA 3 -}; - -extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func; -void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *); - -extern const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass; -extern const struct nvkm_fifo_chan_oclass nv10_fifo_dma_oclass; -extern const struct nvkm_fifo_chan_oclass nv17_fifo_dma_oclass; -extern const struct nvkm_fifo_chan_oclass nv40_fifo_dma_oclass; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c deleted file mode 100644 index 0ad6354b9ccc..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include -#include -#include -#include - -void * -nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) -{ - struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - return chan; -} - -static const struct nvkm_fifo_chan_func -nv50_fifo_chan_func = { - .dtor = nv50_fifo_chan_dtor, -}; - -int -nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, - const struct nvkm_oclass *oclass, - struct nv50_fifo_chan *chan) -{ - int ret; - - if (!vmm) - return -EINVAL; - - ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base, - 0x10000, 0x1000, false, vmm, push, - BIT(NV50_FIFO_ENGN_SW) | - BIT(NV50_FIFO_ENGN_GR) | - BIT(NV50_FIFO_ENGN_MPEG) | - BIT(NV50_FIFO_ENGN_DMA), - 0, 0xc00000, 0x2000, oclass, &chan->base); - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h deleted file mode 100644 index ea4ec3bc4b8a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV50_FIFO_CHAN_H__ -#define __NV50_FIFO_CHAN_H__ -#define nv50_fifo_chan(p) container_of((p), struct nv50_fifo_chan, base) -#include "chan.h" -#include "nv50.h" - -struct nv50_fifo_chan { - struct nvkm_fifo_chan base; - -#define NV50_FIFO_ENGN_SW 0 -#define NV50_FIFO_ENGN_GR 1 -#define NV50_FIFO_ENGN_MPEG 2 -#define NV50_FIFO_ENGN_DMA 3 - -#define G84_FIFO_ENGN_SW 0 -#define G84_FIFO_ENGN_GR 1 -#define G84_FIFO_ENGN_MPEG 2 -#define G84_FIFO_ENGN_MSPPP 2 -#define G84_FIFO_ENGN_ME 3 -#define G84_FIFO_ENGN_CE0 3 -#define G84_FIFO_ENGN_VP 4 -#define G84_FIFO_ENGN_MSPDEC 4 -#define G84_FIFO_ENGN_CIPHER 5 -#define G84_FIFO_ENGN_SEC 5 -#define G84_FIFO_ENGN_VIC 5 -#define G84_FIFO_ENGN_BSP 6 -#define G84_FIFO_ENGN_MSVLD 6 -#define G84_FIFO_ENGN_DMA 7 -}; - -int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, - const struct nvkm_oclass *, struct nv50_fifo_chan *); -void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); - -int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, - const struct nvkm_oclass *, struct nv50_fifo_chan *); - -extern const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass; -extern const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c deleted file mode 100644 index 41f7f22ed935..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv04.h" -#include "regsnv04.h" - -#include -#include -#include - -#include -#include - -void * -nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base) -{ - struct nv04_fifo_chan *chan = nv04_fifo_chan(base); - return chan; -} - -const struct nvkm_fifo_chan_func -nv04_fifo_dma_func = { - .dtor = nv04_fifo_dma_dtor, -}; - -static int -nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nv04_fifo *fifo = nv04_fifo(base); - struct nv04_fifo_chan *chan = NULL; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel dma size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx " - "offset %08x\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - if (!args->v0.pushbuf) - return -EINVAL; - } else - return ret; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - - ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base, - 0x1000, 0x1000, false, 0, args->v0.pushbuf, - BIT(NV04_FIFO_ENGN_SW) | - BIT(NV04_FIFO_ENGN_GR) | - BIT(NV04_FIFO_ENGN_DMA), - 0, 0x800000, 0x10000, oclass, &chan->base); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false); - return 0; -} - -const struct nvkm_fifo_chan_oclass -nv04_fifo_dma_oclass = { - .ctor = nv04_fifo_dma_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c deleted file mode 100644 index 49a000fabc5a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv04.h" -#include "regsnv04.h" - -#include -#include -#include - -#include -#include - -static int -nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nv04_fifo *fifo = nv04_fifo(base); - struct nv04_fifo_chan *chan = NULL; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel dma size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx " - "offset %08x\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - if (!args->v0.pushbuf) - return -EINVAL; - } else - return ret; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - - ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base, - 0x1000, 0x1000, false, 0, args->v0.pushbuf, - BIT(NV04_FIFO_ENGN_SW) | - BIT(NV04_FIFO_ENGN_GR) | - BIT(NV04_FIFO_ENGN_DMA), - 0, 0x800000, 0x10000, oclass, &chan->base); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false); - return 0; -} - -const struct nvkm_fifo_chan_oclass -nv10_fifo_dma_oclass = { - .ctor = nv10_fifo_dma_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c deleted file mode 100644 index cad8c5ec8dbb..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv04.h" -#include "regsnv04.h" - -#include -#include -#include - -#include -#include - -static int -nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nv04_fifo *fifo = nv04_fifo(base); - struct nv04_fifo_chan *chan = NULL; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel dma size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx " - "offset %08x\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - if (!args->v0.pushbuf) - return -EINVAL; - } else - return ret; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - - ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base, - 0x1000, 0x1000, false, 0, args->v0.pushbuf, - BIT(NV04_FIFO_ENGN_SW) | - BIT(NV04_FIFO_ENGN_GR) | - BIT(NV04_FIFO_ENGN_MPEG) | /* NV31- */ - BIT(NV04_FIFO_ENGN_DMA), - 0, 0x800000, 0x10000, oclass, &chan->base); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false); - return 0; -} - -const struct nvkm_fifo_chan_oclass -nv17_fifo_dma_oclass = { - .ctor = nv17_fifo_dma_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c deleted file mode 100644 index e922e4a5ab1a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv04.h" -#include "regsnv04.h" - -#include -#include -#include - -#include -#include - -static const struct nvkm_fifo_chan_func -nv40_fifo_dma_func = { -}; - -static int -nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nv04_fifo *fifo = nv04_fifo(base); - struct nv04_fifo_chan *chan = NULL; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel dma size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx " - "offset %08x\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - if (!args->v0.pushbuf) - return -EINVAL; - } else - return ret; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - - ret = nvkm_fifo_chan_ctor(&nv40_fifo_dma_func, &fifo->base, - 0x1000, 0x1000, false, 0, args->v0.pushbuf, - BIT(NV04_FIFO_ENGN_SW) | - BIT(NV04_FIFO_ENGN_GR) | - BIT(NV04_FIFO_ENGN_MPEG) | - BIT(NV04_FIFO_ENGN_DMA), - 0, 0xc00000, 0x1000, oclass, &chan->base); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false); - return 0; -} - -const struct nvkm_fifo_chan_oclass -nv40_fifo_dma_oclass = { - .ctor = nv40_fifo_dma_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index bc72c536f60d..6b229a3fbd97 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "runl.h" @@ -28,9 +29,6 @@ #include #include -#include "nv50.h" -#include "channv50.h" - #include static void @@ -210,7 +208,6 @@ g84_fifo_runl_ctor(struct nvkm_fifo *fifo) static const struct nvkm_fifo_func g84_fifo = { - .dtor = nv50_fifo_dtor, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = nv50_fifo_chid_ctor, .runl_ctor = g84_fifo_runl_ctor, @@ -223,12 +220,12 @@ g84_fifo = { .engn = &g84_engn, .engn_sw = &nv50_engn_sw, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan, .oclass = &g84_fifo_gpfifo_oclass }, + .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan }, }; int g84_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv50_fifo_new_(&g84_fifo, device, type, inst, pfifo); + return nvkm_fifo_new_(&g84_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c index b2634f21d320..c6ca050c38bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c @@ -19,12 +19,10 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ +#include "priv.h" #include "chan.h" #include "runl.h" -#include "nv50.h" -#include "channv50.h" - #include static int @@ -49,7 +47,6 @@ g98_fifo_runl_ctor(struct nvkm_fifo *fifo) static const struct nvkm_fifo_func g98_fifo = { - .dtor = nv50_fifo_dtor, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = nv50_fifo_chid_ctor, .runl_ctor = g98_fifo_runl_ctor, @@ -62,12 +59,12 @@ g98_fifo = { .engn = &g84_engn, .engn_sw = &nv50_engn_sw, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan, .oclass = &g84_fifo_gpfifo_oclass }, + .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan }, }; int g98_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv50_fifo_new_(&g98_fifo, device, type, inst, pfifo); + return nvkm_fifo_new_(&g98_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c index e228ca3a5203..b0c7b562bfc8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include struct ga102_fifo { @@ -148,9 +148,10 @@ static int ga102_chan_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) { - struct volta_channel_gpfifo_a_v0 *args = argv; + struct nvif_chan_v0 *args = argv; struct nvkm_top_device *tdev; struct nvkm_vmm *vmm; + struct nvkm_memory *userd; struct ga102_chan *chan; int ret; @@ -194,9 +195,9 @@ ga102_chan_new(struct nvkm_device *device, nvkm_kmap(chan->inst); nvkm_wo32(chan->inst, 0x010, 0x0000face); nvkm_wo32(chan->inst, 0x030, 0x7ffff902); - nvkm_wo32(chan->inst, 0x048, lower_32_bits(args->ioffset)); - nvkm_wo32(chan->inst, 0x04c, upper_32_bits(args->ioffset) | - (order_base_2(args->ilength / 8) << 16)); + nvkm_wo32(chan->inst, 0x048, lower_32_bits(args->offset)); + nvkm_wo32(chan->inst, 0x04c, upper_32_bits(args->offset) | + (order_base_2(args->length / 8) << 16)); nvkm_wo32(chan->inst, 0x084, 0x20400000); nvkm_wo32(chan->inst, 0x094, 0x30000001); nvkm_wo32(chan->inst, 0x0ac, 0x00020000); @@ -209,7 +210,12 @@ ga102_chan_new(struct nvkm_device *device, nvkm_wo32(chan->inst, 0x224, upper_32_bits(nvkm_memory_bar2(chan->mthd))); nvkm_done(chan->inst); - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->user); + userd = nvkm_umem_search(oclass->client, args->huserd); + if (IS_ERR(userd)) + return PTR_ERR(userd); + + ret = nvkm_memory_kmap(userd, &chan->user); + nvkm_memory_unref(&userd); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 2e2626168bf2..5bb65258c36d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -21,19 +21,18 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" #include "runq.h" -#include "gf100.h" -#include "changf100.h" - #include #include #include #include +#include #include #include @@ -942,16 +941,8 @@ gf100_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr, &fifo->chid); } -static void * -gf100_fifo_dtor(struct nvkm_fifo *base) -{ - struct gf100_fifo *fifo = gf100_fifo(base); - return fifo; -} - static const struct nvkm_fifo_func gf100_fifo = { - .dtor = gf100_fifo_dtor, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = gf100_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, @@ -967,18 +958,12 @@ gf100_fifo = { .runq = &gf100_runq, .engn = &gf100_engn, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan, .oclass = &gf100_fifo_gpfifo_oclass }, + .chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan }, }; int gf100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - struct gf100_fifo *fifo; - - if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) - return -ENOMEM; - *pfifo = &fifo->base; - - return nvkm_fifo_ctor(&gf100_fifo, device, type, inst, &fifo->base); + return nvkm_fifo_new_(&gf100_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h deleted file mode 100644 index 6027ee7dce5a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __GF100_FIFO_H__ -#define __GF100_FIFO_H__ -#define gf100_fifo(p) container_of((p), struct gf100_fifo, base) -#include "priv.h" - -#include - -struct gf100_fifo { - struct nvkm_fifo base; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 6130f492f48a..d8a4d773a58c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -21,17 +21,16 @@ * * Authors: Ben Skeggs */ +#include "priv.h" +#include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" #include "runq.h" -#include "gk104.h" -#include "cgrp.h" -#include "changk104.h" - #include #include +#include #include #include @@ -805,56 +804,8 @@ gk104_fifo_chid_nr(struct nvkm_fifo *fifo) return 4096; } -int -gk104_fifo_oneinit(struct nvkm_fifo *base) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_top_device *tdev; - - /* Determine runlist configuration from topology device info. */ - list_for_each_entry(tdev, &device->top->device, head) { - const int engn = tdev->engine; - - if (engn < 0) - continue; - - fifo->runlist[tdev->runlist].engm |= BIT(engn); - fifo->runlist[tdev->runlist].engm_sw |= BIT(engn); - if (tdev->type == NVKM_ENGINE_GR) - fifo->runlist[tdev->runlist].engm_sw |= BIT(GK104_FIFO_ENGN_SW); - fifo->runlist_nr = max(fifo->runlist_nr, tdev->runlist + 1); - } - - return 0; -} - -void * -gk104_fifo_dtor(struct nvkm_fifo *base) -{ - struct gk104_fifo *fifo = gk104_fifo(base); - return fifo; -} - -int -gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, int nr, struct nvkm_fifo **pfifo) -{ - struct gk104_fifo *fifo; - - if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) - return -ENOMEM; - fifo->func = func; - *pfifo = &fifo->base; - - return nvkm_fifo_ctor(func, device, type, inst, &fifo->base); -} - static const struct nvkm_fifo_func gk104_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = gk104_fifo_chid_nr, .chid_ctor = gf100_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, @@ -871,12 +822,12 @@ gk104_fifo = { .engn = &gk104_engn, .engn_ce = &gk104_engn_ce, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan, .ctor = &gk104_fifo_gpfifo_new }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan }, }; int gk104_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gk104_fifo, device, type, inst, 0, pfifo); + return nvkm_fifo_new_(&gk104_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h deleted file mode 100644 index 97fc9ccc2930..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __GK104_FIFO_H__ -#define __GK104_FIFO_H__ -#define gk104_fifo(p) container_of((p), struct gk104_fifo, base) -#include "priv.h" -struct nvkm_fifo_cgrp; - -#include - -#define gk104_fifo_func nvkm_fifo_func - -struct gk104_fifo_chan; -struct gk104_fifo { - const struct gk104_fifo_func *func; - struct nvkm_fifo base; - - struct { - u32 engm; - u32 engm_sw; - } runlist[16]; - int runlist_nr; -}; - -int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, - int index, int nr, struct nvkm_fifo **); -void *gk104_fifo_dtor(struct nvkm_fifo *base); -int gk104_fifo_oneinit(struct nvkm_fifo *); -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 2afbaf42572d..a8ff21cf7712 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -21,14 +21,12 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" -#include "gk104.h" -#include "changk104.h" - #include #include @@ -107,8 +105,6 @@ gk110_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) static const struct nvkm_fifo_func gk110_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = gk104_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, @@ -125,12 +121,12 @@ gk110_fifo = { .engn = &gk104_engn, .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, - .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan }, }; int gk110_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gk110_fifo, device, type, inst, 0, pfifo); + return nvkm_fifo_new_(&gk110_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 3727be30d7f4..8fa2b0be141a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -21,9 +21,8 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "runq.h" -#include "gk104.h" -#include "changk104.h" #include @@ -51,8 +50,6 @@ gk208_fifo_chid_nr(struct nvkm_fifo *fifo) static const struct nvkm_fifo_func gk208_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = gk208_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, @@ -69,12 +66,12 @@ gk208_fifo = { .engn = &gk104_engn, .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, - .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan }, }; int gk208_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gk208_fifo, device, type, inst, 0, pfifo); + return nvkm_fifo_new_(&gk208_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index eda1446dce27..b63ca836130f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -19,15 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include "gk104.h" -#include "changk104.h" +#include "priv.h" #include static const struct nvkm_fifo_func gk20a_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, @@ -44,12 +41,12 @@ gk20a_fifo = { .engn = &gk104_engn, .engn_ce = &gk104_engn_ce, .cgrp = {{ }, &gk110_cgrp }, - .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan }, }; int gk20a_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gk20a_fifo, device, type, inst, 0, pfifo); + return nvkm_fifo_new_(&gk20a_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 1089062313cc..5ba60021b510 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -24,8 +24,6 @@ #include "priv.h" #include "chan.h" #include "runl.h" -#include "gk104.h" -#include "changk104.h" #include #include @@ -131,8 +129,6 @@ gm107_fifo_chid_nr(struct nvkm_fifo *fifo) static const struct nvkm_fifo_func gm107_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = gm107_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gf100_fifo_runq_nr, @@ -149,12 +145,12 @@ gm107_fifo = { .engn = &gk104_engn, .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, - .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, + .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan }, }; int gm107_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gm107_fifo, device, type, inst, 0, pfifo); + return nvkm_fifo_new_(&gm107_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index 286c1098b665..d92d1ac39191 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -21,8 +21,7 @@ * * Authors: Ben Skeggs */ -#include "gk104.h" -#include "changk104.h" +#include "priv.h" #include @@ -40,8 +39,6 @@ gm200_fifo_chid_nr(struct nvkm_fifo *fifo) static const struct nvkm_fifo_func gm200_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, @@ -58,12 +55,12 @@ gm200_fifo = { .engn = &gk104_engn, .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp }, - .chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, + .chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan }, }; int gm200_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gm200_fifo, device, type, inst, 0, pfifo); + return nvkm_fifo_new_(&gm200_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 45d536d448f0..65bdb6a7d517 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -21,9 +21,8 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "runl.h" -#include "gk104.h" -#include "changk104.h" #include #include @@ -113,8 +112,6 @@ gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit) static const struct nvkm_fifo_func gp100_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, @@ -131,12 +128,12 @@ gp100_fifo = { .engn = &gk104_engn, .engn_ce = &gk104_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, - .chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new }, + .chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan }, }; int gp100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gp100_fifo, device, type, inst, 0, pfifo); + return nvkm_fifo_new_(&gp100_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c deleted file mode 100644 index 31022441ee8f..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include -#include - -#include -#include - -static int -g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct g82_channel_gpfifo_v0 v0; - } *args = data; - struct nv50_fifo *fifo = nv50_fifo(base); - struct nv50_fifo_chan *chan; - u64 ioffset, ilength; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel gpfifo size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " - "pushbuf %llx ioffset %016llx " - "ilength %08x\n", - args->v0.version, args->v0.vmm, args->v0.pushbuf, - args->v0.ioffset, args->v0.ilength); - if (!args->v0.pushbuf) - return -EINVAL; - } else - return ret; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - - ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf, - oclass, chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - ioffset = args->v0.ioffset; - ilength = args->v0.ilength; - - chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false); - return 0; -} - -const struct nvkm_fifo_chan_oclass -g84_fifo_gpfifo_oclass = { - .ctor = g84_fifo_gpfifo_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c deleted file mode 100644 index f87a54e2f575..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "changf100.h" - -#include -#include -#include -#include - -#include -#include - -static void * -gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) -{ - return gf100_fifo_chan(base); -} - -static const struct nvkm_fifo_chan_func -gf100_fifo_gpfifo_func = { - .dtor = gf100_fifo_gpfifo_dtor, -}; - -static int -gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - union { - struct fermi_channel_gpfifo_v0 v0; - } *args = data; - struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_object *parent = oclass->parent; - struct gf100_fifo_chan *chan; - u64 usermem, ioffset, ilength; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel gpfifo size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " - "ioffset %016llx ilength %08x\n", - args->v0.version, args->v0.vmm, args->v0.ioffset, - args->v0.ilength); - if (!args->v0.vmm) - return -EINVAL; - } else - return ret; - - /* allocate channel */ - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - - ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base, - 0x1000, 0x1000, true, args->v0.vmm, 0, - BIT(GF100_FIFO_ENGN_GR) | - BIT(GF100_FIFO_ENGN_MSPDEC) | - BIT(GF100_FIFO_ENGN_MSPPP) | - BIT(GF100_FIFO_ENGN_MSVLD) | - BIT(GF100_FIFO_ENGN_CE0) | - BIT(GF100_FIFO_ENGN_CE1) | - BIT(GF100_FIFO_ENGN_SW), - 0, 0, 0, - oclass, &chan->base); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - usermem = nvkm_memory_addr(chan->base.userd.mem) + chan->base.userd.base; - ioffset = args->v0.ioffset; - ilength = args->v0.ilength; - - chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false); - return 0; -} - -const struct nvkm_fifo_chan_oclass -gf100_fifo_gpfifo_oclass = { - .ctor = gf100_fifo_gpfifo_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c deleted file mode 100644 index 5036edb62dbd..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "changk104.h" -#include "cgrp.h" - -#include -#include -#include -#include -#include - -#include -#include - -void * -gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) -{ - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - return chan; -} - -const struct nvkm_fifo_chan_func -gk104_fifo_gpfifo_func = { - .dtor = gk104_fifo_gpfifo_dtor, -}; - -static int -gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, - u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv, - const struct nvkm_oclass *oclass, - struct nvkm_object **pobject) -{ - struct gk104_fifo_chan *chan; - int runlist = ffs(*runlists) -1, ret; - - if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) - return -EINVAL; - *runlists = BIT_ULL(runlist); - - /* Allocate the channel. */ - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - chan->runl = runlist; - - ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, - 0x1000, 0x1000, true, vmm, 0, fifo->runlist[runlist].engm_sw, - 0, 0, 0, - oclass, &chan->base); - if (ret) - return ret; - - *chid = chan->base.chid; - *inst = chan->base.inst->addr; - - chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), priv); - return 0; -} - -int -gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct kepler_channel_gpfifo_a_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel gpfifo size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " - "ioffset %016llx ilength %08x " - "runlist %016llx priv %d\n", - args->v0.version, args->v0.vmm, args->v0.ioffset, - args->v0.ilength, args->v0.runlist, args->v0.priv); - return gk104_fifo_gpfifo_new_(fifo, - &args->v0.runlist, - &args->v0.chid, - args->v0.vmm, - args->v0.ioffset, - args->v0.ilength, - &args->v0.inst, - args->v0.priv, - oclass, pobject); - } - - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c deleted file mode 100644 index a97ec53d7e6e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "changk104.h" -#include "cgrp.h" - -#include -#include - -#include -#include - -static const struct nvkm_fifo_chan_func -gv100_fifo_gpfifo = { - .dtor = gk104_fifo_gpfifo_dtor, -}; - -int -gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, - struct gk104_fifo *fifo, u64 *runlists, u16 *chid, - u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv, - u32 *token, const struct nvkm_oclass *oclass, - struct nvkm_object **pobject) -{ - struct gk104_fifo_chan *chan; - int runlist = ffs(*runlists) -1, ret; - - if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) - return -EINVAL; - *runlists = BIT_ULL(runlist); - - /* Allocate the channel. */ - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - chan->runl = runlist; - - ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm, - 0, fifo->runlist[runlist].engm, 0, 0, 0, - oclass, &chan->base); - if (ret) - return ret; - - *chid = chan->base.chid; - *inst = chan->base.inst->addr; - *token = chan->base.func->doorbell_handle(&chan->base); - - chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), priv); - return 0; -} - -int -gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct volta_channel_gpfifo_a_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel gpfifo size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " - "ioffset %016llx ilength %08x " - "runlist %016llx priv %d\n", - args->v0.version, args->v0.vmm, args->v0.ioffset, - args->v0.ilength, args->v0.runlist, args->v0.priv); - return gv100_fifo_gpfifo_new_(&gv100_fifo_gpfifo, fifo, - &args->v0.runlist, - &args->v0.chid, - args->v0.vmm, - args->v0.ioffset, - args->v0.ilength, - &args->v0.inst, - args->v0.priv, - &args->v0.token, - oclass, pobject); - } - - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c deleted file mode 100644 index 88ea7c29941e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include -#include - -#include -#include - -static int -nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct nv50_channel_gpfifo_v0 v0; - } *args = data; - struct nv50_fifo *fifo = nv50_fifo(base); - struct nv50_fifo_chan *chan; - u64 ioffset, ilength; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel gpfifo size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " - "pushbuf %llx ioffset %016llx " - "ilength %08x\n", - args->v0.version, args->v0.vmm, args->v0.pushbuf, - args->v0.ioffset, args->v0.ilength); - if (!args->v0.pushbuf) - return -EINVAL; - } else - return ret; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - - ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf, - oclass, chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - ioffset = args->v0.ioffset; - ilength = args->v0.ilength; - - chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false); - return 0; -} - -const struct nvkm_fifo_chan_oclass -nv50_fifo_gpfifo_oclass = { - .ctor = nv50_fifo_gpfifo_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c deleted file mode 100644 index 62a0f9664a9d..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "changk104.h" -#include "cgrp.h" - -#include -#include - -#include -#include - -static const struct nvkm_fifo_chan_func -tu102_fifo_gpfifo = { - .dtor = gk104_fifo_gpfifo_dtor, -}; - -int -tu102_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_object *parent = oclass->parent; - union { - struct volta_channel_gpfifo_a_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create channel gpfifo size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " - "ioffset %016llx ilength %08x " - "runlist %016llx priv %d\n", - args->v0.version, args->v0.vmm, args->v0.ioffset, - args->v0.ilength, args->v0.runlist, args->v0.priv); - return gv100_fifo_gpfifo_new_(&tu102_fifo_gpfifo, fifo, - &args->v0.runlist, - &args->v0.chid, - args->v0.vmm, - args->v0.ioffset, - args->v0.ilength, - &args->v0.inst, - args->v0.priv, - &args->v0.token, - oclass, pobject); - } - - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c index d55dfc93c61e..33066c8cdc64 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -19,16 +19,15 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ +#include "priv.h" #include "chan.h" #include "chid.h" #include "cgrp.h" #include "runl.h" #include "runq.h" -#include "gk104.h" -#include "changk104.h" - #include +#include #include @@ -71,7 +70,7 @@ gv100_chan_ramfc = { const struct nvkm_chan_func_userd gv100_chan_userd = { - .bar = 1, /*FIXME: hw doesn't have poller, flip to user-allocated in uapi commit. */ + .bar = -1, .size = 0x200, .clear = gf100_chan_userd_clear, }; @@ -467,8 +466,6 @@ gv100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo, u32 engm) static const struct nvkm_fifo_func gv100_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, @@ -484,12 +481,12 @@ gv100_fifo = { .engn = &gv100_engn, .engn_ce = &gv100_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, - .chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan, .ctor = gv100_fifo_gpfifo_new }, + .chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan }, }; int gv100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return gk104_fifo_new_(&gv100_fifo, device, type, inst, 0, pfifo); + return nvkm_fifo_new_(&gv100_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 73ae205fc6ba..674faf002b20 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -21,13 +21,12 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" -#include "nv04.h" -#include "channv04.h" #include "regsnv04.h" #include @@ -520,25 +519,6 @@ nv04_fifo_chid_nr(struct nvkm_fifo *fifo) return 16; } -int -nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, int nr, const struct nv04_fifo_ramfc *ramfc, - struct nvkm_fifo **pfifo) -{ - struct nv04_fifo *fifo; - int ret; - - if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) - return -ENOMEM; - *pfifo = &fifo->base; - - ret = nvkm_fifo_ctor(func, device, type, inst, &fifo->base); - if (ret) - return ret; - - return 0; -} - static const struct nvkm_fifo_func nv04_fifo = { .chid_nr = nv04_fifo_chid_nr, @@ -552,12 +532,12 @@ nv04_fifo = { .engn = &nv04_engn, .engn_sw = &nv04_engn, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, NV03_CHANNEL_DMA }, &nv04_chan, .oclass = &nv04_fifo_dma_oclass }, + .chan = {{ 0, 0, NV03_CHANNEL_DMA }, &nv04_chan }, }; int nv04_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv04_fifo_new_(&nv04_fifo, device, type, inst, 0, NULL, pfifo); + return nvkm_fifo_new_(&nv04_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h deleted file mode 100644 index 93248ab24a81..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV04_FIFO_H__ -#define __NV04_FIFO_H__ -#define nv04_fifo(p) container_of((p), struct nv04_fifo, base) -#include "priv.h" - -#define nv04_fifo_ramfc nvkm_ramfc_layout - -struct nv04_fifo { - struct nvkm_fifo base; -}; - -int nv04_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - int nr, const struct nv04_fifo_ramfc *, struct nvkm_fifo **); -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index 9658ac3dac91..a4bcf6b0a7e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "runl.h" @@ -28,8 +29,6 @@ #include #include -#include "nv04.h" -#include "channv04.h" #include "regsnv04.h" #include @@ -103,12 +102,12 @@ nv10_fifo = { .engn = &nv04_engn, .engn_sw = &nv04_engn, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, NV10_CHANNEL_DMA }, &nv10_chan, .oclass = &nv10_fifo_dma_oclass }, + .chan = {{ 0, 0, NV10_CHANNEL_DMA }, &nv10_chan }, }; int nv10_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv04_fifo_new_(&nv10_fifo, device, type, inst, 0, NULL, pfifo); + return nvkm_fifo_new_(&nv10_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index fb0b106eb09b..c70f44fd4f3b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -21,13 +21,12 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" -#include "nv04.h" -#include "channv04.h" #include "regsnv04.h" #include @@ -132,12 +131,12 @@ nv17_fifo = { .engn = &nv04_engn, .engn_sw = &nv04_engn, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, NV17_CHANNEL_DMA }, &nv17_chan, .oclass = &nv17_fifo_dma_oclass }, + .chan = {{ 0, 0, NV17_CHANNEL_DMA }, &nv17_chan }, }; int nv17_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv04_fifo_new_(&nv17_fifo, device, type, inst, 0, NULL, pfifo); + return nvkm_fifo_new_(&nv17_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index 7574be50d959..e50a94b6d7f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -21,13 +21,12 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "chid.h" #include "runl.h" -#include "nv04.h" -#include "channv04.h" #include "regsnv04.h" #include @@ -242,12 +241,12 @@ nv40_fifo = { .engn = &nv40_engn, .engn_sw = &nv40_engn_sw, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, NV40_CHANNEL_DMA }, &nv40_chan, .oclass = &nv40_fifo_dma_oclass }, + .chan = {{ 0, 0, NV40_CHANNEL_DMA }, &nv40_chan }, }; int nv40_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv04_fifo_new_(&nv40_fifo, device, type, inst, 0, NULL, pfifo); + return nvkm_fifo_new_(&nv40_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 829c52a44a36..954b5f3a7d57 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "chid.h" @@ -29,9 +30,6 @@ #include #include -#include "nv50.h" -#include "channv50.h" - #include void @@ -376,34 +374,8 @@ nv50_fifo_chid_nr(struct nvkm_fifo *fifo) return 128; } -void * -nv50_fifo_dtor(struct nvkm_fifo *base) -{ - struct nv50_fifo *fifo = nv50_fifo(base); - return fifo; -} - -int -nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) -{ - struct nv50_fifo *fifo; - int ret; - - if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) - return -ENOMEM; - *pfifo = &fifo->base; - - ret = nvkm_fifo_ctor(func, device, type, inst, &fifo->base); - if (ret) - return ret; - - return 0; -} - static const struct nvkm_fifo_func nv50_fifo = { - .dtor = nv50_fifo_dtor, .chid_nr = nv50_fifo_chid_nr, .chid_ctor = nv50_fifo_chid_ctor, .runl_ctor = nv04_fifo_runl_ctor, @@ -415,12 +387,12 @@ nv50_fifo = { .engn = &nv50_engn, .engn_sw = &nv50_engn_sw, .cgrp = {{ }, &nv04_cgrp }, - .chan = {{ 0, 0, NV50_CHANNEL_GPFIFO }, &nv50_chan, .oclass = &nv50_fifo_gpfifo_oclass }, + .chan = {{ 0, 0, NV50_CHANNEL_GPFIFO }, &nv50_chan }, }; int nv50_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - return nv50_fifo_new_(&nv50_fifo, device, type, inst, pfifo); + return nvkm_fifo_new_(&nv50_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h deleted file mode 100644 index 3c6d67906730..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV50_FIFO_H__ -#define __NV50_FIFO_H__ -#define nv50_fifo(p) container_of((p), struct nv50_fifo, base) -#include "priv.h" - -struct nv50_fifo { - struct nvkm_fifo base; -}; - -int nv50_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_fifo **); - -void *nv50_fifo_dtor(struct nvkm_fifo *); -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index a5df5e2d9d4b..24125e2d5d4f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -11,13 +11,8 @@ struct nvkm_memory; struct nvkm_runl; struct nvkm_runq; struct nvkm_vctx; -struct gk104_fifo; -struct nvkm_fifo_chan_oclass; struct nvkm_fifo_func { - void *(*dtor)(struct nvkm_fifo *); - - int (*oneinit)(struct nvkm_fifo *); int (*chid_nr)(struct nvkm_fifo *); int (*chid_ctor)(struct nvkm_fifo *, int nr); int (*runq_nr)(struct nvkm_fifo *); @@ -59,17 +54,11 @@ struct nvkm_fifo_func { struct nvkm_fifo_func_chan { struct nvkm_sclass user; const struct nvkm_chan_func *func; - const struct nvkm_fifo_chan_oclass { - int (*ctor)(struct nvkm_fifo *, const struct nvkm_oclass *, - void *data, u32 size, struct nvkm_object **); - } *oclass; - int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *, void *, u32, - struct nvkm_object **); } chan; }; -int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_fifo *); +int nvkm_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int, + struct nvkm_fifo **); int nv04_fifo_chid_ctor(struct nvkm_fifo *, int); int nv04_fifo_runl_ctor(struct nvkm_fifo *); @@ -204,4 +193,6 @@ extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault; int nvkm_uchan_new(struct nvkm_fifo *, struct nvkm_cgrp *, const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **); +int nvkm_ucgrp_new(struct nvkm_fifo *, const struct nvkm_oclass *, void *argv, u32 argc, + struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index 608db9b8dc11..ea9e151dbb48 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -19,13 +19,11 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ +#include "priv.h" +#include "cgrp.h" #include "chan.h" #include "runl.h" -#include "gk104.h" -#include "cgrp.h" -#include "changk104.h" - #include #include #include @@ -263,8 +261,6 @@ tu102_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask) static const struct nvkm_fifo_func tu102_fifo = { - .dtor = gk104_fifo_dtor, - .oneinit = gk104_fifo_oneinit, .chid_nr = gm200_fifo_chid_nr, .chid_ctor = gk110_fifo_chid_ctor, .runq_nr = gm200_fifo_runq_nr, @@ -279,19 +275,12 @@ tu102_fifo = { .engn = &gv100_engn, .engn_ce = &gv100_engn_ce, .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true }, - .chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan, .ctor = tu102_fifo_gpfifo_new }, + .chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan }, }; int tu102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - struct gk104_fifo *fifo; - - if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) - return -ENOMEM; - fifo->func = &tu102_fifo; - *pfifo = &fifo->base; - - return nvkm_fifo_ctor(&tu102_fifo, device, type, inst, &fifo->base); + return nvkm_fifo_new_(&tu102_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c new file mode 100644 index 000000000000..52c594dfb1b8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c @@ -0,0 +1,125 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#define nvkm_ucgrp(p) container_of((p), struct nvkm_ucgrp, object) +#include "priv.h" +#include "cgrp.h" +#include "runl.h" + +#include + +#include + +struct nvkm_ucgrp { + struct nvkm_object object; + struct nvkm_cgrp *cgrp; +}; + +static int +nvkm_ucgrp_chan_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_cgrp *cgrp = nvkm_ucgrp(oclass->parent)->cgrp; + + return nvkm_uchan_new(cgrp->runl->fifo, cgrp, oclass, argv, argc, pobject); +} + +static int +nvkm_ucgrp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass) +{ + struct nvkm_cgrp *cgrp = nvkm_ucgrp(object)->cgrp; + struct nvkm_fifo *fifo = cgrp->runl->fifo; + const struct nvkm_fifo_func_chan *chan = &fifo->func->chan; + int c = 0; + + /* *_CHANNEL_GPFIFO_* */ + if (chan->user.oclass) { + if (c++ == index) { + oclass->base = chan->user; + oclass->ctor = nvkm_ucgrp_chan_new; + return 0; + } + } + + return -EINVAL; +} + +static void * +nvkm_ucgrp_dtor(struct nvkm_object *object) +{ + struct nvkm_ucgrp *ucgrp = nvkm_ucgrp(object); + + nvkm_cgrp_unref(&ucgrp->cgrp); + return ucgrp; +} + +static const struct nvkm_object_func +nvkm_ucgrp = { + .dtor = nvkm_ucgrp_dtor, + .sclass = nvkm_ucgrp_sclass, +}; + +int +nvkm_ucgrp_new(struct nvkm_fifo *fifo, const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + union nvif_cgrp_args *args = argv; + struct nvkm_runl *runl; + struct nvkm_vmm *vmm; + struct nvkm_ucgrp *ucgrp; + int ret; + + if (argc < sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + argc -= sizeof(args->v0); + + if (args->v0.namelen != argc) + return -EINVAL; + + /* Lookup objects referenced in args. */ + runl = nvkm_runl_get(fifo, args->v0.runlist, 0); + if (!runl) + return -EINVAL; + + vmm = nvkm_uvmm_search(oclass->client, args->v0.vmm); + if (IS_ERR(vmm)) + return PTR_ERR(vmm); + + /* Allocate channel group. */ + if (!(ucgrp = kzalloc(sizeof(*ucgrp), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + + nvkm_object_ctor(&nvkm_ucgrp, oclass, &ucgrp->object); + *pobject = &ucgrp->object; + + ret = nvkm_cgrp_new(runl, args->v0.name, vmm, true, &ucgrp->cgrp); + if (ret) + goto done; + + /* Return channel group info to caller. */ + args->v0.cgid = ucgrp->cgrp->id; + +done: + nvkm_vmm_unref(&vmm); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c index 1a89c9313662..1dac95ae7b43 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c @@ -20,6 +20,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #define nvkm_uchan(p) container_of((p), struct nvkm_uchan, object) +#include "priv.h" #include "cgrp.h" #include "chan.h" #include "chid.h" @@ -27,11 +28,11 @@ #include #include +#include +#include #include -#include "gk104.h" - struct nvkm_uchan { struct nvkm_object object; struct nvkm_chan *chan; @@ -204,12 +205,20 @@ nvkm_uchan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *ocl { struct nvkm_chan *chan = nvkm_uchan(object)->chan; struct nvkm_engn *engn; - int ret; + int ret, runq = 0; nvkm_runl_foreach_engn(engn, chan->cgrp->runl) { struct nvkm_engine *engine = engn->engine; int c = 0; + /* Each runqueue, on runlists with multiple, has its own LCE. */ + if (engn->runl->func->runqs) { + if (engine->subdev.type == NVKM_ENGINE_CE) { + if (chan->runq != runq++) + continue; + } + } + oclass->engine = engine; oclass->base.oclass = 0; @@ -246,8 +255,8 @@ static int nvkm_uchan_map(struct nvkm_object *object, void *argv, u32 argc, enum nvkm_object_map *type, u64 *addr, u64 *size) { - struct nvkm_device *device = object->engine->subdev.device; struct nvkm_chan *chan = nvkm_uchan(object)->chan; + struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; if (chan->func->userd->bar < 0) return -ENOSYS; @@ -312,23 +321,89 @@ int nvkm_uchan_new(struct nvkm_fifo *fifo, struct nvkm_cgrp *cgrp, const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) { - struct nvkm_object *object = NULL; + union nvif_chan_args *args = argv; + struct nvkm_runl *runl; + struct nvkm_vmm *vmm = NULL; + struct nvkm_dmaobj *ctxdma = NULL; + struct nvkm_memory *userd = NULL; struct nvkm_uchan *uchan; + struct nvkm_chan *chan; int ret; - if (!(uchan = kzalloc(sizeof(*uchan), GFP_KERNEL))) - return -ENOMEM; + if (argc < sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + argc -= sizeof(args->v0); + + if (args->v0.namelen != argc) + return -EINVAL; + + /* Lookup objects referenced in args. */ + runl = nvkm_runl_get(fifo, args->v0.runlist, 0); + if (!runl) + return -EINVAL; + + if (args->v0.vmm) { + vmm = nvkm_uvmm_search(oclass->client, args->v0.vmm); + if (IS_ERR(vmm)) + return PTR_ERR(vmm); + } + + if (args->v0.ctxdma) { + ctxdma = nvkm_dmaobj_search(oclass->client, args->v0.ctxdma); + if (IS_ERR(ctxdma)) { + ret = PTR_ERR(ctxdma); + goto done; + } + } + + if (args->v0.huserd) { + userd = nvkm_umem_search(oclass->client, args->v0.huserd); + if (IS_ERR(userd)) { + ret = PTR_ERR(userd); + userd = NULL; + goto done; + } + } + + /* Allocate channel. */ + if (!(uchan = kzalloc(sizeof(*uchan), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } nvkm_object_ctor(&nvkm_uchan, oclass, &uchan->object); *pobject = &uchan->object; - if (fifo->func->chan.ctor) - ret = fifo->func->chan.ctor(gk104_fifo(fifo), oclass, argv, argc, &object); + ret = nvkm_chan_new_(fifo->func->chan.func, runl, args->v0.runq, cgrp, args->v0.name, + args->v0.priv != 0, args->v0.devm, vmm, ctxdma, args->v0.offset, + args->v0.length, userd, args->v0.ouserd, &uchan->chan); + if (ret) + goto done; + + chan = uchan->chan; + + /* Return channel info to caller. */ + if (chan->func->doorbell_handle) + args->v0.token = chan->func->doorbell_handle(chan); else - ret = fifo->func->chan.oclass->ctor(fifo, oclass, argv, argc, &object); - if (!object) - return ret; + args->v0.token = ~0; + + args->v0.chid = chan->id; + + switch (nvkm_memory_target(chan->inst->memory)) { + case NVKM_MEM_TARGET_INST: args->v0.aper = NVIF_CHAN_V0_INST_APER_INST; break; + case NVKM_MEM_TARGET_VRAM: args->v0.aper = NVIF_CHAN_V0_INST_APER_VRAM; break; + case NVKM_MEM_TARGET_HOST: args->v0.aper = NVIF_CHAN_V0_INST_APER_HOST; break; + case NVKM_MEM_TARGET_NCOH: args->v0.aper = NVIF_CHAN_V0_INST_APER_NCOH; break; + default: + WARN_ON(1); + ret = -EFAULT; + break; + } - uchan->chan = container_of(object, typeof(*uchan->chan), object); + args->v0.inst = nvkm_memory_addr(chan->inst->memory); +done: + nvkm_memory_unref(&userd); + nvkm_vmm_unref(&vmm); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c index 186b4e63e559..524cd3c0e3fe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c @@ -39,7 +39,7 @@ nvkm_uvmm_search(struct nvkm_client *client, u64 handle) if (IS_ERR(object)) return (void *)object; - return nvkm_uvmm(object)->vmm; + return nvkm_vmm_ref(nvkm_uvmm(object)->vmm); } static int -- cgit v1.2.3 From 05d271c32e12c16d18b096c797eef809fd6c9215 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:38 +1000 Subject: drm/nouveau/ce/ga100-: initial support - replaces the hacked-up version that existed solely to support TTM - noop until the next commit, adding proper support for ampere host v2. fixup for ga103 early merge Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvif/class.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h | 2 + drivers/gpu/drm/nouveau/nouveau_bo.c | 3 + drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild | 2 + drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c | 82 +++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c | 44 ++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h | 4 ++ drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 6 ++ 8 files changed, 144 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index ceea074b064b..36c59c7afd95 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -216,6 +216,7 @@ #define PASCAL_DMA_COPY_B 0x0000c1b5 #define VOLTA_DMA_COPY_A 0x0000c3b5 #define TURING_DMA_COPY_A 0x0000c5b5 +#define AMPERE_DMA_COPY_A 0x0000c6b5 #define AMPERE_DMA_COPY_B 0x0000c7b5 #define FERMI_DECOMPRESS 0x000090b8 diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h index cfd2da8e66fe..b616a1e8ca02 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h @@ -12,4 +12,6 @@ int gp100_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n int gp102_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **); int gv100_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **); int tu102_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **); +int ga100_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **); +int ga102_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 813937ad1dc2..a11871e3119c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -856,6 +856,9 @@ nouveau_bo_move_init(struct nouveau_drm *drm) int (*init)(struct nouveau_channel *, u32 handle); } _methods[] = { { "COPY", 4, 0xc7b5, nve0_bo_move_copy, nve0_bo_move_init }, + { "GRCE", 0, 0xc7b5, nve0_bo_move_copy, nvc0_bo_move_init }, + { "COPY", 4, 0xc6b5, nve0_bo_move_copy, nve0_bo_move_init }, + { "GRCE", 0, 0xc6b5, nve0_bo_move_copy, nvc0_bo_move_init }, { "COPY", 4, 0xc5b5, nve0_bo_move_copy, nve0_bo_move_init }, { "GRCE", 0, 0xc5b5, nve0_bo_move_copy, nvc0_bo_move_init }, { "COPY", 4, 0xc3b5, nve0_bo_move_copy, nve0_bo_move_init }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild index ba88613e1e46..8bf1635ffabc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild @@ -8,3 +8,5 @@ nvkm-y += nvkm/engine/ce/gp100.o nvkm-y += nvkm/engine/ce/gp102.o nvkm-y += nvkm/engine/ce/gv100.o nvkm-y += nvkm/engine/ce/tu102.o +nvkm-y += nvkm/engine/ce/ga100.o +nvkm-y += nvkm/engine/ce/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c new file mode 100644 index 000000000000..6648ed62daa6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c @@ -0,0 +1,82 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +#include + +#include + +static irqreturn_t +ga100_ce_intr(struct nvkm_inth *inth) +{ + struct nvkm_subdev *subdev = container_of(inth, typeof(*subdev), inth); + + /*TODO*/ + nvkm_error(subdev, "intr\n"); + return IRQ_NONE; +} + +int +ga100_ce_fini(struct nvkm_engine *engine, bool suspend) +{ + nvkm_inth_block(&engine->subdev.inth); + return 0; +} + +int +ga100_ce_init(struct nvkm_engine *engine) +{ + nvkm_inth_allow(&engine->subdev.inth); + return 0; +} + +int +ga100_ce_oneinit(struct nvkm_engine *engine) +{ + struct nvkm_subdev *subdev = &engine->subdev; + struct nvkm_device *device = subdev->device; + u32 vector; + + vector = nvkm_rd32(device, 0x10442c + (subdev->inst * 0x80)) & 0x00000fff; + + return nvkm_inth_add(&device->vfn->intr, vector, NVKM_INTR_PRIO_NORMAL, + subdev, ga100_ce_intr, &subdev->inth); +} + +static const struct nvkm_engine_func +ga100_ce = { + .oneinit = ga100_ce_oneinit, + .init = ga100_ce_init, + .fini = ga100_ce_fini, + .cclass = &gv100_ce_cclass, + .sclass = { + { -1, -1, AMPERE_DMA_COPY_A }, + {} + } +}; + +int +ga100_ce_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_engine **pengine) +{ + return nvkm_engine_new_(&ga100_ce, device, type, inst, true, pengine); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c new file mode 100644 index 000000000000..9f3448ad625f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c @@ -0,0 +1,44 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +#include + +static const struct nvkm_engine_func +ga102_ce = { + .oneinit = ga100_ce_oneinit, + .init = ga100_ce_init, + .fini = ga100_ce_fini, + .cclass = &gv100_ce_cclass, + .sclass = { + { -1, -1, AMPERE_DMA_COPY_A }, + { -1, -1, AMPERE_DMA_COPY_B }, + {} + } +}; + +int +ga102_ce_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_engine **pengine) +{ + return nvkm_engine_new_(&ga102_ce, device, type, inst, true, pengine); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h index cd53b93664d6..c4c046916fa6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h @@ -8,4 +8,8 @@ void gk104_ce_intr(struct nvkm_engine *); void gp100_ce_intr(struct nvkm_engine *); extern const struct nvkm_object_func gv100_ce_cclass; + +int ga100_ce_oneinit(struct nvkm_engine *); +int ga100_ce_init(struct nvkm_engine *); +int ga100_ce_fini(struct nvkm_engine *, bool); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 4f5921a2aeb0..490fac3a4a3a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2589,6 +2589,7 @@ nv170_chipset = { .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, .vfn = { 0x00000001, ga100_vfn_new }, + .ce = { 0x000003ff, ga100_ce_new }, }; static const struct nvkm_device_chip @@ -2609,6 +2610,7 @@ nv172_chipset = { .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, .vfn = { 0x00000001, ga100_vfn_new }, + .ce = { 0x0000001f, ga102_ce_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, @@ -2632,6 +2634,7 @@ nv173_chipset = { .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, .vfn = { 0x00000001, ga100_vfn_new }, + .ce = { 0x0000001f, ga102_ce_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, @@ -2655,6 +2658,7 @@ nv174_chipset = { .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, .vfn = { 0x00000001, ga100_vfn_new }, + .ce = { 0x0000001f, ga102_ce_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, @@ -2678,6 +2682,7 @@ nv176_chipset = { .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, .vfn = { 0x00000001, ga100_vfn_new }, + .ce = { 0x0000001f, ga102_ce_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, @@ -2701,6 +2706,7 @@ nv177_chipset = { .timer = { 0x00000001, gk20a_timer_new }, .top = { 0x00000001, ga100_top_new }, .vfn = { 0x00000001, ga100_vfn_new }, + .ce = { 0x0000001f, ga102_ce_new }, .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, -- cgit v1.2.3 From 7f4f35ea5b080e6aeb159b4be023a44a527906ec Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:39 +1000 Subject: drm/nouveau/fifo/ga100-: initial support - replaces the hacked-up version that existed solely to support TTM v2. remove earlier hack preventing use of non-stall intr for fences Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvif/class.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 2 + drivers/gpu/drm/nouveau/nouveau_chan.c | 4 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 4 +- drivers/gpu/drm/nouveau/nv84_fence.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 19 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c | 550 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c | 280 +---------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 11 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 3 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h | 8 +- 13 files changed, 610 insertions(+), 276 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index 36c59c7afd95..15529d2c85f9 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -86,6 +86,7 @@ #define PASCAL_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c06f #define VOLTA_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c36f #define TURING_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c46f +#define AMPERE_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c56f #define AMPERE_CHANNEL_GPFIFO_B /* if0020.h */ 0x0000c76f #define NV50_DISP /* if0010.h */ 0x00005070 diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index c71f412bbb7f..4825403a2688 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -56,6 +56,7 @@ struct nvkm_fifo { struct { #define NVKM_FIFO_NONSTALL_EVENT BIT(0) struct nvkm_event event; + struct nvkm_inth intr; } nonstall; struct { @@ -92,5 +93,6 @@ int gm200_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct int gp100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int gv100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int tu102_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); +int ga100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int ga102_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index efd6cf46921b..e648ecd0c1a0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -253,6 +253,7 @@ nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool p int version; } hosts[] = { { AMPERE_CHANNEL_GPFIFO_B, 0 }, + { AMPERE_CHANNEL_GPFIFO_A, 0 }, { TURING_CHANNEL_GPFIFO_A, 0 }, { VOLTA_CHANNEL_GPFIFO_A, 0 }, { PASCAL_CHANNEL_GPFIFO_A, 0 }, @@ -365,8 +366,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) if (ret) return ret; - if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO && - chan->user.oclass < AMPERE_CHANNEL_GPFIFO_B) { + if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) { struct { struct nvif_event_v0 base; struct nvif_chan_event_v0 host; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 61be972f8385..a19f18b251f3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -348,9 +348,6 @@ nouveau_accel_gr_init(struct nouveau_drm *drm) u64 runm; int ret; - if (device->info.family >= NV_DEVICE_INFO_V0_AMPERE) - return; - /* Allocate channel that has access to the graphics engine. */ runm = nvif_fifo_runlist(device, NV_DEVICE_HOST_RUNLIST_ENGINES_GR); if (!runm) { @@ -473,6 +470,7 @@ nouveau_accel_init(struct nouveau_drm *drm) case PASCAL_CHANNEL_GPFIFO_A: case VOLTA_CHANNEL_GPFIFO_A: case TURING_CHANNEL_GPFIFO_A: + case AMPERE_CHANNEL_GPFIFO_A: case AMPERE_CHANNEL_GPFIFO_B: ret = nvc0_fence_create(drm); break; diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index a01fd934c85e..812b8c62eeba 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -210,7 +210,7 @@ nv84_fence_create(struct nouveau_drm *drm) priv->base.context_new = nv84_fence_context_new; priv->base.context_del = nv84_fence_context_del; - priv->base.uevent = drm->client.device.info.family < NV_DEVICE_INFO_V0_AMPERE; + priv->base.uevent = true; mutex_init(&priv->mutex); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 490fac3a4a3a..852c18aec4cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2590,6 +2590,7 @@ nv170_chipset = { .top = { 0x00000001, ga100_top_new }, .vfn = { 0x00000001, ga100_vfn_new }, .ce = { 0x000003ff, ga100_ce_new }, + .fifo = { 0x00000001, ga100_fifo_new }, }; static const struct nvkm_device_chip diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index f9aad4cf8271..5a074b9970ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -23,6 +23,7 @@ nvkm-y += nvkm/engine/fifo/gm200.o nvkm-y += nvkm/engine/fifo/gp100.o nvkm-y += nvkm/engine/fifo/gv100.o nvkm-y += nvkm/engine/fifo/tu102.o +nvkm-y += nvkm/engine/fifo/ga100.o nvkm-y += nvkm/engine/fifo/ga102.o nvkm-y += nvkm/engine/fifo/ucgrp.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 61534a8a33d7..abce1ecfd4d4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -124,6 +124,7 @@ nvkm_fifo_init(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); struct nvkm_runq *runq; + struct nvkm_runl *runl; u32 mask = 0; if (fifo->func->init_pbdmas) { @@ -136,7 +137,13 @@ nvkm_fifo_init(struct nvkm_engine *engine) runq->func->init(runq); } - fifo->func->init(fifo); + nvkm_runl_foreach(runl, fifo) { + if (runl->func->init) + runl->func->init(runl); + } + + if (fifo->func->init) + fifo->func->init(fifo); nvkm_inth_allow(&fifo->engine.subdev.inth); return 0; @@ -243,7 +250,7 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) return ret; nvkm_runl_foreach(runl, fifo) { - RUNL_DEBUG(runl, ""); + RUNL_DEBUG(runl, "chan:%06x", runl->chan); nvkm_runl_foreach_engn(engn, runl) { ENGN_DEBUG(engn, ""); } @@ -259,6 +266,14 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) } } + /* Initialise non-stall intr handling. */ + if (fifo->func->nonstall_ctor) { + ret = fifo->func->nonstall_ctor(fifo); + if (ret) { + nvkm_error(subdev, "nonstall %d\n", ret); + } + } + /* Allocate USERD + BAR1 polling area. */ if (fifo->func->chan.func->userd->bar == 1) { struct nvkm_vmm *bar1 = nvkm_bar_bar1_vmm(device); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c new file mode 100644 index 000000000000..12a5d99d5e77 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c @@ -0,0 +1,550 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" +#include "cgrp.h" +#include "chan.h" +#include "chid.h" +#include "runl.h" +#include "runq.h" + +#include +#include +#include + +#include + +/*TODO: allocate? */ +#define GA100_FIFO_NONSTALL_VECTOR 0 + +static u32 +ga100_chan_doorbell_handle(struct nvkm_chan *chan) +{ + return (chan->cgrp->runl->doorbell << 16) | chan->id; +} + +static void +ga100_chan_stop(struct nvkm_chan *chan) +{ + struct nvkm_runl *runl = chan->cgrp->runl; + + nvkm_wr32(runl->fifo->engine.subdev.device, runl->chan + (chan->id * 4), 0x00000003); +} + +static void +ga100_chan_start(struct nvkm_chan *chan) +{ + struct nvkm_runl *runl = chan->cgrp->runl; + struct nvkm_device *device = runl->fifo->engine.subdev.device; + const int gfid = 0; + + nvkm_wr32(device, runl->chan + (chan->id * 4), 0x00000002); + nvkm_wr32(device, runl->addr + 0x0090, (gfid << 16) | chan->id); /* INTERNAL_DOORBELL. */ +} + +static void +ga100_chan_unbind(struct nvkm_chan *chan) +{ + struct nvkm_runl *runl = chan->cgrp->runl; + + nvkm_wr32(runl->fifo->engine.subdev.device, runl->chan + (chan->id * 4), 0xffffffff); +} + +static int +ga100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) +{ + const u32 limit2 = ilog2(length / 8); + + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x010, 0x0000face); + nvkm_wo32(chan->inst, 0x030, 0x7ffff902); + nvkm_wo32(chan->inst, 0x048, lower_32_bits(offset)); + nvkm_wo32(chan->inst, 0x04c, upper_32_bits(offset) | (limit2 << 16)); + nvkm_wo32(chan->inst, 0x084, 0x20400000); + nvkm_wo32(chan->inst, 0x094, 0x30000000 | devm); + nvkm_wo32(chan->inst, 0x0e4, priv ? 0x00000020 : 0x00000000); + nvkm_wo32(chan->inst, 0x0e8, chan->id); + nvkm_wo32(chan->inst, 0x0f4, 0x00001000 | (priv ? 0x00000100 : 0x00000000)); + nvkm_wo32(chan->inst, 0x0f8, 0x80000000 | GA100_FIFO_NONSTALL_VECTOR); + nvkm_mo32(chan->inst, 0x218, 0x00000000, 0x00000000); + nvkm_done(chan->inst); + return 0; +} + +static const struct nvkm_chan_func_ramfc +ga100_chan_ramfc = { + .write = ga100_chan_ramfc_write, + .devm = 0xfff, + .priv = true, +}; + +const struct nvkm_chan_func +ga100_chan = { + .inst = &gf100_chan_inst, + .userd = &gv100_chan_userd, + .ramfc = &ga100_chan_ramfc, + .unbind = ga100_chan_unbind, + .start = ga100_chan_start, + .stop = ga100_chan_stop, + .preempt = gk110_chan_preempt, + .doorbell_handle = ga100_chan_doorbell_handle, +}; + +static void +ga100_cgrp_preempt(struct nvkm_cgrp *cgrp) +{ + struct nvkm_runl *runl = cgrp->runl; + + nvkm_wr32(runl->fifo->engine.subdev.device, runl->addr + 0x098, 0x01000000 | cgrp->id); +} + +const struct nvkm_cgrp_func +ga100_cgrp = { + .preempt = ga100_cgrp_preempt, +}; + +static int +ga100_engn_cxid(struct nvkm_engn *engn, bool *cgid) +{ + struct nvkm_runl *runl = engn->runl; + struct nvkm_device *device = runl->fifo->engine.subdev.device; + u32 stat = nvkm_rd32(device, runl->addr + 0x200 + engn->id * 0x40); + + ENGN_DEBUG(engn, "status %08x", stat); + *cgid = true; + + switch ((stat & 0x0000e000) >> 13) { + case 0 /* INVALID */: return -ENODEV; + case 1 /* VALID */: + case 5 /* SAVE */: return (stat & 0x00000fff); + case 6 /* LOAD */: return (stat & 0x0fff0000) >> 16; + case 7 /* SWITCH */: + if (nvkm_engine_chsw_load(engn->engine)) + return (stat & 0x0fff0000) >> 16; + return (stat & 0x00000fff); + default: + WARN_ON(1); + break; + } + + return -ENODEV; +} + +const struct nvkm_engn_func +ga100_engn = { + .cxid = ga100_engn_cxid, + .ctor = gk104_ectx_ctor, + .bind = gv100_ectx_bind, +}; + +const struct nvkm_engn_func +ga100_engn_ce = { + .cxid = ga100_engn_cxid, + .ctor = gv100_ectx_ce_ctor, + .bind = gv100_ectx_ce_bind, +}; + +static bool +ga100_runq_idle(struct nvkm_runq *runq) +{ + struct nvkm_device *device = runq->fifo->engine.subdev.device; + + return !(nvkm_rd32(device, 0x04015c + (runq->id * 0x800)) & 0x0000e000); +} + +static bool +ga100_runq_intr_1(struct nvkm_runq *runq, struct nvkm_runl *runl) +{ + struct nvkm_device *device = runq->fifo->engine.subdev.device; + u32 inte = nvkm_rd32(device, 0x040180 + (runq->id * 0x800)); + u32 intr = nvkm_rd32(device, 0x040148 + (runq->id * 0x800)); + u32 stat = intr & inte; + + if (!stat) { + RUNQ_DEBUG(runq, "inte1 %08x %08x", intr, inte); + return false; + } + + if (stat & 0x80000000) { + u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x0800)) & runl->chid->mask; + struct nvkm_chan *chan; + unsigned long flags; + + RUNQ_ERROR(runq, "CTXNOTVALID chid:%d", chid); + chan = nvkm_runl_chan_get_chid(runl, chid, &flags); + if (chan) { + nvkm_chan_error(chan, true); + nvkm_chan_put(&chan, flags); + } + + nvkm_mask(device, 0x0400ac + (runq->id * 0x800), 0x00030000, 0x00030000); + stat &= ~0x80000000; + } + + if (stat) { + RUNQ_ERROR(runq, "intr1 %08x", stat); + nvkm_wr32(device, 0x0401a0 + (runq->id * 0x800), stat); + } + + nvkm_wr32(device, 0x040148 + (runq->id * 0x800), intr); + return true; +} + +static bool +ga100_runq_intr_0(struct nvkm_runq *runq, struct nvkm_runl *runl) +{ + struct nvkm_device *device = runq->fifo->engine.subdev.device; + u32 inte = nvkm_rd32(device, 0x040170 + (runq->id * 0x800)); + u32 intr = nvkm_rd32(device, 0x040108 + (runq->id * 0x800)); + u32 stat = intr & inte; + + if (!stat) { + RUNQ_DEBUG(runq, "inte0 %08x %08x", intr, inte); + return false; + } + + /*TODO: expand on this when fixing up gf100's version. */ + if (stat & 0xc6afe000) { + u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x0800)) & runl->chid->mask; + struct nvkm_chan *chan; + unsigned long flags; + + RUNQ_ERROR(runq, "intr0 %08x", stat); + chan = nvkm_runl_chan_get_chid(runl, chid, &flags); + if (chan) { + nvkm_chan_error(chan, true); + nvkm_chan_put(&chan, flags); + } + + stat &= ~0xc6afe000; + } + + if (stat) { + RUNQ_ERROR(runq, "intr0 %08x", stat); + nvkm_wr32(device, 0x040190 + (runq->id * 0x800), stat); + } + + nvkm_wr32(device, 0x040108 + (runq->id * 0x800), intr); + return true; +} + +static bool +ga100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *runl) +{ + bool intr0 = ga100_runq_intr_0(runq, runl); + bool intr1 = ga100_runq_intr_1(runq, runl); + + return intr0 || intr1; +} + +static void +ga100_runq_init(struct nvkm_runq *runq) +{ + struct nvkm_device *device = runq->fifo->engine.subdev.device; + + nvkm_wr32(device, 0x040108 + (runq->id * 0x800), 0xffffffff); /* INTR_0 */ + nvkm_wr32(device, 0x040148 + (runq->id * 0x800), 0xffffffff); /* INTR_1 */ + nvkm_wr32(device, 0x040170 + (runq->id * 0x800), 0xffffffff); /* INTR_0_EN_SET_TREE */ + nvkm_wr32(device, 0x040180 + (runq->id * 0x800), 0xffffffff); /* INTR_1_EN_SET_TREE */ +} + +const struct nvkm_runq_func +ga100_runq = { + .init = ga100_runq_init, + .intr = ga100_runq_intr, + .idle = ga100_runq_idle, +}; + +static bool +ga100_runl_preempt_pending(struct nvkm_runl *runl) +{ + return nvkm_rd32(runl->fifo->engine.subdev.device, runl->addr + 0x098) & 0x00100000; +} + +static void +ga100_runl_preempt(struct nvkm_runl *runl) +{ + nvkm_wr32(runl->fifo->engine.subdev.device, runl->addr + 0x098, 0x00000000); +} + +static void +ga100_runl_allow(struct nvkm_runl *runl, u32 engm) +{ + nvkm_mask(runl->fifo->engine.subdev.device, runl->addr + 0x094, 0x00000001, 0x00000000); +} + +static void +ga100_runl_block(struct nvkm_runl *runl, u32 engm) +{ + nvkm_mask(runl->fifo->engine.subdev.device, runl->addr + 0x094, 0x00000001, 0x00000001); +} + +static bool +ga100_runl_pending(struct nvkm_runl *runl) +{ + struct nvkm_device *device = runl->fifo->engine.subdev.device; + + return nvkm_rd32(device, runl->addr + 0x08c) & 0x00008000; +} + +static void +ga100_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count) +{ + struct nvkm_device *device = runl->fifo->engine.subdev.device; + u64 addr = nvkm_memory_addr(memory) + start; + + nvkm_wr32(device, runl->addr + 0x080, lower_32_bits(addr)); + nvkm_wr32(device, runl->addr + 0x084, upper_32_bits(addr)); + nvkm_wr32(device, runl->addr + 0x088, count); +} + +static irqreturn_t +ga100_runl_intr(struct nvkm_inth *inth) +{ + struct nvkm_runl *runl = container_of(inth, typeof(*runl), inth); + struct nvkm_engn *engn; + struct nvkm_device *device = runl->fifo->engine.subdev.device; + u32 inte = nvkm_rd32(device, runl->addr + 0x120); + u32 intr = nvkm_rd32(device, runl->addr + 0x100); + u32 stat = intr & inte; + u32 info; + + if (!stat) { + RUNL_DEBUG(runl, "inte %08x %08x", intr, inte); + return IRQ_NONE; + } + + if (stat & 0x00000007) { + nvkm_runl_foreach_engn_cond(engn, runl, stat & BIT(engn->id)) { + info = nvkm_rd32(device, runl->addr + 0x224 + (engn->id * 0x40)); + + tu102_fifo_intr_ctxsw_timeout_info(engn, info); + + nvkm_wr32(device, runl->addr + 0x100, BIT(engn->id)); + stat &= ~BIT(engn->id); + } + } + + if (stat & 0x00000300) { + nvkm_wr32(device, runl->addr + 0x100, stat & 0x00000300); + stat &= ~0x00000300; + } + + if (stat & 0x00010000) { + if (runl->runq[0]) { + if (runl->runq[0]->func->intr(runl->runq[0], runl)) + stat &= ~0x00010000; + } + } + + if (stat & 0x00020000) { + if (runl->runq[1]) { + if (runl->runq[1]->func->intr(runl->runq[1], runl)) + stat &= ~0x00020000; + } + } + + if (stat) { + RUNL_ERROR(runl, "intr %08x", stat); + nvkm_wr32(device, runl->addr + 0x140, stat); + } + + nvkm_wr32(device, runl->addr + 0x180, 0x00000001); + return IRQ_HANDLED; +} + +static void +ga100_runl_fini(struct nvkm_runl *runl) +{ + nvkm_mask(runl->fifo->engine.subdev.device, runl->addr + 0x300, 0x80000000, 0x00000000); + nvkm_inth_block(&runl->inth); +} + +static void +ga100_runl_init(struct nvkm_runl *runl) +{ + struct nvkm_fifo *fifo = runl->fifo; + struct nvkm_runq *runq; + struct nvkm_device *device = fifo->engine.subdev.device; + int i; + + /* Submit NULL runlist and preempt. */ + nvkm_wr32(device, runl->addr + 0x088, 0x00000000); + runl->func->preempt(runl); + + /* Enable doorbell. */ + nvkm_mask(device, runl->addr + 0x300, 0x80000000, 0x80000000); + + nvkm_wr32(device, runl->addr + 0x100, 0xffffffff); /* INTR_0 */ + nvkm_wr32(device, runl->addr + 0x140, 0xffffffff); /* INTR_0_EN_CLEAR_TREE(0) */ + nvkm_wr32(device, runl->addr + 0x120, 0x000f1307); /* INTR_0_EN_SET_TREE(0) */ + nvkm_wr32(device, runl->addr + 0x148, 0xffffffff); /* INTR_0_EN_CLEAR_TREE(1) */ + nvkm_wr32(device, runl->addr + 0x128, 0x00000000); /* INTR_0_EN_SET_TREE(1) */ + + /* Init PBDMA(s). */ + for (i = 0; i < runl->runq_nr; i++) { + runq = runl->runq[i]; + runq->func->init(runq); + } + + nvkm_inth_allow(&runl->inth); +} + +const struct nvkm_runl_func +ga100_runl = { + .init = ga100_runl_init, + .fini = ga100_runl_fini, + .size = 16, + .update = nv50_runl_update, + .insert_cgrp = gv100_runl_insert_cgrp, + .insert_chan = gv100_runl_insert_chan, + .commit = ga100_runl_commit, + .wait = nv50_runl_wait, + .pending = ga100_runl_pending, + .block = ga100_runl_block, + .allow = ga100_runl_allow, + .preempt = ga100_runl_preempt, + .preempt_pending = ga100_runl_preempt_pending, +}; + +static int +ga100_runl_new(struct nvkm_fifo *fifo, int id, u32 addr, struct nvkm_runl **prunl) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_runl *runl; + u32 chcfg = nvkm_rd32(device, addr + 0x004); + u32 chnum = 1 << (chcfg & 0x0000000f); + u32 chaddr = (chcfg & 0xfffffff0); + u32 dbcfg = nvkm_rd32(device, addr + 0x008); + u32 vector = nvkm_rd32(device, addr + 0x160); + int i, ret; + + runl = *prunl = nvkm_runl_new(fifo, id, addr, chnum); + if (IS_ERR(runl)) + return PTR_ERR(runl); + + for (i = 0; i < 2; i++) { + u32 pbcfg = nvkm_rd32(device, addr + 0x010 + (i * 0x04)); + if (pbcfg & 0x80000000) { + runl->runq[runl->runq_nr] = + nvkm_runq_new(fifo, ((pbcfg & 0x03fffc00) - 0x040000) / 0x800); + if (!runl->runq[runl->runq_nr]) + return -ENOMEM; + + runl->runq_nr++; + } + } + + ret = nvkm_inth_add(&device->vfn->intr, vector & 0x00000fff, NVKM_INTR_PRIO_NORMAL, + &fifo->engine.subdev, ga100_runl_intr, &runl->inth); + if (ret) + return ret; + + runl->chan = chaddr; + runl->doorbell = dbcfg >> 16; + return 0; +} + +static irqreturn_t +ga100_fifo_nonstall_intr(struct nvkm_inth *inth) +{ + struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), nonstall.intr); + + nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT); + return IRQ_HANDLED; +} + +static void +ga100_fifo_nonstall_block(struct nvkm_event *event, int type, int index) +{ + struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); + + nvkm_inth_block(&fifo->nonstall.intr); +} + +static void +ga100_fifo_nonstall_allow(struct nvkm_event *event, int type, int index) +{ + struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); + + nvkm_inth_allow(&fifo->nonstall.intr); +} + +const struct nvkm_event_func +ga100_fifo_nonstall = { + .init = ga100_fifo_nonstall_allow, + .fini = ga100_fifo_nonstall_block, +}; + +int +ga100_fifo_nonstall_ctor(struct nvkm_fifo *fifo) +{ + return nvkm_inth_add(&fifo->engine.subdev.device->vfn->intr, GA100_FIFO_NONSTALL_VECTOR, + NVKM_INTR_PRIO_NORMAL, &fifo->engine.subdev, ga100_fifo_nonstall_intr, + &fifo->nonstall.intr); +} + +int +ga100_fifo_runl_ctor(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_top_device *tdev; + struct nvkm_runl *runl; + int id = 0, ret; + + nvkm_list_foreach(tdev, &device->top->device, head, tdev->runlist >= 0) { + runl = nvkm_runl_get(fifo, -1, tdev->runlist); + if (!runl) { + ret = ga100_runl_new(fifo, id++, tdev->runlist, &runl); + if (ret) + return ret; + } + + if (tdev->engine < 0) + continue; + + nvkm_runl_add(runl, tdev->engine, (tdev->type == NVKM_ENGINE_CE) ? + fifo->func->engn_ce : fifo->func->engn, tdev->type, tdev->inst); + } + + return 0; +} + +static const struct nvkm_fifo_func +ga100_fifo = { + .runl_ctor = ga100_fifo_runl_ctor, + .mmu_fault = &tu102_fifo_mmu_fault, + .nonstall_ctor = ga100_fifo_nonstall_ctor, + .nonstall = &ga100_fifo_nonstall, + .runl = &ga100_runl, + .runq = &ga100_runq, + .engn = &ga100_engn, + .engn_ce = &ga100_engn_ce, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &ga100_cgrp, .force = true }, + .chan = {{ 0, 0, AMPERE_CHANNEL_GPFIFO_A }, &ga100_chan }, +}; + +int +ga100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_fifo **pfifo) +{ + return nvkm_fifo_new_(&ga100_fifo, device, type, inst, pfifo); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c index b0c7b562bfc8..2cdf5da339b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c @@ -19,281 +19,27 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#define ga102_fifo(p) container_of((p), struct ga102_fifo, base.engine) -#define ga102_chan(p) container_of((p), struct ga102_chan, object) -#include +#include "priv.h" -#include -#include -#include -#include - -#include -#include #include -struct ga102_fifo { - struct nvkm_fifo base; -}; - -struct ga102_chan { - struct nvkm_object object; - - struct { - u32 runl; - u32 chan; - } ctrl; - - struct nvkm_memory *mthd; - struct nvkm_memory *inst; - struct nvkm_memory *user; - struct nvkm_memory *runl; - - struct nvkm_vmm *vmm; -}; - -static int -ga102_chan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass) -{ - if (index == 0) { - oclass->ctor = nvkm_object_new; - oclass->base = (struct nvkm_sclass) { -1, -1, AMPERE_DMA_COPY_B }; - return 0; - } - - return -EINVAL; -} - -static int -ga102_chan_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct ga102_chan *chan = ga102_chan(object); - struct nvkm_device *device = chan->object.engine->subdev.device; - u64 bar2 = nvkm_memory_bar2(chan->user); - - if (bar2 == ~0ULL) - return -EFAULT; - - *type = NVKM_OBJECT_MAP_IO; - *addr = device->func->resource_addr(device, 3) + bar2; - *size = 0x1000; - return 0; -} - -static int -ga102_chan_fini(struct nvkm_object *object, bool suspend) -{ - struct ga102_chan *chan = ga102_chan(object); - struct nvkm_device *device = chan->object.engine->subdev.device; - - nvkm_wr32(device, chan->ctrl.chan, 0x00000003); - - nvkm_wr32(device, chan->ctrl.runl + 0x098, 0x01000000); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, chan->ctrl.runl + 0x098) & 0x00100000)) - break; - ); - - nvkm_wr32(device, chan->ctrl.runl + 0x088, 0); - - nvkm_wr32(device, chan->ctrl.chan, 0xffffffff); - return 0; -} - -static int -ga102_chan_init(struct nvkm_object *object) -{ - struct ga102_chan *chan = ga102_chan(object); - struct nvkm_device *device = chan->object.engine->subdev.device; - - nvkm_mask(device, chan->ctrl.runl + 0x300, 0x80000000, 0x80000000); - - nvkm_wr32(device, chan->ctrl.runl + 0x080, lower_32_bits(nvkm_memory_addr(chan->runl))); - nvkm_wr32(device, chan->ctrl.runl + 0x084, upper_32_bits(nvkm_memory_addr(chan->runl))); - nvkm_wr32(device, chan->ctrl.runl + 0x088, 2); - - nvkm_wr32(device, chan->ctrl.chan, 0x00000002); - nvkm_wr32(device, chan->ctrl.runl + 0x0090, 0); - return 0; -} - -static void * -ga102_chan_dtor(struct nvkm_object *object) -{ - struct ga102_chan *chan = ga102_chan(object); - - if (chan->vmm) { - nvkm_vmm_part(chan->vmm, chan->inst); - nvkm_vmm_unref(&chan->vmm); - } - - nvkm_memory_unref(&chan->runl); - nvkm_memory_unref(&chan->user); - nvkm_memory_unref(&chan->inst); - nvkm_memory_unref(&chan->mthd); - return chan; -} - -static const struct nvkm_object_func -ga102_chan = { - .dtor = ga102_chan_dtor, - .init = ga102_chan_init, - .fini = ga102_chan_fini, - .map = ga102_chan_map, - .sclass = ga102_chan_sclass, -}; - -static int -ga102_chan_new(struct nvkm_device *device, - const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) -{ - struct nvif_chan_v0 *args = argv; - struct nvkm_top_device *tdev; - struct nvkm_vmm *vmm; - struct nvkm_memory *userd; - struct ga102_chan *chan; - int ret; - - if (argc != sizeof(*args)) - return -ENOSYS; - - vmm = nvkm_uvmm_search(oclass->client, args->vmm); - if (IS_ERR(vmm)) - return PTR_ERR(vmm); - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - - nvkm_object_ctor(&ga102_chan, oclass, &chan->object); - *pobject = &chan->object; - - list_for_each_entry(tdev, &device->top->device, head) { - if (tdev->type == NVKM_ENGINE_CE) { - chan->ctrl.runl = tdev->runlist; - break; - } - } - - if (!chan->ctrl.runl) - return -ENODEV; - - chan->ctrl.chan = nvkm_rd32(device, chan->ctrl.runl + 0x004) & 0xfffffff0; - - args->chid = 0; - args->inst = 0; - args->token = nvkm_rd32(device, chan->ctrl.runl + 0x008) & 0xffff0000; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->mthd); - if (ret) - return ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->inst); - if (ret) - return ret; - - nvkm_kmap(chan->inst); - nvkm_wo32(chan->inst, 0x010, 0x0000face); - nvkm_wo32(chan->inst, 0x030, 0x7ffff902); - nvkm_wo32(chan->inst, 0x048, lower_32_bits(args->offset)); - nvkm_wo32(chan->inst, 0x04c, upper_32_bits(args->offset) | - (order_base_2(args->length / 8) << 16)); - nvkm_wo32(chan->inst, 0x084, 0x20400000); - nvkm_wo32(chan->inst, 0x094, 0x30000001); - nvkm_wo32(chan->inst, 0x0ac, 0x00020000); - nvkm_wo32(chan->inst, 0x0e4, 0x00000000); - nvkm_wo32(chan->inst, 0x0e8, 0); - nvkm_wo32(chan->inst, 0x0f4, 0x00001000); - nvkm_wo32(chan->inst, 0x0f8, 0x10003080); - nvkm_mo32(chan->inst, 0x218, 0x00000000, 0x00000000); - nvkm_wo32(chan->inst, 0x220, lower_32_bits(nvkm_memory_bar2(chan->mthd))); - nvkm_wo32(chan->inst, 0x224, upper_32_bits(nvkm_memory_bar2(chan->mthd))); - nvkm_done(chan->inst); - - userd = nvkm_umem_search(oclass->client, args->huserd); - if (IS_ERR(userd)) - return PTR_ERR(userd); - - ret = nvkm_memory_kmap(userd, &chan->user); - nvkm_memory_unref(&userd); - if (ret) - return ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->runl); - if (ret) - return ret; - - nvkm_kmap(chan->runl); - nvkm_wo32(chan->runl, 0x00, 0x80030001); - nvkm_wo32(chan->runl, 0x04, 1); - nvkm_wo32(chan->runl, 0x08, 0); - nvkm_wo32(chan->runl, 0x0c, 0x00000000); - nvkm_wo32(chan->runl, 0x10, lower_32_bits(nvkm_memory_addr(chan->user))); - nvkm_wo32(chan->runl, 0x14, upper_32_bits(nvkm_memory_addr(chan->user))); - nvkm_wo32(chan->runl, 0x18, lower_32_bits(nvkm_memory_addr(chan->inst))); - nvkm_wo32(chan->runl, 0x1c, upper_32_bits(nvkm_memory_addr(chan->inst))); - nvkm_done(chan->runl); - - ret = nvkm_vmm_join(vmm, chan->inst); - if (ret) - return ret; - - chan->vmm = nvkm_vmm_ref(vmm); - return 0; -} - -static const struct nvkm_device_oclass -ga102_chan_oclass = { - .ctor = ga102_chan_new, -}; - -static int -ga102_fifo_sclass(struct nvkm_oclass *oclass, int index, const struct nvkm_device_oclass **class) -{ - if (index == 0) { - oclass->base = (struct nvkm_sclass) { 0, 0, AMPERE_CHANNEL_GPFIFO_B }; - *class = &ga102_chan_oclass; - return 0; - } - - return 1; -} - -static int -ga102_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data) -{ - switch (mthd) { - case NV_DEVICE_HOST_CHANNELS: *data = 1; return 0; - default: - break; - } - - return -ENOSYS; -} - -static void * -ga102_fifo_dtor(struct nvkm_engine *engine) -{ - return ga102_fifo(engine); -} - -static const struct nvkm_engine_func +static const struct nvkm_fifo_func ga102_fifo = { - .dtor = ga102_fifo_dtor, - .info = ga102_fifo_info, - .base.sclass = ga102_fifo_sclass, + .runl_ctor = ga100_fifo_runl_ctor, + .mmu_fault = &tu102_fifo_mmu_fault, + .nonstall_ctor = ga100_fifo_nonstall_ctor, + .nonstall = &ga100_fifo_nonstall, + .runl = &ga100_runl, + .runq = &ga100_runq, + .engn = &ga100_engn, + .engn_ce = &ga100_engn_ce, + .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &ga100_cgrp, .force = true }, + .chan = {{ 0, 0, AMPERE_CHANNEL_GPFIFO_B }, &ga100_chan }, }; int ga102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { - struct ga102_fifo *fifo; - - if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) - return -ENOMEM; - - nvkm_engine_ctor(&ga102_fifo, device, type, inst, true, &fifo->base.engine); - *pfifo = &fifo->base; - return 0; + return nvkm_fifo_new_(&ga102_fifo, device, type, inst, pfifo); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index 24125e2d5d4f..4d448be19224 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -37,6 +37,7 @@ struct nvkm_fifo_func { void (*pause)(struct nvkm_fifo *, unsigned long *); void (*start)(struct nvkm_fifo *, unsigned long *); + int (*nonstall_ctor)(struct nvkm_fifo *); const struct nvkm_event_func *nonstall; const struct nvkm_runl_func *runl; @@ -191,6 +192,16 @@ extern const struct nvkm_chan_func_ramfc gv100_chan_ramfc; void tu102_fifo_intr_ctxsw_timeout_info(struct nvkm_engn *, u32 info); extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault; +int ga100_fifo_runl_ctor(struct nvkm_fifo *); +int ga100_fifo_nonstall_ctor(struct nvkm_fifo *); +extern const struct nvkm_event_func ga100_fifo_nonstall; +extern const struct nvkm_runl_func ga100_runl; +extern const struct nvkm_runq_func ga100_runq; +extern const struct nvkm_engn_func ga100_engn; +extern const struct nvkm_engn_func ga100_engn_ce; +extern const struct nvkm_cgrp_func ga100_cgrp; +extern const struct nvkm_chan_func ga100_chan; + int nvkm_uchan_new(struct nvkm_fifo *, struct nvkm_cgrp *, const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **); int nvkm_ucgrp_new(struct nvkm_fifo *, const struct nvkm_oclass *, void *argv, u32 argc, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index e654c1c4f769..fe51c075d6c4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -308,6 +308,9 @@ nvkm_runl_block(struct nvkm_runl *runl) void nvkm_runl_fini(struct nvkm_runl *runl) { + if (runl->func->fini) + runl->func->fini(runl); + flush_work(&runl->work); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h index 5159b64377c5..c93d21bb7bd5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h @@ -1,6 +1,6 @@ #ifndef __NVKM_RUNL_H__ #define __NVKM_RUNL_H__ -#include +#include struct nvkm_cctx; struct nvkm_cgrp; struct nvkm_chan; @@ -36,6 +36,8 @@ struct nvkm_engn { struct nvkm_runl { const struct nvkm_runl_func { + void (*init)(struct nvkm_runl *); + void (*fini)(struct nvkm_runl *); int runqs; u8 size; int (*update)(struct nvkm_runl *); @@ -53,6 +55,8 @@ struct nvkm_runl { struct nvkm_fifo *fifo; int id; u32 addr; + u32 chan; + u16 doorbell; struct nvkm_chid *cgid; #define NVKM_CHAN_EVENT_ERRORED BIT(0) @@ -63,6 +67,8 @@ struct nvkm_runl { struct nvkm_runq *runq[2]; int runq_nr; + struct nvkm_inth inth; + struct list_head cgrps; int cgrp_nr; int chan_nr; -- cgit v1.2.3 From 74f9dcb0df10567c1124b0cece2c6229a8c77cab Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:47 +1000 Subject: drm/nouveau/gsp: add funcs Ampere. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/layout.h | 4 ++-- drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c | 4 +++- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c | 11 ++++++++--- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h | 6 +++++- 5 files changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h index a344ddb77c80..58108dea5aeb 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h @@ -1,9 +1,10 @@ /* SPDX-License-Identifier: MIT */ +NVKM_LAYOUT_ONCE(NVKM_SUBDEV_TOP , struct nvkm_top , top) +NVKM_LAYOUT_ONCE(NVKM_SUBDEV_GSP , struct nvkm_gsp , gsp) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VFN , struct nvkm_vfn , vfn) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_PCI , struct nvkm_pci , pci) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VBIOS , struct nvkm_bios , bios) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_DEVINIT , struct nvkm_devinit , devinit) -NVKM_LAYOUT_ONCE(NVKM_SUBDEV_TOP , struct nvkm_top , top) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_PRIVRING, struct nvkm_subdev , privring) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_GPIO , struct nvkm_gpio , gpio) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_I2C , struct nvkm_i2c , i2c) @@ -24,7 +25,6 @@ NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VOLT , struct nvkm_volt , volt) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_ICCSENSE, struct nvkm_iccsense, iccsense) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_THERM , struct nvkm_therm , therm) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_CLK , struct nvkm_clk , clk) -NVKM_LAYOUT_ONCE(NVKM_SUBDEV_GSP , struct nvkm_gsp , gsp) NVKM_LAYOUT_INST(NVKM_SUBDEV_IOCTRL , struct nvkm_subdev , ioctrl, 3) NVKM_LAYOUT_ONCE(NVKM_SUBDEV_FLA , struct nvkm_subdev , fla) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h index cf42a59d4e58..ccf886ec1f84 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h @@ -5,7 +5,9 @@ #include struct nvkm_gsp { + const struct nvkm_gsp_func *func; struct nvkm_subdev subdev; + struct nvkm_falcon falcon; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c index 22574886b819..591ac95c2669 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c @@ -53,5 +53,7 @@ nvkm_gsp_new_(const struct nvkm_gsp_fwif *fwif, struct nvkm_device *device, if (IS_ERR(fwif)) return PTR_ERR(fwif); - return nvkm_falcon_ctor(fwif->flcn, &gsp->subdev, gsp->subdev.name, 0, &gsp->falcon); + gsp->func = fwif->func; + + return nvkm_falcon_ctor(gsp->func->flcn, &gsp->subdev, gsp->subdev.name, 0, &gsp->falcon); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c index 6c4ef62a746a..bc1138799ce5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c @@ -36,6 +36,11 @@ gv100_gsp_flcn = { .disable = nvkm_falcon_v1_disable, }; +static const struct nvkm_gsp_func +gv100_gsp = { + .flcn = &gv100_gsp_flcn, +}; + static int gv100_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif) { @@ -43,8 +48,8 @@ gv100_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif) } static struct nvkm_gsp_fwif -gv100_gsp[] = { - { -1, gv100_gsp_nofw, &gv100_gsp_flcn }, +gv100_gsps[] = { + { -1, gv100_gsp_nofw, &gv100_gsp }, {} }; @@ -52,5 +57,5 @@ int gv100_gsp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gsp **pgsp) { - return nvkm_gsp_new_(gv100_gsp, device, type, inst, pgsp); + return nvkm_gsp_new_(gv100_gsps, device, type, inst, pgsp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h index 19381ddd38d4..89749a40203c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h @@ -4,10 +4,14 @@ #include enum nvkm_acr_lsf_id; +struct nvkm_gsp_func { + const struct nvkm_falcon_func *flcn; +}; + struct nvkm_gsp_fwif { int version; int (*load)(struct nvkm_gsp *, int ver, const struct nvkm_gsp_fwif *); - const struct nvkm_falcon_func *flcn; + const struct nvkm_gsp_func *func; }; int nvkm_gsp_new_(const struct nvkm_gsp_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int, -- cgit v1.2.3 From b7f44ef7320a50dd6718df06f8750489c1b1d5ea Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:48 +1000 Subject: drm/nouveau/pmu: move preinit() falcon reset to devinit Cleanup before falcon changes. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c | 8 +++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 12 ------------ 2 files changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c index a308b9bde449..f30718d7e61a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c @@ -26,6 +26,7 @@ #include #include #include +#include #include static void @@ -85,13 +86,18 @@ pmu_load(struct nv50_devinit *init, u8 type, bool post, struct nvkm_subdev *subdev = &init->base.subdev; struct nvkm_bios *bios = subdev->device->bios; struct nvbios_pmuR pmu; + int ret; if (!nvbios_pmuRm(bios, type, &pmu)) return -EINVAL; - if (!post) + if (!post || !subdev->device->pmu) return 0; + ret = nvkm_falcon_reset(&subdev->device->pmu->falcon); + if (ret) + return ret; + pmu_code(init, pmu.boot_addr_pmu, pmu.boot_addr, pmu.boot_size, false); pmu_code(init, pmu.code_addr_pmu, pmu.code_addr, pmu.code_size, true); pmu_data(init, pmu.data_addr_pmu, pmu.data_addr, pmu.data_size); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 455e95a89259..e10f46c7e817 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -99,9 +99,6 @@ nvkm_pmu_reset(struct nvkm_pmu *pmu) { struct nvkm_device *device = pmu->subdev.device; - if (!pmu->func->enabled(pmu)) - return; - /* Reset. */ if (pmu->func->reset) pmu->func->reset(pmu); @@ -113,14 +110,6 @@ nvkm_pmu_reset(struct nvkm_pmu *pmu) ); } -static int -nvkm_pmu_preinit(struct nvkm_subdev *subdev) -{ - struct nvkm_pmu *pmu = nvkm_pmu(subdev); - nvkm_pmu_reset(pmu); - return 0; -} - static int nvkm_pmu_init(struct nvkm_subdev *subdev) { @@ -160,7 +149,6 @@ nvkm_pmu_dtor(struct nvkm_subdev *subdev) static const struct nvkm_subdev_func nvkm_pmu = { .dtor = nvkm_pmu_dtor, - .preinit = nvkm_pmu_preinit, .init = nvkm_pmu_init, .fini = nvkm_pmu_fini, .intr = nvkm_pmu_intr, -- cgit v1.2.3 From ccdc043123d2a485e173e5e2627598151b7850b3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:48 +1000 Subject: drm/nouveau/pmu: move init() falcon reset to non-nvfw code Cleanup before falcon changes. - fixes (attempt at?) reset of pmu while rtos is running, on gm20b v2: - remove extra whitespace Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 31 +++--------------------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c | 1 - drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c | 2 -- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 7 +++--- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c | 7 ------ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 14 ++--------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c | 32 ++++++++++++++----------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 3 +-- 8 files changed, 27 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index e10f46c7e817..51808a4e75ac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -81,6 +81,9 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); + if (!subdev->use.enabled) + return 0; + if (pmu->func->fini) pmu->func->fini(pmu); @@ -94,42 +97,14 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) return 0; } -static void -nvkm_pmu_reset(struct nvkm_pmu *pmu) -{ - struct nvkm_device *device = pmu->subdev.device; - - /* Reset. */ - if (pmu->func->reset) - pmu->func->reset(pmu); - - /* Wait for IMEM/DMEM scrubbing to be complete. */ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006)) - break; - ); -} - static int nvkm_pmu_init(struct nvkm_subdev *subdev) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); - struct nvkm_device *device = pmu->subdev.device; if (!pmu->func->init) return 0; - if (pmu->func->enabled(pmu)) { - /* Inhibit interrupts, and wait for idle. */ - nvkm_wr32(device, 0x10a014, 0x0000ffff); - nvkm_msec(device, 2000, - if (!nvkm_rd32(device, 0x10a04c)) - break; - ); - - nvkm_pmu_reset(pmu); - } - return pmu->func->init(pmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c index a67a42e73f08..b5e52b35f5d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c @@ -197,7 +197,6 @@ gk20a_dvfs_data= { static const struct nvkm_pmu_func gk20a_pmu = { .flcn = >215_pmu_flcn, - .enabled = gf100_pmu_enabled, .init = gk20a_pmu_init, .fini = gk20a_pmu_fini, .reset = gf100_pmu_reset, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c index 40439e329aa9..34e8320421f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c @@ -55,11 +55,9 @@ gm200_pmu_flcn = { static const struct nvkm_pmu_func gm200_pmu = { .flcn = &gm200_pmu_flcn, - .enabled = gf100_pmu_enabled, .reset = gf100_pmu_reset, }; - int gm200_pmu_nofw(struct nvkm_pmu *pmu, int ver, const struct nvkm_pmu_fwif *fwif) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 612310d5d481..2b73848d4aed 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -166,7 +166,7 @@ gm20b_pmu_acr_init_wpr(struct nvkm_pmu *pmu) gm20b_pmu_acr_init_wpr_callback, pmu, 0); } -int +static int gm20b_pmu_initmsg(struct nvkm_pmu *pmu) { struct nv_pmu_init_msg msg; @@ -192,7 +192,7 @@ gm20b_pmu_initmsg(struct nvkm_pmu *pmu) return gm20b_pmu_acr_init_wpr(pmu); } -void +static void gm20b_pmu_recv(struct nvkm_pmu *pmu) { if (!pmu->initmsg_received) { @@ -209,10 +209,9 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu) nvkm_falcon_msgq_recv(pmu->msgq); } -static const struct nvkm_pmu_func +const struct nvkm_pmu_func gm20b_pmu = { .flcn = &gm200_pmu_flcn, - .enabled = gf100_pmu_enabled, .intr = gt215_pmu_intr, .recv = gm20b_pmu_recv, .initmsg = gm20b_pmu_initmsg, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c index 1a6f9c3af5ec..9fd1116ebe27 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c @@ -31,16 +31,9 @@ gp102_pmu_reset(struct nvkm_pmu *pmu) nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000000); } -static bool -gp102_pmu_enabled(struct nvkm_pmu *pmu) -{ - return !(nvkm_rd32(pmu->subdev.device, 0x10a3c0) & 0x00000001); -} - static const struct nvkm_pmu_func gp102_pmu = { .flcn = &gm200_pmu_flcn, - .enabled = gp102_pmu_enabled, .reset = gp102_pmu_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index 94cfb1791af6..9fba37ec05e0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -76,16 +76,6 @@ gp10b_pmu_acr = { .bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons, }; -static const struct nvkm_pmu_func -gp10b_pmu = { - .flcn = &gm200_pmu_flcn, - .enabled = gf100_pmu_enabled, - .intr = gt215_pmu_intr, - .recv = gm20b_pmu_recv, - .initmsg = gm20b_pmu_initmsg, - .reset = gp102_pmu_reset, -}; - #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) MODULE_FIRMWARE("nvidia/gp10b/pmu/desc.bin"); MODULE_FIRMWARE("nvidia/gp10b/pmu/image.bin"); @@ -94,8 +84,8 @@ MODULE_FIRMWARE("nvidia/gp10b/pmu/sig.bin"); static const struct nvkm_pmu_fwif gp10b_pmu_fwif[] = { - { 0, gm20b_pmu_load, &gp10b_pmu, &gp10b_pmu_acr }, - { -1, gm200_pmu_nofw, &gp10b_pmu }, + { 0, gm20b_pmu_load, &gm20b_pmu, &gp10b_pmu_acr }, + { -1, gm200_pmu_nofw, &gm20b_pmu }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c index b0407b86bc10..6d1a966be081 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c @@ -184,6 +184,7 @@ static void gt215_pmu_reset(struct nvkm_pmu *pmu) { struct nvkm_device *device = pmu->subdev.device; + nvkm_mask(device, 0x022210, 0x00000001, 0x00000000); nvkm_mask(device, 0x022210, 0x00000001, 0x00000001); nvkm_rd32(device, 0x022210); @@ -201,6 +202,23 @@ gt215_pmu_init(struct nvkm_pmu *pmu) struct nvkm_device *device = pmu->subdev.device; int i; + /* Inhibit interrupts, and wait for idle. */ + if (pmu->func->enabled(pmu)) { + nvkm_wr32(device, 0x10a014, 0x0000ffff); + nvkm_msec(device, 2000, + if (!nvkm_rd32(device, 0x10a04c)) + break; + ); + } + + pmu->func->reset(pmu); + + /* Wait for IMEM/DMEM scrubbing to be complete. */ + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006)) + break; + ); + /* upload data segment */ nvkm_wr32(device, 0x10a1c0, 0x01000000); for (i = 0; i < pmu->func->data.size / 4; i++) @@ -243,20 +261,6 @@ gt215_pmu_init(struct nvkm_pmu *pmu) const struct nvkm_falcon_func gt215_pmu_flcn = { - .debug = 0xc08, - .fbif = 0xe00, - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, - .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, - .cmdq = { 0x4a0, 0x4b0, 4 }, - .msgq = { 0x4c8, 0x4cc, 0 }, }; static const struct nvkm_pmu_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 21abf31f4442..1e7815b1a649 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -47,12 +47,11 @@ void gk110_pmu_pgob(struct nvkm_pmu *, bool); extern const struct nvkm_falcon_func gm200_pmu_flcn; +extern const struct nvkm_pmu_func gm20b_pmu; void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64); void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); int gm20b_pmu_acr_boot(struct nvkm_falcon *); int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id); -void gm20b_pmu_recv(struct nvkm_pmu *); -int gm20b_pmu_initmsg(struct nvkm_pmu *); struct nvkm_pmu_fwif { int version; -- cgit v1.2.3 From a9d90860c42a6a014b3a0596c76dff016fc2ce27 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:49 +1000 Subject: drm/nouveau/pmu/gm20b,gp10b: boot RTOS from PMU init Cleanup before falcon changes. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 8 +-- drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 4 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 80 +++++++++++++--------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 7 -- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 49 +++++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 1 - drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 1 - 9 files changed, 92 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index 176f0921d82f..780e25fdd119 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -16,7 +16,7 @@ enum nvkm_falcon_dmaidx { struct nvkm_falcon { const struct nvkm_falcon_func *func; - const struct nvkm_subdev *owner; + struct nvkm_subdev *owner; const char *name; u32 addr; @@ -24,7 +24,7 @@ struct nvkm_falcon { struct mutex dmem_mutex; bool oneinit; - const struct nvkm_subdev *user; + struct nvkm_subdev *user; u8 version; u8 secret; @@ -50,8 +50,8 @@ struct nvkm_falcon { struct nvkm_engine engine; }; -int nvkm_falcon_get(struct nvkm_falcon *, const struct nvkm_subdev *); -void nvkm_falcon_put(struct nvkm_falcon *, const struct nvkm_subdev *); +int nvkm_falcon_get(struct nvkm_falcon *, struct nvkm_subdev *); +void nvkm_falcon_put(struct nvkm_falcon *, struct nvkm_subdev *); int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *, enum nvkm_subdev_type, int inst, bool enable, u32 addr, struct nvkm_engine **); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index c0b254f7f0b5..3a269bb1d41b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -50,6 +50,7 @@ struct nvkm_acr { struct nvkm_vmm *vmm; bool done; + struct nvkm_acr_lsf *rtos; const struct firmware *wpr_fw; bool wpr_comp; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index f3f90c1063dd..5a5b96dad640 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -169,7 +169,7 @@ nvkm_falcon_oneinit(struct nvkm_falcon *falcon) } void -nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) +nvkm_falcon_put(struct nvkm_falcon *falcon, struct nvkm_subdev *user) { if (unlikely(!falcon)) return; @@ -183,7 +183,7 @@ nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) } int -nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) +nvkm_falcon_get(struct nvkm_falcon *falcon, struct nvkm_subdev *user) { int ret = 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index af6cac696d43..777b6cb33b47 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -63,10 +63,30 @@ nvkm_acr_hsf_boot(struct nvkm_acr *acr, const char *name) return 0; } +static struct nvkm_acr_lsf * +nvkm_acr_rtos(struct nvkm_acr *acr) +{ + struct nvkm_acr_lsf *lsf; + + if (acr) { + list_for_each_entry(lsf, &acr->lsf, head) { + if (lsf->func->bootstrap_falcon) + return lsf; + } + } + + return NULL; +} + static void nvkm_acr_unload(struct nvkm_acr *acr) { if (acr->done) { + if (acr->rtos) { + nvkm_subdev_unref(acr->rtos->falcon->owner); + acr->rtos = NULL; + } + nvkm_acr_hsf_boot(acr, "unload"); acr->done = false; } @@ -76,6 +96,7 @@ static int nvkm_acr_load(struct nvkm_acr *acr) { struct nvkm_subdev *subdev = &acr->subdev; + struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr); struct nvkm_acr_lsf *lsf; u64 start, limit; int ret; @@ -100,6 +121,14 @@ nvkm_acr_load(struct nvkm_acr *acr) acr->done = true; + if (rtos) { + ret = nvkm_subdev_ref(rtos->falcon->owner); + if (ret) + return ret; + + acr->rtos = rtos; + } + list_for_each_entry(lsf, &acr->lsf, head) { if (lsf->func->boot) { ret = lsf->func->boot(lsf->falcon); @@ -118,33 +147,17 @@ nvkm_acr_reload(struct nvkm_acr *acr) return nvkm_acr_load(acr); } -static struct nvkm_acr_lsf * -nvkm_acr_falcon(struct nvkm_device *device) -{ - struct nvkm_acr *acr = device->acr; - struct nvkm_acr_lsf *lsf; - - if (acr) { - list_for_each_entry(lsf, &acr->lsf, head) { - if (lsf->func->bootstrap_falcon) - return lsf; - } - } - - return NULL; -} - int nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask) { - struct nvkm_acr_lsf *acrflcn = nvkm_acr_falcon(device); struct nvkm_acr *acr = device->acr; + struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr); unsigned long id; /* If there's no LS FW managing bootstrapping of other LS falcons, * we depend on the HS firmware being able to do it instead. */ - if (!acrflcn) { + if (!rtos) { /* Which isn't possible everywhere... */ if ((mask & acr->func->bootstrap_falcons) == mask) { int ret = nvkm_acr_reload(acr); @@ -156,16 +169,14 @@ nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask) return -ENOSYS; } - if ((mask & acrflcn->func->bootstrap_falcons) != mask) + if ((mask & rtos->func->bootstrap_falcons) != mask) return -ENOSYS; - if (acrflcn->func->bootstrap_multiple_falcons) { - return acrflcn->func-> - bootstrap_multiple_falcons(acrflcn->falcon, mask); - } + if (rtos->func->bootstrap_multiple_falcons) + return rtos->func->bootstrap_multiple_falcons(rtos->falcon, mask); for_each_set_bit(id, &mask, NVKM_ACR_LSF_NUM) { - int ret = acrflcn->func->bootstrap_falcon(acrflcn->falcon, id); + int ret = rtos->func->bootstrap_falcon(rtos->falcon, id); if (ret) return ret; } @@ -189,6 +200,9 @@ nvkm_acr_managed_falcon(struct nvkm_device *device, enum nvkm_acr_lsf_id id) static int nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend) { + if (!subdev->use.enabled) + return 0; + nvkm_acr_unload(nvkm_acr(subdev)); return 0; } @@ -196,10 +210,12 @@ nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend) static int nvkm_acr_init(struct nvkm_subdev *subdev) { - if (!nvkm_acr_falcon(subdev->device)) + struct nvkm_acr *acr = nvkm_acr(subdev); + + if (!nvkm_acr_rtos(acr)) return 0; - return nvkm_acr_load(nvkm_acr(subdev)); + return nvkm_acr_load(acr); } static void @@ -218,7 +234,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) struct nvkm_acr *acr = nvkm_acr(subdev); struct nvkm_acr_hsfw *hsfw; struct nvkm_acr_lsfw *lsfw, *lsft; - struct nvkm_acr_lsf *lsf; + struct nvkm_acr_lsf *lsf, *rtos; u32 wpr_size = 0; u64 falcons; int ret, i; @@ -260,10 +276,10 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) } /* Ensure the falcon that'll provide ACR functions is booted first. */ - lsf = nvkm_acr_falcon(device); - if (lsf) { - falcons = lsf->func->bootstrap_falcons; - list_move(&lsf->head, &acr->lsf); + rtos = nvkm_acr_rtos(acr); + if (rtos) { + falcons = rtos->func->bootstrap_falcons; + list_move(&rtos->head, &acr->lsf); } else { falcons = acr->func->bootstrap_falcons; } @@ -301,7 +317,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) nvkm_wobj(acr->wpr, 0, acr->wpr_fw->data, acr->wpr_fw->size); if (!acr->wpr_fw || acr->wpr_comp) - acr->func->wpr_build(acr, nvkm_acr_falcon(device)); + acr->func->wpr_build(acr, rtos); acr->func->wpr_patch(acr, (s64)acr->wpr_start - acr->wpr_prev); if (acr->wpr_fw && acr->wpr_comp) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 51808a4e75ac..8f2f50ad4ded 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -87,13 +87,6 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) if (pmu->func->fini) pmu->func->fini(pmu); - flush_work(&pmu->recv.work); - - reinit_completion(&pmu->wpr_ready); - - nvkm_falcon_cmdq_fini(pmu->lpq); - nvkm_falcon_cmdq_fini(pmu->hpq); - pmu->initmsg_received = false; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 2b73848d4aed..a72403777329 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -62,16 +62,6 @@ gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon, return ret; } -int -gm20b_pmu_acr_boot(struct nvkm_falcon *falcon) -{ - struct nv_pmu_args args = { .secure_mode = true }; - const u32 addr_args = falcon->data.limit - sizeof(struct nv_pmu_args); - nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0); - nvkm_falcon_start(falcon); - return 0; -} - void gm20b_pmu_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) { @@ -125,7 +115,6 @@ gm20b_pmu_acr = { .bld_size = sizeof(struct loader_config), .bld_write = gm20b_pmu_acr_bld_write, .bld_patch = gm20b_pmu_acr_bld_patch, - .boot = gm20b_pmu_acr_boot, .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) | BIT_ULL(NVKM_ACR_LSF_FECS) | BIT_ULL(NVKM_ACR_LSF_GPCCS), @@ -198,8 +187,7 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu) if (!pmu->initmsg_received) { int ret = pmu->func->initmsg(pmu); if (ret) { - nvkm_error(&pmu->subdev, - "error parsing init message: %d\n", ret); + nvkm_error(&pmu->subdev, "error parsing init message: %d\n", ret); return; } @@ -209,9 +197,44 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu) nvkm_falcon_msgq_recv(pmu->msgq); } +static void +gm20b_pmu_fini(struct nvkm_pmu *pmu) +{ + /*TODO: shutdown RTOS. */ + + flush_work(&pmu->recv.work); + nvkm_falcon_cmdq_fini(pmu->lpq); + nvkm_falcon_cmdq_fini(pmu->hpq); + + reinit_completion(&pmu->wpr_ready); + + nvkm_falcon_put(&pmu->falcon, &pmu->subdev); +} + +static int +gm20b_pmu_init(struct nvkm_pmu *pmu) +{ + struct nvkm_falcon *falcon = &pmu->falcon; + struct nv_pmu_args args = { .secure_mode = true }; + u32 addr_args = falcon->data.limit - sizeof(args); + int ret; + + ret = nvkm_falcon_get(&pmu->falcon, &pmu->subdev); + if (ret) + return ret; + + pmu->initmsg_received = false; + + nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0); + nvkm_falcon_start(falcon); + return 0; +} + const struct nvkm_pmu_func gm20b_pmu = { .flcn = &gm200_pmu_flcn, + .init = gm20b_pmu_init, + .fini = gm20b_pmu_fini, .intr = gt215_pmu_intr, .recv = gm20b_pmu_recv, .initmsg = gm20b_pmu_initmsg, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index 9fba37ec05e0..a6f410ba60bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -68,7 +68,6 @@ gp10b_pmu_acr = { .bld_size = sizeof(struct loader_config), .bld_write = gm20b_pmu_acr_bld_write, .bld_patch = gm20b_pmu_acr_bld_patch, - .boot = gm20b_pmu_acr_boot, .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) | BIT_ULL(NVKM_ACR_LSF_FECS) | BIT_ULL(NVKM_ACR_LSF_GPCCS), diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c index 6d1a966be081..32cee21ed858 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c @@ -178,6 +178,7 @@ void gt215_pmu_fini(struct nvkm_pmu *pmu) { nvkm_wr32(pmu->subdev.device, 0x10a014, 0x00000060); + flush_work(&pmu->recv.work); } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 1e7815b1a649..75ede265a52c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -50,7 +50,6 @@ extern const struct nvkm_falcon_func gm200_pmu_flcn; extern const struct nvkm_pmu_func gm20b_pmu; void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64); void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); -int gm20b_pmu_acr_boot(struct nvkm_falcon *); int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id); struct nvkm_pmu_fwif { -- cgit v1.2.3 From 3b330f0875014b475ca3dc37e4397aee13f00986 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:49 +1000 Subject: drm/nouveau/sec2: unload RTOS before tearing down WPR Reset regs won't be available on Ampere while SEC2 RTOS is running, and we're apparently supposed to be doing this on earlier GPUs too. v2: - fixed some excessive indentation Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvfw/sec2.h | 5 ++ drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 4 +- drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 73 +++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 33 ++++++---- drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 5 +- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 8 +-- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 9 --- 11 files changed, 91 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h index 9a37ad4179cb..07d7094d8ed8 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h @@ -10,6 +10,7 @@ struct nv_sec2_args { }; #define NV_SEC2_UNIT_INIT 0x01 +#define NV_SEC2_UNIT_UNLOAD 0x06 #define NV_SEC2_UNIT_ACR 0x08 struct nv_sec2_init_msg { @@ -57,4 +58,8 @@ struct nv_sec2_acr_bootstrap_falcon_msg { u32 error_code; u32 falcon_id; }; + +#define NV_SEC2_UNIT_V2_INIT 0x01 +#define NV_SEC2_UNIT_V2_UNLOAD 0x05 +#define NV_SEC2_UNIT_V2_ACR 0x07 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index d647d8acb15b..2db6b5d2ebc6 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -72,6 +72,7 @@ int nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *, const char *name, void nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **); void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *, u32 index, u32 offset, u32 size); +bool nvkm_falcon_msgq_empty(struct nvkm_falcon_msgq *); int nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *, void *, u32 size); void nvkm_falcon_msgq_recv(struct nvkm_falcon_msgq *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index 06264c840eae..a41b86426f80 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -10,12 +10,14 @@ struct nvkm_sec2 { struct nvkm_engine engine; struct nvkm_falcon falcon; + atomic_t running; + atomic_t initmsg; + struct nvkm_falcon_qmgr *qmgr; struct nvkm_falcon_cmdq *cmdq; struct nvkm_falcon_msgq *msgq; struct work_struct work; - bool initmsg_received; }; int gp102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 3a269bb1d41b..fe5024b6d0f3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -109,7 +109,6 @@ struct nvkm_acr_lsf_func { u32 bld_size; void (*bld_write)(struct nvkm_acr *, u32 bld, struct nvkm_acr_lsfw *); void (*bld_patch)(struct nvkm_acr *, u32 bld, s64 adjust); - int (*boot)(struct nvkm_falcon *); u64 bootstrap_falcons; int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id); int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index 092c6d0b8e01..428bbda30a6f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -22,25 +22,17 @@ #include "priv.h" #include -#include +#include -static void -nvkm_sec2_recv(struct work_struct *work) -{ - struct nvkm_sec2 *sec2 = container_of(work, typeof(*sec2), work); - - if (!sec2->initmsg_received) { - int ret = sec2->func->initmsg(sec2); - if (ret) { - nvkm_error(&sec2->engine.subdev, - "error parsing init message: %d\n", ret); - return; - } +#include - sec2->initmsg_received = true; - } +static int +nvkm_sec2_finimsg(void *priv, struct nvfw_falcon_msg *hdr) +{ + struct nvkm_sec2 *sec2 = priv; - nvkm_falcon_msgq_recv(sec2->msgq); + atomic_set(&sec2->running, 0); + return 0; } static void @@ -54,14 +46,52 @@ static int nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_falcon *falcon = &sec2->falcon; + struct nvkm_falcon_cmdq *cmdq = sec2->cmdq; + struct nvfw_falcon_cmd cmd = { + .unit_id = sec2->func->unit_unload, + .size = sizeof(cmd), + }; + int ret; + + if (!subdev->use.enabled) + return 0; - flush_work(&sec2->work); + if (atomic_read(&sec2->initmsg) == 1) { + ret = nvkm_falcon_cmdq_send(cmdq, &cmd, nvkm_sec2_finimsg, sec2, + msecs_to_jiffies(1000)); + WARN_ON(ret); - if (suspend) { - nvkm_falcon_cmdq_fini(sec2->cmdq); - sec2->initmsg_received = false; + nvkm_msec(subdev->device, 2000, + if (nvkm_falcon_rd32(falcon, 0x100) & 0x00000010) + break; + ); } + nvkm_falcon_cmdq_fini(cmdq); + falcon->func->disable(falcon); + nvkm_falcon_put(falcon, subdev); + return 0; +} + +static int +nvkm_sec2_init(struct nvkm_engine *engine) +{ + struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_falcon *falcon = &sec2->falcon; + int ret; + + ret = nvkm_falcon_get(falcon, subdev); + if (ret) + return ret; + + nvkm_falcon_wr32(falcon, 0x014, 0xffffffff); + atomic_set(&sec2->initmsg, 0); + atomic_set(&sec2->running, 1); + + nvkm_falcon_start(falcon); return 0; } @@ -69,6 +99,7 @@ static void * nvkm_sec2_dtor(struct nvkm_engine *engine) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + nvkm_falcon_msgq_del(&sec2->msgq); nvkm_falcon_cmdq_del(&sec2->cmdq); nvkm_falcon_qmgr_del(&sec2->qmgr); @@ -79,6 +110,7 @@ nvkm_sec2_dtor(struct nvkm_engine *engine) static const struct nvkm_engine_func nvkm_sec2 = { .dtor = nvkm_sec2_dtor, + .init = nvkm_sec2_init, .fini = nvkm_sec2_fini, .intr = nvkm_sec2_intr, }; @@ -113,6 +145,5 @@ nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, (ret = nvkm_falcon_msgq_new(sec2->qmgr, "msgq", &sec2->msgq))) return ret; - INIT_WORK(&sec2->work, nvkm_sec2_recv); return 0; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 44e39f5743d5..fb6d5417b290 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -74,16 +74,6 @@ gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, msecs_to_jiffies(1000)); } -static int -gp102_sec2_acr_boot(struct nvkm_falcon *falcon) -{ - struct nv_sec2_args args = {}; - nvkm_falcon_load_dmem(falcon, &args, - falcon->func->emem_addr, sizeof(args), 0); - nvkm_falcon_start(falcon); - return 0; -} - static void gp102_sec2_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) { @@ -122,7 +112,6 @@ gp102_sec2_acr_0 = { .bld_size = sizeof(struct loader_config_v1), .bld_write = gp102_sec2_acr_bld_write, .bld_patch = gp102_sec2_acr_bld_patch, - .boot = gp102_sec2_acr_boot, .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | BIT_ULL(NVKM_ACR_LSF_GPCCS) | BIT_ULL(NVKM_ACR_LSF_SEC2), @@ -169,11 +158,29 @@ gp102_sec2_intr(struct nvkm_sec2 *sec2) u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16); if (intr & 0x00000040) { - schedule_work(&sec2->work); + if (unlikely(atomic_read(&sec2->initmsg) == 0)) { + int ret = sec2->func->initmsg(sec2); + + if (ret) + nvkm_error(subdev, "error parsing init message: %d\n", ret); + + atomic_set(&sec2->initmsg, ret ?: 1); + } + + if (atomic_read(&sec2->initmsg) > 0) { + if (!nvkm_falcon_msgq_empty(sec2->msgq)) + nvkm_falcon_msgq_recv(sec2->msgq); + } + nvkm_falcon_wr32(falcon, 0x004, 0x00000040); intr &= ~0x00000040; } + if (intr & 0x00000010) { + nvkm_falcon_wr32(falcon, 0x004, 0x00000010); + intr &= ~0x00000010; + } + if (intr) { nvkm_error(subdev, "unhandled intr %08x\n", intr); nvkm_falcon_wr32(falcon, 0x004, intr); @@ -250,6 +257,7 @@ gp102_sec2_flcn = { const struct nvkm_sec2_func gp102_sec2 = { .flcn = &gp102_sec2_flcn, + .unit_unload = NV_SEC2_UNIT_UNLOAD, .unit_acr = NV_SEC2_UNIT_ACR, .intr = gp102_sec2_intr, .initmsg = gp102_sec2_initmsg, @@ -304,7 +312,6 @@ gp102_sec2_acr_1 = { .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), .bld_write = gp102_sec2_acr_bld_write_1, .bld_patch = gp102_sec2_acr_bld_patch_1, - .boot = gp102_sec2_acr_boot, .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | BIT_ULL(NVKM_ACR_LSF_GPCCS) | BIT_ULL(NVKM_ACR_LSF_SEC2), diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index af19229e885d..814a5f11def0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -5,6 +5,7 @@ struct nvkm_sec2_func { const struct nvkm_falcon_func *flcn; + u8 unit_unload; u8 unit_acr; void (*intr)(struct nvkm_sec2 *); int (*initmsg)(struct nvkm_sec2 *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index f3faeb705575..39e42be03974 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -22,6 +22,8 @@ #include "priv.h" #include +#include + static const struct nvkm_falcon_func tu102_sec2_flcn = { .debug = 0x408, @@ -44,7 +46,8 @@ tu102_sec2_flcn = { static const struct nvkm_sec2_func tu102_sec2 = { .flcn = &tu102_sec2_flcn, - .unit_acr = 0x07, + .unit_unload = NV_SEC2_UNIT_V2_UNLOAD, + .unit_acr = NV_SEC2_UNIT_V2_ACR, .intr = gp102_sec2_intr, .initmsg = gp102_sec2_initmsg, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index e74371dffc76..04f853151648 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -25,7 +25,7 @@ static void nvkm_falcon_msgq_open(struct nvkm_falcon_msgq *msgq) { - mutex_lock(&msgq->mutex); + spin_lock(&msgq->lock); msgq->position = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->tail_reg); } @@ -37,10 +37,10 @@ nvkm_falcon_msgq_close(struct nvkm_falcon_msgq *msgq, bool commit) if (commit) nvkm_falcon_wr32(falcon, msgq->tail_reg, msgq->position); - mutex_unlock(&msgq->mutex); + spin_unlock(&msgq->lock); } -static bool +bool nvkm_falcon_msgq_empty(struct nvkm_falcon_msgq *msgq) { u32 head = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->head_reg); @@ -208,6 +208,6 @@ nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *qmgr, const char *name, msgq->qmgr = qmgr; msgq->name = name; - mutex_init(&msgq->mutex); + spin_lock_init(&msgq->lock); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index 33564ac906a8..79f0da9e749f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -73,7 +73,7 @@ struct nvkm_falcon_cmdq { struct nvkm_falcon_msgq { struct nvkm_falcon_qmgr *qmgr; const char *name; - struct mutex mutex; + spinlock_t lock; u32 head_reg; u32 tail_reg; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index 777b6cb33b47..882d8d30bd64 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -97,7 +97,6 @@ nvkm_acr_load(struct nvkm_acr *acr) { struct nvkm_subdev *subdev = &acr->subdev; struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr); - struct nvkm_acr_lsf *lsf; u64 start, limit; int ret; @@ -129,14 +128,6 @@ nvkm_acr_load(struct nvkm_acr *acr) acr->rtos = rtos; } - list_for_each_entry(lsf, &acr->lsf, head) { - if (lsf->func->boot) { - ret = lsf->func->boot(lsf->falcon); - if (ret) - break; - } - } - return ret; } -- cgit v1.2.3 From c7c0aac7421331baffdeb8f9c3e9702bdb1c0389 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:50 +1000 Subject: drm/nouveau/sec2: switch to newer style interrupt handler Ampere. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 25 ++++++++++++++++-------- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 7 +++++-- drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c | 3 ++- 4 files changed, 26 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index 428bbda30a6f..b1e5f543c99d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -22,6 +22,7 @@ #include "priv.h" #include +#include #include #include @@ -35,13 +36,6 @@ nvkm_sec2_finimsg(void *priv, struct nvfw_falcon_msg *hdr) return 0; } -static void -nvkm_sec2_intr(struct nvkm_engine *engine) -{ - struct nvkm_sec2 *sec2 = nvkm_sec2(engine); - sec2->func->intr(sec2); -} - static int nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) { @@ -69,6 +63,8 @@ nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) ); } + nvkm_inth_block(&subdev->inth); + nvkm_falcon_cmdq_fini(cmdq); falcon->func->disable(falcon); nvkm_falcon_put(falcon, subdev); @@ -90,11 +86,24 @@ nvkm_sec2_init(struct nvkm_engine *engine) nvkm_falcon_wr32(falcon, 0x014, 0xffffffff); atomic_set(&sec2->initmsg, 0); atomic_set(&sec2->running, 1); + nvkm_inth_allow(&subdev->inth); nvkm_falcon_start(falcon); return 0; } +static int +nvkm_sec2_oneinit(struct nvkm_engine *engine) +{ + struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_intr *intr = &sec2->engine.subdev.device->mc->intr; + enum nvkm_intr_type type = NVKM_INTR_SUBDEV; + + return nvkm_inth_add(intr, type, NVKM_INTR_PRIO_NORMAL, subdev, sec2->func->intr, + &subdev->inth); +} + static void * nvkm_sec2_dtor(struct nvkm_engine *engine) { @@ -110,9 +119,9 @@ nvkm_sec2_dtor(struct nvkm_engine *engine) static const struct nvkm_engine_func nvkm_sec2 = { .dtor = nvkm_sec2_dtor, + .oneinit = nvkm_sec2_oneinit, .init = nvkm_sec2_init, .fini = nvkm_sec2_fini, - .intr = nvkm_sec2_intr, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index fb6d5417b290..639ab9dfa452 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -149,9 +149,10 @@ gp102_sec2_initmsg(struct nvkm_sec2 *sec2) return 0; } -void -gp102_sec2_intr(struct nvkm_sec2 *sec2) +irqreturn_t +gp102_sec2_intr(struct nvkm_inth *inth) { + struct nvkm_sec2 *sec2 = container_of(inth, typeof(*sec2), engine.subdev.inth); struct nvkm_subdev *subdev = &sec2->engine.subdev; struct nvkm_falcon *falcon = &sec2->falcon; u32 disp = nvkm_falcon_rd32(falcon, 0x01c); @@ -185,6 +186,8 @@ gp102_sec2_intr(struct nvkm_sec2 *sec2) nvkm_error(subdev, "unhandled intr %08x\n", intr); nvkm_falcon_wr32(falcon, 0x004, intr); } + + return IRQ_HANDLED; } int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index 814a5f11def0..4997b8903a78 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -7,11 +7,11 @@ struct nvkm_sec2_func { const struct nvkm_falcon_func *flcn; u8 unit_unload; u8 unit_acr; - void (*intr)(struct nvkm_sec2 *); + irqreturn_t (*intr)(struct nvkm_inth *); int (*initmsg)(struct nvkm_sec2 *); }; -void gp102_sec2_intr(struct nvkm_sec2 *); +irqreturn_t gp102_sec2_intr(struct nvkm_inth *); int gp102_sec2_initmsg(struct nvkm_sec2 *); struct nvkm_sec2_fwif { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c index 7606bed2ff6f..3a99a450b6b0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c @@ -37,7 +37,8 @@ gp100_mc_intrs[] = { { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true }, - { NVKM_SUBDEV_TOP , 0, 0, 0xffffffff, true }, + { NVKM_SUBDEV_TOP , 0, 0, 0x00008000 }, + { NVKM_SUBDEV_TOP , 0, 0, 0xffff7fff, true }, {}, }; -- cgit v1.2.3 From f15cde64b66161bfa74fb58f4e5697d8265b802e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:51 +1000 Subject: drm/nouveau/flcn: rework falcon reset Mostly preparation to fit in Ampere changes, but should result in reset sequences a lot closer to RM's, and perhaps help out with the issues we sometimes see reported in this area. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 10 ++- .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 12 ++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 8 --- drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c | 6 +- drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c | 11 --- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 16 ++--- drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 7 +- drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild | 3 + drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 37 ++-------- drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 83 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c | 32 +++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/priv.h | 8 +++ drivers/gpu/drm/nouveau/nvkm/falcon/v1.c | 43 ----------- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c | 6 +- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c | 17 ++--- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c | 29 +++++--- 16 files changed, 185 insertions(+), 143 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 2db6b5d2ebc6..625ffe31eaaf 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -5,6 +5,13 @@ int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner, const char *name, u32 addr, struct nvkm_falcon *); void nvkm_falcon_dtor(struct nvkm_falcon *); +int nvkm_falcon_reset(struct nvkm_falcon *); + +int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *); +int gm200_flcn_disable(struct nvkm_falcon *); +int gm200_flcn_enable(struct nvkm_falcon *); + +int gp102_flcn_reset_eng(struct nvkm_falcon *); void nvkm_falcon_v1_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); @@ -15,11 +22,8 @@ int nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *, u32); int nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *, u32); void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *, u32 start_addr); void nvkm_falcon_v1_start(struct nvkm_falcon *); -int nvkm_falcon_v1_enable(struct nvkm_falcon *); -void nvkm_falcon_v1_disable(struct nvkm_falcon *); void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *); -int gp102_sec2_flcn_enable(struct nvkm_falcon *); #define FLCN_PRINTK(f,l,p,fmt,a...) ({ \ if ((f)->owner->name != (f)->name) \ diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index 780e25fdd119..45c73893f100 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -57,6 +57,12 @@ int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *, enum nvkm_subdev_type, int inst, bool enable, u32 addr, struct nvkm_engine **); struct nvkm_falcon_func { + int (*disable)(struct nvkm_falcon *); + int (*enable)(struct nvkm_falcon *); + bool reset_pmc; + int (*reset_eng)(struct nvkm_falcon *); + int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *); + struct { u32 *data; u32 size; @@ -80,9 +86,6 @@ struct nvkm_falcon_func { int (*clear_interrupt)(struct nvkm_falcon *, u32); void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr); void (*start)(struct nvkm_falcon *); - int (*enable)(struct nvkm_falcon *falcon); - void (*disable)(struct nvkm_falcon *falcon); - int (*reset)(struct nvkm_falcon *); struct { u32 head; @@ -122,7 +125,4 @@ void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32); void nvkm_falcon_start(struct nvkm_falcon *); int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32); int nvkm_falcon_clear_interrupt(struct nvkm_falcon *, u32); -int nvkm_falcon_enable(struct nvkm_falcon *); -void nvkm_falcon_disable(struct nvkm_falcon *); -int nvkm_falcon_reset(struct nvkm_falcon *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 68da77df856a..ee14115d669c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2073,17 +2073,9 @@ gf100_gr_ = { static const struct nvkm_falcon_func gf100_gr_flcn = { - .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c index 8c44ce44a6d7..d9425e9195ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c @@ -23,6 +23,10 @@ static const struct nvkm_falcon_func gm107_nvdec_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .reset_pmc = true, + .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0xd00, .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, @@ -33,8 +37,6 @@ gm107_nvdec_flcn = { .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, }; static const struct nvkm_nvdec_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c index f44d41bf2034..ad27d8b97569 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c @@ -24,17 +24,6 @@ static const struct nvkm_falcon_func gm107_nvenc_flcn = { - .fbif = 0x800, - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, - .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, }; static const struct nvkm_nvenc_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 639ab9dfa452..ae910c9bdc0a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -190,15 +190,6 @@ gp102_sec2_intr(struct nvkm_inth *inth) return IRQ_HANDLED; } -int -gp102_sec2_flcn_enable(struct nvkm_falcon *falcon) -{ - nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001); - udelay(10); - nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000); - return nvkm_falcon_v1_enable(falcon); -} - void gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) @@ -240,6 +231,11 @@ gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon, static const struct nvkm_falcon_func gp102_sec2_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .reset_pmc = true, + .reset_eng = gp102_flcn_reset_eng, + .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0x408, .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, @@ -251,8 +247,6 @@ gp102_sec2_flcn = { .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, .start = nvkm_falcon_v1_start, - .enable = gp102_sec2_flcn_enable, - .disable = nvkm_falcon_v1_disable, .cmdq = { 0xa00, 0xa04, 8 }, .msgq = { 0xa30, 0xa34, 8 }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index 39e42be03974..0f859f323504 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -26,6 +26,11 @@ static const struct nvkm_falcon_func tu102_sec2_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .reset_pmc = true, + .reset_eng = gp102_flcn_reset_eng, + .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0x408, .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, @@ -37,8 +42,6 @@ tu102_sec2_flcn = { .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, .cmdq = { 0xc00, 0xc04, 8 }, .msgq = { 0xc80, 0xc84, 8 }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild index d79d783904ee..f2ffca4afbe3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild @@ -4,3 +4,6 @@ nvkm-y += nvkm/falcon/cmdq.o nvkm-y += nvkm/falcon/msgq.o nvkm-y += nvkm/falcon/qmgr.o nvkm-y += nvkm/falcon/v1.o + +nvkm-y += nvkm/falcon/gm200.o +nvkm-y += nvkm/falcon/gp102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index 5a5b96dad640..ed88cfb17f12 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -85,44 +85,15 @@ nvkm_falcon_start(struct nvkm_falcon *falcon) } int -nvkm_falcon_enable(struct nvkm_falcon *falcon) +nvkm_falcon_reset(struct nvkm_falcon *falcon) { - struct nvkm_device *device = falcon->owner->device; int ret; - nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst); - ret = falcon->func->enable(falcon); - if (ret) { - nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst); + ret = falcon->func->disable(falcon); + if (WARN_ON(ret)) return ret; - } - - return 0; -} - -void -nvkm_falcon_disable(struct nvkm_falcon *falcon) -{ - struct nvkm_device *device = falcon->owner->device; - - /* already disabled, return or wait_idle will timeout */ - if (!nvkm_mc_enabled(device, falcon->owner->type, falcon->owner->inst)) - return; - - falcon->func->disable(falcon); - - nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst); -} - -int -nvkm_falcon_reset(struct nvkm_falcon *falcon) -{ - if (!falcon->func->reset) { - nvkm_falcon_disable(falcon); - return nvkm_falcon_enable(falcon); - } - return falcon->func->reset(falcon); + return nvkm_falcon_enable(falcon); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c new file mode 100644 index 000000000000..9144bcbc7f45 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c @@ -0,0 +1,83 @@ +/* + * Copyright 2022 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +#include +#include + +int +gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon) +{ + nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000); + + if (nvkm_msec(falcon->owner->device, 10, + if (!(nvkm_falcon_rd32(falcon, 0x10c) & 0x00000006)) + break; + ) < 0) + return -ETIMEDOUT; + + return 0; +} + +int +gm200_flcn_enable(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->owner->device; + int ret; + + if (falcon->func->reset_eng) { + ret = falcon->func->reset_eng(falcon); + if (ret) + return ret; + } + + if (falcon->func->reset_pmc) + nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst); + + ret = falcon->func->reset_wait_mem_scrubbing(falcon); + if (ret) + return ret; + + nvkm_falcon_wr32(falcon, 0x084, nvkm_rd32(device, 0x000000)); + return 0; +} + +int +gm200_flcn_disable(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->owner->device; + int ret; + + nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000); + nvkm_falcon_wr32(falcon, 0x014, 0xffffffff); + + if (falcon->func->reset_pmc) + nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst); + + if (falcon->func->reset_eng) { + ret = falcon->func->reset_eng(falcon); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c new file mode 100644 index 000000000000..f49918530d0b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c @@ -0,0 +1,32 @@ +/* + * Copyright 2022 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +int +gp102_flcn_reset_eng(struct nvkm_falcon *falcon) +{ + nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001); + udelay(10); + nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000); + + return falcon->func->reset_wait_mem_scrubbing(falcon); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h b/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h index 466188752eb0..11a24b9c8569 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h @@ -2,4 +2,12 @@ #ifndef __NVKM_FALCON_PRIV_H__ #define __NVKM_FALCON_PRIV_H__ #include + +static inline int +nvkm_falcon_enable(struct nvkm_falcon *falcon) +{ + if (falcon->func->enable) + return falcon->func->enable(falcon); + return 0; +} #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index b0ee4c31414c..9a9e1e6f70a6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -266,46 +266,3 @@ nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *falcon, u32 mask) return 0; } - -static int -falcon_v1_wait_idle(struct nvkm_falcon *falcon) -{ - struct nvkm_device *device = falcon->owner->device; - int ret; - - ret = nvkm_wait_msec(device, 10, falcon->addr + 0x04c, 0xffff, 0x0); - if (ret < 0) - return ret; - - return 0; -} - -int -nvkm_falcon_v1_enable(struct nvkm_falcon *falcon) -{ - struct nvkm_device *device = falcon->owner->device; - int ret; - - ret = nvkm_wait_msec(device, 10, falcon->addr + 0x10c, 0x6, 0x0); - if (ret < 0) { - nvkm_error(falcon->user, "Falcon mem scrubbing timeout\n"); - return ret; - } - - ret = falcon_v1_wait_idle(falcon); - if (ret) - return ret; - - /* enable IRQs */ - nvkm_falcon_wr32(falcon, 0x010, 0xff); - - return 0; -} - -void -nvkm_falcon_v1_disable(struct nvkm_falcon *falcon) -{ - /* disable IRQs and wait for any previous code to complete */ - nvkm_falcon_wr32(falcon, 0x014, 0xff); - falcon_v1_wait_idle(falcon); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c index bc1138799ce5..a247e57f7d9f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c @@ -23,6 +23,10 @@ static const struct nvkm_falcon_func gv100_gsp_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .reset_eng = gp102_flcn_reset_eng, + .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, @@ -32,8 +36,6 @@ gv100_gsp_flcn = { .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, .start = nvkm_falcon_v1_start, - .enable = gp102_sec2_flcn_enable, - .disable = nvkm_falcon_v1_disable, }; static const struct nvkm_gsp_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c index 34e8320421f5..0bd854092da9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c @@ -23,18 +23,12 @@ */ #include "priv.h" -static int -gm200_pmu_flcn_reset(struct nvkm_falcon *falcon) -{ - struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon); - - nvkm_falcon_wr32(falcon, 0x014, 0x0000ffff); - pmu->func->reset(pmu); - return nvkm_falcon_enable(falcon); -} - const struct nvkm_falcon_func gm200_pmu_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .reset_pmc = true, + .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0xc08, .fbif = 0xe00, .load_imem = nvkm_falcon_v1_load_imem, @@ -45,9 +39,6 @@ gm200_pmu_flcn = { .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, - .reset = gm200_pmu_flcn_reset, .cmdq = { 0x4a0, 0x4b0, 4 }, .msgq = { 0x4c8, 0x4cc, 0 }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c index 9fd1116ebe27..47c7412f86e8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c @@ -23,18 +23,29 @@ */ #include "priv.h" -void -gp102_pmu_reset(struct nvkm_pmu *pmu) -{ - struct nvkm_device *device = pmu->subdev.device; - nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000001); - nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000000); -} +static const struct nvkm_falcon_func +gp102_pmu_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .reset_eng = gp102_flcn_reset_eng, + .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, + .debug = 0xc08, + .fbif = 0xe00, + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .cmdq = { 0x4a0, 0x4b0, 4 }, + .msgq = { 0x4c8, 0x4cc, 0 }, +}; static const struct nvkm_pmu_func gp102_pmu = { - .flcn = &gm200_pmu_flcn, - .reset = gp102_pmu_reset, + .flcn = &gp102_pmu_flcn, }; static const struct nvkm_pmu_fwif -- cgit v1.2.3 From 0e44c21708761977dcbea9b846b51a6fb684907a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:51 +1000 Subject: drm/nouveau/flcn: new code to load+boot simple HS FWs (VPR scrubber) Adds the start of common interfaces to load and boot the HS binaries provided by NVIDIA that enable the usage of GR. ACR already handles most of this, but it's very much tied into ACR's init process, and there's other code that could benefit from reusing a lot of this stuff too (ie. VBIOS DEVINIT/PreOS, VPR scrubber). The VPR scrubber code is fairly independent, and a good first target. - adds better debug output to fw loading process, to ease bring-up/debug v2: - whitespace, 0->false Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 94 +++++++++ .../gpu/drm/nouveau/include/nvkm/core/firmware.h | 17 ++ .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 5 +- drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 42 ++++ drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c | 11 +- drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 54 +++++ drivers/gpu/drm/nouveau/nvkm/falcon/fw.c | 229 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 144 +++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | 63 +----- 10 files changed, 594 insertions(+), 66 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/fw.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 625ffe31eaaf..d8fd2cbd2872 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -1,15 +1,44 @@ #ifndef __NVKM_FALCON_H__ #define __NVKM_FALCON_H__ +#include #include +enum nvkm_falcon_mem { + IMEM, + DMEM, +}; + +static inline const char * +nvkm_falcon_mem(enum nvkm_falcon_mem mem) +{ + switch (mem) { + case IMEM: return "imem"; + case DMEM: return "dmem"; + default: + WARN_ON(1); + return "?mem"; + } +} + +struct nvkm_falcon_func_pio { + int min; + int max; + void (*wr_init)(struct nvkm_falcon *, u8 port, bool sec, u32 mem_base); + void (*wr)(struct nvkm_falcon *, u8 port, const u8 *img, int len, u16 tag); +}; + int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner, const char *name, u32 addr, struct nvkm_falcon *); void nvkm_falcon_dtor(struct nvkm_falcon *); int nvkm_falcon_reset(struct nvkm_falcon *); +int nvkm_falcon_pio_wr(struct nvkm_falcon *, const u8 *img, u32 img_base, u8 port, + enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec); int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *); int gm200_flcn_disable(struct nvkm_falcon *); int gm200_flcn_enable(struct nvkm_falcon *); +extern const struct nvkm_falcon_func_pio gm200_flcn_imem_pio; +extern const struct nvkm_falcon_func_pio gm200_flcn_dmem_pio; int gp102_flcn_reset_eng(struct nvkm_falcon *); @@ -33,6 +62,71 @@ void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *); }) #define FLCN_DBG(f,fmt,a...) FLCN_PRINTK((f), DEBUG, info, " "fmt"\n", ##a) #define FLCN_ERR(f,fmt,a...) FLCN_PRINTK((f), ERROR, err, " "fmt"\n", ##a) +#define FLCN_ERRON(f,c,fmt,a...) \ + ({ bool _cond = (c); _cond ? FLCN_ERR(f, fmt, ##a) : FLCN_DBG(f, fmt, ##a); _cond; }) + + +struct nvkm_falcon_fw { + const struct nvkm_falcon_fw_func { + int (*signature)(struct nvkm_falcon_fw *, u32 *sig_base_src); + int (*reset)(struct nvkm_falcon_fw *); + int (*load)(struct nvkm_falcon_fw *); + int (*boot)(struct nvkm_falcon_fw *, + u32 *mbox0, u32 *mbox1, u32 mbox0_ok, u32 irqsclr); + } *func; + struct nvkm_firmware fw; + + u32 sig_base_prd; + u32 sig_base_dbg; + u32 sig_base_img; + u32 sig_size; + int sig_nr; + u8 *sigs; + + u32 nmem_base_img; + u32 nmem_base; + u32 nmem_size; + + u32 imem_base_img; + u32 imem_base; + u32 imem_size; + + u32 dmem_base_img; + u32 dmem_base; + u32 dmem_size; + u32 dmem_sign; + + u32 boot_addr; + + struct nvkm_falcon *falcon; + struct nvkm_memory *inst; + struct nvkm_vmm *vmm; +}; + +int nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *, const char *name, struct nvkm_device *, + bool bl, const void *src, u32 len, struct nvkm_falcon *, + struct nvkm_falcon_fw *); +int nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *, const char *name, + struct nvkm_subdev *, const char *bl, const char *img, int ver, + struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw); +int nvkm_falcon_fw_sign(struct nvkm_falcon_fw *, u32 sig_base_img, u32 sig_size, const u8 *sigs, + int sig_nr_prd, u32 sig_base_prd, int sig_nr_dbg, u32 sig_base_dbg); +int nvkm_falcon_fw_patch(struct nvkm_falcon_fw *); +void nvkm_falcon_fw_dtor(struct nvkm_falcon_fw *); +int nvkm_falcon_fw_oneinit(struct nvkm_falcon_fw *, struct nvkm_falcon *, struct nvkm_vmm *, + struct nvkm_memory *inst); +int nvkm_falcon_fw_boot(struct nvkm_falcon_fw *, struct nvkm_subdev *user, + bool release, u32 *pmbox0, u32 *pmbox1, u32 mbox0_ok, u32 irqsclr); + +extern const struct nvkm_falcon_fw_func gm200_flcn_fw; +int gm200_flcn_fw_signature(struct nvkm_falcon_fw *, u32 *); +int gm200_flcn_fw_reset(struct nvkm_falcon_fw *); +int gm200_flcn_fw_load(struct nvkm_falcon_fw *); +int gm200_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32); + +#define FLCNFW_PRINTK(f,l,p,fmt,a...) FLCN_PRINTK((f)->falcon, l, p, "%s: "fmt, (f)->fw.name, ##a) +#define FLCNFW_DBG(f,fmt,a...) FLCNFW_PRINTK((f), DEBUG, info, fmt"\n", ##a) +#define FLCNFW_ERR(f,fmt,a...) FLCNFW_PRINTK((f), ERROR, err, fmt"\n", ##a) /** * struct nvfw_falcon_msg - header for all messages diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h index 85bcb80f6873..8453025891a5 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h @@ -4,6 +4,23 @@ #include #include +struct nvkm_firmware { + const struct nvkm_firmware_func { + enum nvkm_firmware_type { + NVKM_FIRMWARE_IMG_RAM, + } type; + } *func; + const char *name; + struct nvkm_device *device; + + int len; + u8 *img; +}; + +int nvkm_firmware_ctor(const struct nvkm_firmware_func *, const char *name, struct nvkm_device *, + const void *ptr, int len, struct nvkm_firmware *); +void nvkm_firmware_dtor(struct nvkm_firmware *); + int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname, int ver, const struct firmware **); void nvkm_firmware_put(const struct firmware *); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index 45c73893f100..ca751199379e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -63,6 +63,10 @@ struct nvkm_falcon_func { int (*reset_eng)(struct nvkm_falcon *); int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *); + u32 debug; + const struct nvkm_falcon_func_pio *imem_pio; + const struct nvkm_falcon_func_pio *dmem_pio; + struct { u32 *data; u32 size; @@ -74,7 +78,6 @@ struct nvkm_falcon_func { void (*init)(struct nvkm_falcon *); void (*intr)(struct nvkm_falcon *, struct nvkm_chan *); - u32 debug; u32 fbif; void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c index ca1f8463cff5..aa1bf6b5a8cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c @@ -107,3 +107,45 @@ nvkm_firmware_put(const struct firmware *fw) { release_firmware(fw); } + +void +nvkm_firmware_dtor(struct nvkm_firmware *fw) +{ + if (!fw->img) + return; + + switch (fw->func->type) { + case NVKM_FIRMWARE_IMG_RAM: + kfree(fw->img); + break; + default: + WARN_ON(1); + break; + } + + fw->img = NULL; +} + +int +nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name, + struct nvkm_device *device, const void *src, int len, struct nvkm_firmware *fw) +{ + fw->func = func; + fw->name = name; + fw->device = device; + + switch (fw->func->type) { + case NVKM_FIRMWARE_IMG_RAM: + fw->len = len; + fw->img = kmemdup(src, fw->len, GFP_KERNEL); + break; + default: + WARN_ON(1); + return -EINVAL; + } + + if (!fw->img) + return -ENOMEM; + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c index d9425e9195ce..5d04ded35cc3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c @@ -28,15 +28,8 @@ gm107_nvdec_flcn = { .reset_pmc = true, .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0xd00, - .fbif = 0x600, - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, - .start = nvkm_falcon_v1_start, + .imem_pio = &gm200_flcn_imem_pio, + .dmem_pio = &gm200_flcn_dmem_pio, }; static const struct nvkm_nvdec_func diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild index f2ffca4afbe3..6ffde5290b87 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild @@ -1,6 +1,7 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/falcon/base.o nvkm-y += nvkm/falcon/cmdq.o +nvkm-y += nvkm/falcon/fw.o nvkm-y += nvkm/falcon/msgq.o nvkm-y += nvkm/falcon/qmgr.o nvkm-y += nvkm/falcon/v1.o diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index ed88cfb17f12..c15dda020c77 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -24,6 +24,60 @@ #include #include +static const struct nvkm_falcon_func_pio * +nvkm_falcon_pio(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base) +{ + switch (*mem_type) { + case IMEM: + return falcon->func->imem_pio; + case DMEM: + if (!falcon->func->emem_addr || *mem_base < falcon->func->emem_addr) + return falcon->func->dmem_pio; + + *mem_base -= falcon->func->emem_addr; + fallthrough; + default: + return NULL; + } +} + +int +nvkm_falcon_pio_wr(struct nvkm_falcon *falcon, const u8 *img, u32 img_base, u8 port, + enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec) +{ + const struct nvkm_falcon_func_pio *pio = nvkm_falcon_pio(falcon, &mem_type, &mem_base); + const char *type = nvkm_falcon_mem(mem_type); + int xfer_len; + + if (WARN_ON(!pio || !pio->wr)) + return -EINVAL; + + FLCN_DBG(falcon, "%s %08x <- %08x bytes at %08x", type, mem_base, len, img_base); + if (WARN_ON(!len || (len & (pio->min - 1)))) + return -EINVAL; + + pio->wr_init(falcon, port, sec, mem_base); + do { + xfer_len = min(len, pio->max); + pio->wr(falcon, port, img, xfer_len, tag++); + + if (nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) { + for (img_base = 0; img_base < xfer_len; img_base += 4, mem_base += 4) { + if (((img_base / 4) % 8) == 0) + printk(KERN_INFO "%s %08x <-", type, mem_base); + printk(KERN_CONT " %08x", *(u32 *)(img + img_base)); + if ((img_base / 4) == 7 && mem_type == IMEM) + printk(KERN_CONT " %04x", tag - 1); + } + } + + img += xfer_len; + len -= xfer_len; + } while (len); + + return 0; +} + void nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, u32 size, u16 tag, u8 port, bool secure) diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c new file mode 100644 index 000000000000..12a899dbec35 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c @@ -0,0 +1,229 @@ +/* + * Copyright 2022 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +#include +#include + +#include +#include + +int +nvkm_falcon_fw_patch(struct nvkm_falcon_fw *fw) +{ + struct nvkm_falcon *falcon = fw->falcon; + u32 sig_base_src = fw->sig_base_prd; + u32 src, dst, len, i; + int idx = 0; + + FLCNFW_DBG(fw, "patching sigs:%d size:%d", fw->sig_nr, fw->sig_size); + if (fw->func->signature) { + idx = fw->func->signature(fw, &sig_base_src); + if (idx < 0) + return idx; + } + + src = idx * fw->sig_size; + dst = fw->sig_base_img; + len = fw->sig_size / 4; + FLCNFW_DBG(fw, "patch idx:%d src:%08x dst:%08x", idx, sig_base_src + src, dst); + for (i = 0; i < len; i++) { + u32 sig = *(u32 *)(fw->sigs + src); + + if (nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) { + if (i % 8 == 0) + printk(KERN_INFO "sig -> %08x:", dst); + printk(KERN_CONT " %08x", sig); + } + + *(u32 *)(fw->fw.img + dst) = sig; + src += 4; + dst += 4; + } + + return 0; +} + +static void +nvkm_falcon_fw_dtor_sigs(struct nvkm_falcon_fw *fw) +{ + kfree(fw->sigs); + fw->sigs = NULL; +} + +int +nvkm_falcon_fw_boot(struct nvkm_falcon_fw *fw, struct nvkm_subdev *user, + bool release, u32 *pmbox0, u32 *pmbox1, u32 mbox0_ok, u32 irqsclr) +{ + struct nvkm_falcon *falcon = fw->falcon; + int ret; + + ret = nvkm_falcon_get(falcon, user); + if (ret) + return ret; + + if (fw->sigs) { + ret = nvkm_falcon_fw_patch(fw); + if (ret) + goto done; + + nvkm_falcon_fw_dtor_sigs(fw); + } + + FLCNFW_DBG(fw, "resetting"); + fw->func->reset(fw); + + FLCNFW_DBG(fw, "loading"); + ret = fw->func->load(fw); + if (ret) + goto done; + + FLCNFW_DBG(fw, "booting"); + ret = fw->func->boot(fw, pmbox0, pmbox1, mbox0_ok, irqsclr); + if (ret) + FLCNFW_ERR(fw, "boot failed: %d", ret); + else + FLCNFW_DBG(fw, "booted"); + +done: + if (ret || release) + nvkm_falcon_put(falcon, user); + return ret; +} + +int +nvkm_falcon_fw_oneinit(struct nvkm_falcon_fw *fw, struct nvkm_falcon *falcon, + struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + fw->falcon = falcon; + fw->vmm = nvkm_vmm_ref(vmm); + fw->inst = nvkm_memory_ref(inst); + return 0; +} + +void +nvkm_falcon_fw_dtor(struct nvkm_falcon_fw *fw) +{ + nvkm_vmm_unref(&fw->vmm); + nvkm_memory_unref(&fw->inst); + nvkm_falcon_fw_dtor_sigs(fw); + nvkm_firmware_dtor(&fw->fw); +} + +static const struct nvkm_firmware_func +nvkm_falcon_fw = { + .type = NVKM_FIRMWARE_IMG_RAM, +}; + +int +nvkm_falcon_fw_sign(struct nvkm_falcon_fw *fw, u32 sig_base_img, u32 sig_size, const u8 *sigs, + int sig_nr_prd, u32 sig_base_prd, int sig_nr_dbg, u32 sig_base_dbg) +{ + fw->sig_base_prd = sig_base_prd; + fw->sig_base_dbg = sig_base_dbg; + fw->sig_base_img = sig_base_img; + fw->sig_size = sig_size; + fw->sig_nr = sig_nr_prd + sig_nr_dbg; + + fw->sigs = kmalloc_array(fw->sig_nr, fw->sig_size, GFP_KERNEL); + if (!fw->sigs) + return -ENOMEM; + + memcpy(fw->sigs, sigs + sig_base_prd, sig_nr_prd * fw->sig_size); + if (sig_nr_dbg) + memcpy(fw->sigs + sig_size, sigs + sig_base_dbg, sig_nr_dbg * fw->sig_size); + + return 0; +} + +int +nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *func, const char *name, + struct nvkm_device *device, bool dma, const void *src, u32 len, + struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw) +{ + const struct nvkm_firmware_func *type = &nvkm_falcon_fw; + int ret; + + fw->func = func; + + ret = nvkm_firmware_ctor(type, name, device, src, len, &fw->fw); + if (ret) + return ret; + + return falcon ? nvkm_falcon_fw_oneinit(fw, falcon, NULL, NULL) : 0; +} + +int +nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *func, const char *name, + struct nvkm_subdev *subdev, const char *bl, const char *img, int ver, + struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw) +{ + const struct firmware *blob; + const struct nvfw_bin_hdr *hdr; + const struct nvfw_hs_header *hshdr; + const struct nvfw_hs_load_header *lhdr; + u32 loc, sig; + int ret; + + ret = nvkm_firmware_load_name(subdev, img, "", ver, &blob); + if (ret) + return ret; + + hdr = nvfw_bin_hdr(subdev, blob->data); + hshdr = nvfw_hs_header(subdev, blob->data + hdr->header_offset); + loc = *(u32 *)(blob->data + hshdr->patch_loc); + sig = *(u32 *)(blob->data + hshdr->patch_sig); + + ret = nvkm_falcon_fw_ctor(func, name, subdev->device, bl != NULL, + blob->data + hdr->data_offset, hdr->data_size, falcon, fw); + if (ret) + goto done; + + ret = nvkm_falcon_fw_sign(fw, loc, hshdr->sig_prod_size, blob->data, + 1, hshdr->sig_prod_offset + sig, + 1, hshdr->sig_dbg_offset + sig); + if (ret) + goto done; + + lhdr = nvfw_hs_load_header(subdev, blob->data + hshdr->hdr_offset); + + fw->nmem_base_img = 0; + fw->nmem_base = lhdr->non_sec_code_off; + fw->nmem_size = lhdr->non_sec_code_size; + + fw->imem_base_img = lhdr->apps[0]; + fw->imem_base = ALIGN(lhdr->apps[0], 0x100); + fw->imem_size = lhdr->apps[lhdr->num_apps + 0]; + + fw->dmem_base_img = lhdr->data_dma_base; + fw->dmem_base = 0; + fw->dmem_size = lhdr->data_size; + fw->dmem_sign = loc - lhdr->data_dma_base; + + fw->boot_addr = fw->nmem_base; +done: + if (ret) + nvkm_falcon_fw_dtor(fw); + + nvkm_firmware_put(blob); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c index 9144bcbc7f45..014ca38b8ff3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c @@ -24,6 +24,55 @@ #include #include +static void +gm200_flcn_pio_dmem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag) +{ + while (len >= 4) { + nvkm_falcon_wr32(falcon, 0x1c4 + (port * 8), *(u32 *)img); + img += 4; + len -= 4; + } +} + +static void +gm200_flcn_pio_dmem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 dmem_base) +{ + nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), BIT(24) | dmem_base); +} + +const struct nvkm_falcon_func_pio +gm200_flcn_dmem_pio = { + .min = 4, + .max = 0x100, + .wr_init = gm200_flcn_pio_dmem_wr_init, + .wr = gm200_flcn_pio_dmem_wr, +}; + +static void +gm200_flcn_pio_imem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 imem_base) +{ + nvkm_falcon_wr32(falcon, 0x180 + (port * 0x10), (sec ? BIT(28) : 0) | BIT(24) | imem_base); +} + +static void +gm200_flcn_pio_imem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag) +{ + nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag++); + while (len >= 4) { + nvkm_falcon_wr32(falcon, 0x184 + (port * 0x10), *(u32 *)img); + img += 4; + len -= 4; + } +} + +const struct nvkm_falcon_func_pio +gm200_flcn_imem_pio = { + .min = 0x100, + .max = 0x100, + .wr_init = gm200_flcn_pio_imem_wr_init, + .wr = gm200_flcn_pio_imem_wr, +}; + int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon) { @@ -81,3 +130,98 @@ gm200_flcn_disable(struct nvkm_falcon *falcon) return 0; } + +int +gm200_flcn_fw_boot(struct nvkm_falcon_fw *fw, u32 *pmbox0, u32 *pmbox1, u32 mbox0_ok, u32 irqsclr) +{ + struct nvkm_falcon *falcon = fw->falcon; + u32 mbox0, mbox1; + int ret = 0; + + nvkm_falcon_wr32(falcon, 0x040, pmbox0 ? *pmbox0 : 0xcafebeef); + if (pmbox1) + nvkm_falcon_wr32(falcon, 0x044, *pmbox1); + + nvkm_falcon_wr32(falcon, 0x104, fw->boot_addr); + nvkm_falcon_wr32(falcon, 0x100, 0x00000002); + + if (nvkm_msec(falcon->owner->device, 2000, + if (nvkm_falcon_rd32(falcon, 0x100) & 0x00000010) + break; + ) < 0) + ret = -ETIMEDOUT; + + mbox0 = nvkm_falcon_rd32(falcon, 0x040); + mbox1 = nvkm_falcon_rd32(falcon, 0x044); + if (FLCN_ERRON(falcon, ret || mbox0 != mbox0_ok, "mbox %08x %08x", mbox0, mbox1)) + ret = ret ?: -EIO; + + if (irqsclr) + nvkm_falcon_mask(falcon, 0x004, 0xffffffff, irqsclr); + + return ret; +} + +int +gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) +{ + struct nvkm_falcon *falcon = fw->falcon; + int ret; + + if (1) { + nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080); + nvkm_falcon_wr32(falcon, 0x10c, 0x00000000); + } + + ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->nmem_base_img, fw->nmem_base_img, 0, + IMEM, fw->nmem_base, fw->nmem_size, fw->nmem_base >> 8, false); + if (ret) + return ret; + + ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->imem_base_img, fw->imem_base_img, 0, + IMEM, fw->imem_base, fw->imem_size, fw->imem_base >> 8, true); + if (ret) + return ret; + + ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->dmem_base_img, fw->dmem_base_img, 0, + DMEM, fw->dmem_base, fw->dmem_size, 0, false); + if (ret) + return ret; + + return 0; +} + +int +gm200_flcn_fw_reset(struct nvkm_falcon_fw *fw) +{ + return nvkm_falcon_reset(fw->falcon); +} + +int +gm200_flcn_fw_signature(struct nvkm_falcon_fw *fw, u32 *sig_base_src) +{ + struct nvkm_falcon *falcon = fw->falcon; + u32 addr = falcon->func->debug; + int ret = 0; + + if (addr) { + ret = nvkm_falcon_enable(falcon); + if (ret) + return ret; + + if (nvkm_falcon_rd32(falcon, addr) & 0x00100000) { + *sig_base_src = fw->sig_base_dbg; + return 1; + } + } + + return ret; +} + +const struct nvkm_falcon_fw_func +gm200_flcn_fw = { + .signature = gm200_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .load = gm200_flcn_fw_load, + .boot = gm200_flcn_fw_boot, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index 0e78b3d734a0..e15ac4b7598e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -24,71 +24,22 @@ #include "gf100.h" #include "ram.h" -#include -#include -#include -#include #include int gp102_fb_vpr_scrub(struct nvkm_fb *fb) { struct nvkm_subdev *subdev = &fb->subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_falcon *falcon = &device->nvdec[0]->falcon; - struct nvkm_blob *blob = &fb->vpr_scrubber; - const struct nvfw_bin_hdr *hsbin_hdr; - const struct nvfw_hs_header *fw_hdr; - const struct nvfw_hs_load_header *lhdr; - void *scrub_data; - u32 patch_loc, patch_sig; + struct nvkm_falcon_fw fw = {}; int ret; - nvkm_falcon_get(falcon, subdev); - - hsbin_hdr = nvfw_bin_hdr(subdev, blob->data); - fw_hdr = nvfw_hs_header(subdev, blob->data + hsbin_hdr->header_offset); - lhdr = nvfw_hs_load_header(subdev, blob->data + fw_hdr->hdr_offset); - scrub_data = blob->data + hsbin_hdr->data_offset; - - patch_loc = *(u32 *)(blob->data + fw_hdr->patch_loc); - patch_sig = *(u32 *)(blob->data + fw_hdr->patch_sig); - if (falcon->debug) { - memcpy(scrub_data + patch_loc, - blob->data + fw_hdr->sig_dbg_offset + patch_sig, - fw_hdr->sig_dbg_size); - } else { - memcpy(scrub_data + patch_loc, - blob->data + fw_hdr->sig_prod_offset + patch_sig, - fw_hdr->sig_prod_size); - } - - nvkm_falcon_reset(falcon); - nvkm_falcon_bind_context(falcon, NULL); - - nvkm_falcon_load_imem(falcon, scrub_data, lhdr->non_sec_code_off, - lhdr->non_sec_code_size, - lhdr->non_sec_code_off >> 8, 0, false); - nvkm_falcon_load_imem(falcon, scrub_data + lhdr->apps[0], - ALIGN(lhdr->apps[0], 0x100), - lhdr->apps[1], - lhdr->apps[0] >> 8, 0, true); - nvkm_falcon_load_dmem(falcon, scrub_data + lhdr->data_dma_base, 0, - lhdr->data_size, 0); - - nvkm_falcon_set_start_addr(falcon, 0x0); - nvkm_falcon_start(falcon); - - ret = nvkm_falcon_wait_for_halt(falcon, 500); - if (ret < 0) { - ret = -ETIMEDOUT; - goto end; - } + ret = nvkm_falcon_fw_ctor_hs(&gm200_flcn_fw, "mem-unlock", subdev, NULL, + "nvdec/scrubber", 0, &subdev->device->nvdec[0]->falcon, &fw); + if (ret) + return ret; - /* put nvdec in clean state - without reset it will remain in HS mode */ - nvkm_falcon_reset(falcon); -end: - nvkm_falcon_put(falcon, subdev); + ret = nvkm_falcon_fw_boot(&fw, subdev, true, NULL, NULL, 0, 0x00000000); + nvkm_falcon_fw_dtor(&fw); return ret; } -- cgit v1.2.3 From 5728d064190e169f1a42381bd7e5fc4d411f3188 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:51 +1000 Subject: drm/nouveau/fb: handle sysmem flush page from common code - also executes pre-DEVINIT, so early boot is able to DMA sysmem Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h | 5 +++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 44 ++++++++++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c | 3 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c | 3 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c | 25 ++++---------- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h | 4 --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c | 4 +-- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c | 18 ++-------- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | 3 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c | 3 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c | 38 ++++---------------- drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h | 2 -- drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | 9 +++-- 15 files changed, 80 insertions(+), 83 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h index ef6a6297148c..f2bd9b11c84a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h @@ -35,6 +35,11 @@ struct nvkm_fb { struct nvkm_blob vpr_scrubber; + struct { + struct page *flush_page; + dma_addr_t flush_page_addr; + } sysmem; + struct nvkm_ram *ram; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index 6faaea948fc4..2ebdec44236d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -57,6 +57,15 @@ nvkm_fb_tile_prog(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile) } } +static void +nvkm_fb_sysmem_flush_page_init(struct nvkm_device *device) +{ + struct nvkm_fb *fb = device->fb; + + if (fb->func->sysmem.flush_page_init) + fb->func->sysmem.flush_page_init(fb); +} + int nvkm_fb_bios_memtype(struct nvkm_bios *bios) { @@ -168,6 +177,8 @@ nvkm_fb_init(struct nvkm_subdev *subdev) for (i = 0; i < fb->tile.regions; i++) fb->func->tile.prog(fb, i, &fb->tile.region[i]); + nvkm_fb_sysmem_flush_page_init(subdev->device); + if (fb->func->init) fb->func->init(fb); @@ -193,6 +204,13 @@ nvkm_fb_init(struct nvkm_subdev *subdev) return 0; } +static int +nvkm_fb_preinit(struct nvkm_subdev *subdev) +{ + nvkm_fb_sysmem_flush_page_init(subdev->device); + return 0; +} + static void * nvkm_fb_dtor(struct nvkm_subdev *subdev) { @@ -212,20 +230,28 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev) nvkm_blob_dtor(&fb->vpr_scrubber); + if (fb->sysmem.flush_page) { + dma_unmap_page(subdev->device->dev, fb->sysmem.flush_page_addr, + PAGE_SIZE, DMA_BIDIRECTIONAL); + __free_page(fb->sysmem.flush_page); + } + if (fb->func->dtor) return fb->func->dtor(fb); + return fb; } static const struct nvkm_subdev_func nvkm_fb = { .dtor = nvkm_fb_dtor, + .preinit = nvkm_fb_preinit, .oneinit = nvkm_fb_oneinit, .init = nvkm_fb_init, .intr = nvkm_fb_intr, }; -void +int nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb *fb) { @@ -234,6 +260,19 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device, fb->tile.regions = fb->func->tile.regions; fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", fb->func->default_bigpage); mutex_init(&fb->tags.mutex); + + if (func->sysmem.flush_page_init) { + fb->sysmem.flush_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!fb->sysmem.flush_page) + return -ENOMEM; + + fb->sysmem.flush_page_addr = dma_map_page(device->dev, fb->sysmem.flush_page, + 0, PAGE_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(device->dev, fb->sysmem.flush_page_addr)) + return -EFAULT; + } + + return 0; } int @@ -242,6 +281,5 @@ nvkm_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, { if (!(*pfb = kzalloc(sizeof(**pfb), GFP_KERNEL))) return -ENOMEM; - nvkm_fb_ctor(func, device, type, inst, *pfb); - return 0; + return nvkm_fb_ctor(func, device, type, inst, *pfb); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c index b47bebfbc26f..5098f219e3e6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c @@ -26,9 +26,10 @@ static const struct nvkm_fb_func ga100_fb = { .dtor = gf100_fb_dtor, .oneinit = gf100_fb_oneinit, - .init = gp100_fb_init, + .init = gm200_fb_init, .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .ram_new = gp100_ram_new, .default_bigpage = 16, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c index 6ea7908f0563..52435c0a485c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c @@ -26,9 +26,10 @@ static const struct nvkm_fb_func ga102_fb = { .dtor = gf100_fb_dtor, .oneinit = gf100_fb_oneinit, - .init = gp100_fb_init, + .init = gm200_fb_init, .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .ram_new = ga102_ram_new, .default_bigpage = 16, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c index 9dcc40f9ef79..07db9b397ac1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c @@ -61,14 +61,6 @@ gf100_fb_oneinit(struct nvkm_fb *base) if (ret) return ret; - fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (fb->r100c10_page) { - fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0, - PAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(device->dev, fb->r100c10)) - return -EFAULT; - } - return 0; } @@ -85,15 +77,18 @@ gf100_fb_init_page(struct nvkm_fb *fb) return 0; } +void +gf100_fb_sysmem_flush_page_init(struct nvkm_fb *fb) +{ + nvkm_wr32(fb->subdev.device, 0x100c10, fb->sysmem.flush_page_addr >> 8); +} + void gf100_fb_init(struct nvkm_fb *base) { struct gf100_fb *fb = gf100_fb(base); struct nvkm_device *device = fb->base.subdev.device; - if (fb->r100c10_page) - nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8); - if (base->func->clkgate_pack) { nvkm_therm_clkgate_init(device->therm, base->func->clkgate_pack); @@ -104,13 +99,6 @@ void * gf100_fb_dtor(struct nvkm_fb *base) { struct gf100_fb *fb = gf100_fb(base); - struct nvkm_device *device = fb->base.subdev.device; - - if (fb->r100c10_page) { - dma_unmap_page(device->dev, fb->r100c10, PAGE_SIZE, - DMA_BIDIRECTIONAL); - __free_page(fb->r100c10_page); - } return fb; } @@ -136,6 +124,7 @@ gf100_fb = { .init = gf100_fb_init, .init_page = gf100_fb_init_page, .intr = gf100_fb_intr, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .ram_new = gf100_ram_new, .default_bigpage = 17, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h index 0cac7b06acc8..77472b558591 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h @@ -6,8 +6,6 @@ struct gf100_fb { struct nvkm_fb base; - struct page *r100c10_page; - dma_addr_t r100c10; }; int gf100_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *, enum nvkm_subdev_type, int, @@ -16,7 +14,5 @@ void *gf100_fb_dtor(struct nvkm_fb *); void gf100_fb_init(struct nvkm_fb *); void gf100_fb_intr(struct nvkm_fb *); -void gp100_fb_init(struct nvkm_fb *); - void gm200_fb_init(struct nvkm_fb *base); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c index 5acf8d15d06f..fb02092a65eb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c @@ -46,9 +46,6 @@ gm200_fb_init(struct nvkm_fb *base) struct gf100_fb *fb = gf100_fb(base); struct nvkm_device *device = fb->base.subdev.device; - if (fb->r100c10_page) - nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8); - nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->base.mmu_wr) >> 8); nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->base.mmu_rd) >> 8); nvkm_mask(device, 0x100cc4, 0x00060000, @@ -62,6 +59,7 @@ gm200_fb = { .init = gm200_fb_init, .init_page = gm200_fb_init_page, .intr = gf100_fb_intr, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .ram_new = gm200_ram_new, .default_bigpage = 0 /* per-instance. */, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c index 86f61a3f2fea..50875af94c18 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c @@ -30,6 +30,7 @@ gm20b_fb = { .init = gm200_fb_init, .init_page = gm200_fb_init_page, .intr = gf100_fb_intr, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .default_bigpage = 0 /* per-instance. */, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c index 09e943edc362..110c08c94849 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c @@ -44,29 +44,15 @@ gp100_fb_init_remapper(struct nvkm_fb *fb) nvkm_mask(device, 0x100c14, 0x00040000, 0x00000000); } -void -gp100_fb_init(struct nvkm_fb *base) -{ - struct gf100_fb *fb = gf100_fb(base); - struct nvkm_device *device = fb->base.subdev.device; - - if (fb->r100c10_page) - nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8); - - nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->base.mmu_wr) >> 8); - nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->base.mmu_rd) >> 8); - nvkm_mask(device, 0x100cc4, 0x00060000, - min(nvkm_memory_size(fb->base.mmu_rd) >> 16, (u64)2) << 17); -} - static const struct nvkm_fb_func gp100_fb = { .dtor = gf100_fb_dtor, .oneinit = gf100_fb_oneinit, - .init = gp100_fb_init, + .init = gm200_fb_init, .init_remapper = gp100_fb_init_remapper, .init_page = gm200_fb_init_page, .init_unkn = gp100_fb_init_unkn, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .ram_new = gp100_ram_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index e15ac4b7598e..2658481d575b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -55,9 +55,10 @@ static const struct nvkm_fb_func gp102_fb = { .dtor = gf100_fb_dtor, .oneinit = gf100_fb_oneinit, - .init = gp100_fb_init, + .init = gm200_fb_init, .init_remapper = gp100_fb_init_remapper, .init_page = gm200_fb_init_page, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .vpr.scrub_required = gp102_fb_vpr_scrub_required, .vpr.scrub = gp102_fb_vpr_scrub, .ram_new = gp100_ram_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c index 84c9815a6d48..a04a5f712019 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c @@ -28,6 +28,7 @@ gp10b_fb = { .init = gm200_fb_init, .init_page = gm200_fb_init_page, .intr = gf100_fb_intr, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c index 63daa83ae12d..1f0126437c1a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c @@ -32,9 +32,10 @@ static const struct nvkm_fb_func gv100_fb = { .dtor = gf100_fb_dtor, .oneinit = gf100_fb_oneinit, - .init = gp100_fb_init, + .init = gm200_fb_init, .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, + .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .vpr.scrub_required = gp102_fb_vpr_scrub_required, .vpr.scrub = gp102_fb_vpr_scrub, .ram_new = gp100_ram_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c index 48641735168e..a6efbd913c13 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c @@ -191,35 +191,12 @@ nv50_fb_intr(struct nvkm_fb *base) nvkm_chan_put(&chan, flags); } -static int -nv50_fb_oneinit(struct nvkm_fb *base) -{ - struct nv50_fb *fb = nv50_fb(base); - struct nvkm_device *device = fb->base.subdev.device; - - fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (fb->r100c08_page) { - fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0, - PAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(device->dev, fb->r100c08)) - return -EFAULT; - } - - return 0; -} - static void nv50_fb_init(struct nvkm_fb *base) { struct nv50_fb *fb = nv50_fb(base); struct nvkm_device *device = fb->base.subdev.device; - /* Not a clue what this is exactly. Without pointing it at a - * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) - * cause IOMMU "read from address 0" errors (rh#561267) - */ - nvkm_wr32(device, 0x100c08, fb->r100c08 >> 8); - /* This is needed to get meaningful information from 100c90 * on traps. No idea what these values mean exactly. */ nvkm_wr32(device, 0x100c90, fb->func->trap); @@ -234,17 +211,16 @@ nv50_fb_tags(struct nvkm_fb *base) return 0; } +static void +nv50_fb_sysmem_flush_page_init(struct nvkm_fb *fb) +{ + nvkm_wr32(fb->subdev.device, 0x100c08, fb->sysmem.flush_page_addr >> 8); +} + static void * nv50_fb_dtor(struct nvkm_fb *base) { struct nv50_fb *fb = nv50_fb(base); - struct nvkm_device *device = fb->base.subdev.device; - - if (fb->r100c08_page) { - dma_unmap_page(device->dev, fb->r100c08, PAGE_SIZE, - DMA_BIDIRECTIONAL); - __free_page(fb->r100c08_page); - } return fb; } @@ -253,9 +229,9 @@ static const struct nvkm_fb_func nv50_fb_ = { .dtor = nv50_fb_dtor, .tags = nv50_fb_tags, - .oneinit = nv50_fb_oneinit, .init = nv50_fb_init, .intr = nv50_fb_intr, + .sysmem.flush_page_init = nv50_fb_sysmem_flush_page_init, .ram_new = nv50_fb_ram_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h index a5e673859a90..4f68bc4513a7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h @@ -7,8 +7,6 @@ struct nv50_fb { const struct nv50_fb_func *func; struct nvkm_fb base; - struct page *r100c08_page; - dma_addr_t r100c08; }; struct nv50_fb_func { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index 3f1be9780c65..ac03eac0f261 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -16,6 +16,10 @@ struct nvkm_fb_func { void (*init_unkn)(struct nvkm_fb *); void (*intr)(struct nvkm_fb *); + struct nvkm_fb_func_sysmem { + void (*flush_page_init)(struct nvkm_fb *); + } sysmem; + struct { bool (*scrub_required)(struct nvkm_fb *); int (*scrub)(struct nvkm_fb *); @@ -37,8 +41,8 @@ struct nvkm_fb_func { const struct nvkm_therm_clkgate_pack *clkgate_pack; }; -void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_fb *); +int nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_fb *); int nvkm_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **); int nvkm_fb_bios_memtype(struct nvkm_bios *); @@ -72,6 +76,7 @@ void nv46_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, int gf100_fb_oneinit(struct nvkm_fb *); int gf100_fb_init_page(struct nvkm_fb *); +void gf100_fb_sysmem_flush_page_init(struct nvkm_fb *); int gm200_fb_init_page(struct nvkm_fb *); -- cgit v1.2.3 From e3f324956a32d08a9361ee1e3beca383f1b01eba Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:52 +1000 Subject: drm/nouveau/fb/gp102-: unlock VPR right after devinit Under memory load, instmem allocations could end up in the regions of VRAM that are inaccessible right after boot, and be corrupted after a suspend/resume cycle as a result of being restored before booting the mem unlock firmware. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 4 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 19 ++++++++++--------- 3 files changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h index f2bd9b11c84a..40768373cdd9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h @@ -58,6 +58,8 @@ struct nvkm_fb { struct nvkm_memory *mmu_wr; }; +int nvkm_fb_mem_unlock(struct nvkm_fb *); + void nvkm_fb_tile_init(struct nvkm_fb *, int region, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *); void nvkm_fb_tile_fini(struct nvkm_fb *, int region, struct nvkm_fb_tile *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 852c18aec4cd..c94de7b45556 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2808,6 +2808,10 @@ nvkm_device_preinit(struct nvkm_device *device) if (ret) goto fail; + ret = nvkm_fb_mem_unlock(device->fb); + if (ret) + goto fail; + time = ktime_to_us(ktime_get()) - time; nvdev_trace(device, "preinit completed in %lldus\n", time); return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index 2ebdec44236d..bac7dcc4c2c1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -134,12 +134,20 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev) return nvkm_mm_init(&fb->tags.mm, 0, 0, tags, 1); } -static int -nvkm_fb_init_scrub_vpr(struct nvkm_fb *fb) +int +nvkm_fb_mem_unlock(struct nvkm_fb *fb) { struct nvkm_subdev *subdev = &fb->subdev; int ret; + if (!fb->func->vpr.scrub_required) + return 0; + + if (!fb->func->vpr.scrub_required(fb)) { + nvkm_debug(subdev, "VPR not locked\n"); + return 0; + } + nvkm_debug(subdev, "VPR locked, running scrubber binary\n"); if (!fb->vpr_scrubber.size) { @@ -194,13 +202,6 @@ nvkm_fb_init(struct nvkm_subdev *subdev) if (fb->func->init_unkn) fb->func->init_unkn(fb); - if (fb->func->vpr.scrub_required && - fb->func->vpr.scrub_required(fb)) { - ret = nvkm_fb_init_scrub_vpr(fb); - if (ret) - return ret; - } - return 0; } -- cgit v1.2.3 From 2541626cfb794e57ba0575a6920826f591f7ced0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:52 +1000 Subject: drm/nouveau/acr: use common falcon HS FW code for ACR FWs Adds context binding and support for FWs with a bootloader to the code that was added to load VPR scrubber HS binaries, and ports ACR over to using all of it. - gv100 split from gp108 to handle FW exit status differences Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 21 ++- .../gpu/drm/nouveau/include/nvkm/core/firmware.h | 8 + .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 32 ++-- drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 3 +- drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 87 ++++++++- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 53 +----- drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 14 +- drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 79 ++++----- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 2 +- drivers/gpu/drm/nouveau/nvkm/falcon/fw.c | 75 +++++++- drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 88 +++++++++- drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c | 42 +++++ drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 2 +- drivers/gpu/drm/nouveau/nvkm/falcon/v1.c | 167 ------------------ drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 73 ++++---- drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c | 195 +++++---------------- drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c | 44 ++--- drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c | 27 +-- drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c | 55 +++--- drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c | 67 +++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c | 177 ------------------- drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h | 93 +++------- drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c | 36 +--- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c | 14 +- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c | 31 +++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c | 12 +- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 1 + 30 files changed, 648 insertions(+), 856 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index d8fd2cbd2872..4c8b668bacb4 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -6,6 +6,7 @@ enum nvkm_falcon_mem { IMEM, DMEM, + EMEM, }; static inline const char * @@ -14,6 +15,7 @@ nvkm_falcon_mem(enum nvkm_falcon_mem mem) switch (mem) { case IMEM: return "imem"; case DMEM: return "dmem"; + case EMEM: return "emem"; default: WARN_ON(1); return "?mem"; @@ -25,6 +27,8 @@ struct nvkm_falcon_func_pio { int max; void (*wr_init)(struct nvkm_falcon *, u8 port, bool sec, u32 mem_base); void (*wr)(struct nvkm_falcon *, u8 port, const u8 *img, int len, u16 tag); + void (*rd_init)(struct nvkm_falcon *, u8 port, u32 mem_base); + void (*rd)(struct nvkm_falcon *, u8 port, const u8 *img, int len); }; int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner, @@ -33,27 +37,25 @@ void nvkm_falcon_dtor(struct nvkm_falcon *); int nvkm_falcon_reset(struct nvkm_falcon *); int nvkm_falcon_pio_wr(struct nvkm_falcon *, const u8 *img, u32 img_base, u8 port, enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec); +int nvkm_falcon_pio_rd(struct nvkm_falcon *, u8 port, enum nvkm_falcon_mem type, u32 mem_base, + const u8 *img, u32 img_base, int len); int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *); int gm200_flcn_disable(struct nvkm_falcon *); int gm200_flcn_enable(struct nvkm_falcon *); +void gm200_flcn_bind_inst(struct nvkm_falcon *, int, u64); +int gm200_flcn_bind_stat(struct nvkm_falcon *, bool); extern const struct nvkm_falcon_func_pio gm200_flcn_imem_pio; extern const struct nvkm_falcon_func_pio gm200_flcn_dmem_pio; int gp102_flcn_reset_eng(struct nvkm_falcon *); +extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio; void nvkm_falcon_v1_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); -void nvkm_falcon_v1_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); -void nvkm_falcon_v1_bind_context(struct nvkm_falcon *, struct nvkm_memory *); -int nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *, u32); -int nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *, u32); -void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *, u32 start_addr); void nvkm_falcon_v1_start(struct nvkm_falcon *); -void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *); - #define FLCN_PRINTK(f,l,p,fmt,a...) ({ \ if ((f)->owner->name != (f)->name) \ nvkm_printk___((f)->owner, (f)->user, NV_DBG_##l, p, "%s:"fmt, (f)->name, ##a); \ @@ -70,7 +72,9 @@ struct nvkm_falcon_fw { const struct nvkm_falcon_fw_func { int (*signature)(struct nvkm_falcon_fw *, u32 *sig_base_src); int (*reset)(struct nvkm_falcon_fw *); + int (*setup)(struct nvkm_falcon_fw *); int (*load)(struct nvkm_falcon_fw *); + int (*load_bld)(struct nvkm_falcon_fw *); int (*boot)(struct nvkm_falcon_fw *, u32 *mbox0, u32 *mbox1, u32 mbox0_ok, u32 irqsclr); } *func; @@ -96,11 +100,14 @@ struct nvkm_falcon_fw { u32 dmem_size; u32 dmem_sign; + u8 *boot; + u32 boot_size; u32 boot_addr; struct nvkm_falcon *falcon; struct nvkm_memory *inst; struct nvkm_vmm *vmm; + struct nvkm_vma *vma; }; int nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *, const char *name, struct nvkm_device *, diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h index 8453025891a5..d4e507e252b1 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_FIRMWARE_H__ #define __NVKM_FIRMWARE_H__ +#include #include #include @@ -8,6 +9,7 @@ struct nvkm_firmware { const struct nvkm_firmware_func { enum nvkm_firmware_type { NVKM_FIRMWARE_IMG_RAM, + NVKM_FIRMWARE_IMG_DMA, } type; } *func; const char *name; @@ -15,6 +17,12 @@ struct nvkm_firmware { int len; u8 *img; + u64 phys; + + struct nvkm_firmware_mem { + struct nvkm_memory memory; + struct scatterlist sgl; + } mem; }; int nvkm_firmware_ctor(const struct nvkm_firmware_func *, const char *name, struct nvkm_device *, diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index ca751199379e..f576ca246d10 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -64,9 +64,22 @@ struct nvkm_falcon_func { int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *); u32 debug; + void (*bind_inst)(struct nvkm_falcon *, int target, u64 addr); + int (*bind_stat)(struct nvkm_falcon *, bool intr); + bool bind_intr; + const struct nvkm_falcon_func_pio *imem_pio; const struct nvkm_falcon_func_pio *dmem_pio; + u32 emem_addr; + const struct nvkm_falcon_func_pio *emem_pio; + + struct { + u32 head; + u32 tail; + u32 stride; + } cmdq, msgq; + struct { u32 *data; u32 size; @@ -78,24 +91,10 @@ struct nvkm_falcon_func { void (*init)(struct nvkm_falcon *); void (*intr)(struct nvkm_falcon *, struct nvkm_chan *); - u32 fbif; - void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8); - void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *); - u32 emem_addr; - void (*bind_context)(struct nvkm_falcon *, struct nvkm_memory *); - int (*wait_for_halt)(struct nvkm_falcon *, u32); - int (*clear_interrupt)(struct nvkm_falcon *, u32); - void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr); void (*start)(struct nvkm_falcon *); - struct { - u32 head; - u32 tail; - u32 stride; - } cmdq, msgq; - struct nvkm_sclass sclass[]; }; @@ -122,10 +121,5 @@ nvkm_falcon_mask(struct nvkm_falcon *falcon, u32 addr, u32 mask, u32 val) void nvkm_falcon_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); -void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); -void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_memory *); -void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32); void nvkm_falcon_start(struct nvkm_falcon *); -int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32); -int nvkm_falcon_clear_interrupt(struct nvkm_falcon *, u32); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index fe5024b6d0f3..12c0b8395262 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -36,7 +36,7 @@ struct nvkm_acr { const struct nvkm_acr_func *func; struct nvkm_subdev subdev; - struct list_head hsfw, hsf; + struct list_head hsfw; struct list_head lsfw, lsf; u64 managed_falcons; @@ -65,6 +65,7 @@ int gm20b_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct int gp102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); int gp108_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); int gp10b_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); +int gv100_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); int tu102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); struct nvkm_acr_lsfw { diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c index aa1bf6b5a8cd..fcf2a002f6cb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c @@ -22,6 +22,9 @@ #include #include +#include +#include + int nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *base, const char *name, int ver, const struct firmware **pfw) @@ -108,9 +111,70 @@ nvkm_firmware_put(const struct firmware *fw) release_firmware(fw); } +#define nvkm_firmware_mem(p) container_of((p), struct nvkm_firmware, mem.memory) + +static int +nvkm_firmware_mem_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, + struct nvkm_vma *vma, void *argv, u32 argc) +{ + struct nvkm_firmware *fw = nvkm_firmware_mem(memory); + struct nvkm_vmm_map map = { + .memory = &fw->mem.memory, + .offset = offset, + .sgl = &fw->mem.sgl, + }; + + if (WARN_ON(fw->func->type != NVKM_FIRMWARE_IMG_DMA)) + return -ENOSYS; + + return nvkm_vmm_map(vmm, vma, argv, argc, &map); +} + +static u64 +nvkm_firmware_mem_size(struct nvkm_memory *memory) +{ + return sg_dma_len(&nvkm_firmware_mem(memory)->mem.sgl); +} + +static u64 +nvkm_firmware_mem_addr(struct nvkm_memory *memory) +{ + return nvkm_firmware_mem(memory)->phys; +} + +static u8 +nvkm_firmware_mem_page(struct nvkm_memory *memory) +{ + return PAGE_SHIFT; +} + +static enum nvkm_memory_target +nvkm_firmware_mem_target(struct nvkm_memory *memory) +{ + return NVKM_MEM_TARGET_HOST; +} + +static void * +nvkm_firmware_mem_dtor(struct nvkm_memory *memory) +{ + return NULL; +} + +static const struct nvkm_memory_func +nvkm_firmware_mem = { + .dtor = nvkm_firmware_mem_dtor, + .target = nvkm_firmware_mem_target, + .page = nvkm_firmware_mem_page, + .addr = nvkm_firmware_mem_addr, + .size = nvkm_firmware_mem_size, + .map = nvkm_firmware_mem_map, +}; + void nvkm_firmware_dtor(struct nvkm_firmware *fw) { + struct nvkm_memory *memory = &fw->mem.memory; + if (!fw->img) return; @@ -118,6 +182,10 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw) case NVKM_FIRMWARE_IMG_RAM: kfree(fw->img); break; + case NVKM_FIRMWARE_IMG_DMA: + nvkm_memory_unref(&memory); + dma_free_coherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), fw->img, fw->phys); + break; default: WARN_ON(1); break; @@ -133,12 +201,28 @@ nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name, fw->func = func; fw->name = name; fw->device = device; + fw->len = len; switch (fw->func->type) { case NVKM_FIRMWARE_IMG_RAM: - fw->len = len; fw->img = kmemdup(src, fw->len, GFP_KERNEL); break; + case NVKM_FIRMWARE_IMG_DMA: { + dma_addr_t addr; + + len = ALIGN(fw->len, PAGE_SIZE); + + fw->img = dma_alloc_coherent(fw->device->dev, len, &addr, GFP_KERNEL); + if (fw->img) { + memcpy(fw->img, src, fw->len); + fw->phys = addr; + } + + sg_init_one(&fw->mem.sgl, fw->img, len); + sg_dma_address(&fw->mem.sgl) = fw->phys; + sg_dma_len(&fw->mem.sgl) = len; + } + break; default: WARN_ON(1); return -EINVAL; @@ -147,5 +231,6 @@ nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name, if (!fw->img) return -ENOMEM; + nvkm_memory_ctor(&nvkm_firmware_mem, &fw->mem.memory); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index c94de7b45556..931a59581815 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2364,7 +2364,7 @@ nv13b_chipset = { static const struct nvkm_device_chip nv140_chipset = { .name = "GV100", - .acr = { 0x00000001, gp108_acr_new }, + .acr = { 0x00000001, gv100_acr_new }, .bar = { 0x00000001, gm107_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .bus = { 0x00000001, gf100_bus_new }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index ae910c9bdc0a..a5c987ce58ed 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -190,45 +190,6 @@ gp102_sec2_intr(struct nvkm_inth *inth) return IRQ_HANDLED; } -void -gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon, - struct nvkm_memory *ctx) -{ - struct nvkm_device *device = falcon->owner->device; - - nvkm_falcon_v1_bind_context(falcon, ctx); - if (!ctx) - return; - - /* Not sure if this is a WAR for a HW issue, or some additional - * programming sequence that's needed to properly complete the - * context switch we trigger above. - * - * Fixes unreliability of booting the SEC2 RTOS on Quadro P620, - * particularly when resuming from suspend. - * - * Also removes the need for an odd workaround where we needed - * to program SEC2's FALCON_CPUCTL_ALIAS_STARTCPU twice before - * the SEC2 RTOS would begin executing. - */ - nvkm_msec(device, 10, - u32 irqstat = nvkm_falcon_rd32(falcon, 0x008); - u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc); - if ((irqstat & 0x00000008) && - (flcn0dc & 0x00007000) == 0x00005000) - break; - ); - - nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008); - nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002); - - nvkm_msec(device, 10, - u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc); - if ((flcn0dc & 0x00007000) == 0x00000000) - break; - ); -} - static const struct nvkm_falcon_func gp102_sec2_flcn = { .disable = gm200_flcn_disable, @@ -237,15 +198,13 @@ gp102_sec2_flcn = { .reset_eng = gp102_flcn_reset_eng, .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0x408, - .fbif = 0x600, - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_inst = gm200_flcn_bind_inst, + .bind_stat = gm200_flcn_bind_stat, + .bind_intr = true, + .imem_pio = &gm200_flcn_imem_pio, + .dmem_pio = &gm200_flcn_dmem_pio, .emem_addr = 0x01000000, - .bind_context = gp102_sec2_flcn_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, + .emem_pio = &gp102_flcn_emem_pio, .start = nvkm_falcon_v1_start, .cmdq = { 0xa00, 0xa04, 8 }, .msgq = { 0xa30, 0xa34, 8 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index 0f859f323504..0afc4b2fa529 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -32,15 +32,13 @@ tu102_sec2_flcn = { .reset_eng = gp102_flcn_reset_eng, .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0x408, - .fbif = 0x600, - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_inst = gm200_flcn_bind_inst, + .bind_stat = gm200_flcn_bind_stat, + .bind_intr = true, + .imem_pio = &gm200_flcn_imem_pio, + .dmem_pio = &gm200_flcn_dmem_pio, .emem_addr = 0x01000000, - .bind_context = gp102_sec2_flcn_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, + .emem_pio = &gp102_flcn_emem_pio, .start = nvkm_falcon_v1_start, .cmdq = { 0xc00, 0xc04, 8 }, .msgq = { 0xc80, 0xc84, 8 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index c15dda020c77..e4075aa441f3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -22,6 +22,7 @@ #include "priv.h" #include +#include #include static const struct nvkm_falcon_func_pio * @@ -36,11 +37,48 @@ nvkm_falcon_pio(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base -= falcon->func->emem_addr; fallthrough; + case EMEM: + return falcon->func->emem_pio; default: return NULL; } } +int +nvkm_falcon_pio_rd(struct nvkm_falcon *falcon, u8 port, enum nvkm_falcon_mem mem_type, u32 mem_base, + const u8 *img, u32 img_base, int len) +{ + const struct nvkm_falcon_func_pio *pio = nvkm_falcon_pio(falcon, &mem_type, &mem_base); + const char *type = nvkm_falcon_mem(mem_type); + int xfer_len; + + if (WARN_ON(!pio || !pio->rd)) + return -EINVAL; + + FLCN_DBG(falcon, "%s %08x -> %08x bytes at %08x", type, mem_base, len, img_base); + if (WARN_ON(!len || (len & (pio->min - 1)))) + return -EINVAL; + + pio->rd_init(falcon, port, mem_base); + do { + xfer_len = min(len, pio->max); + pio->rd(falcon, port, img, xfer_len); + + if (nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) { + for (img_base = 0; img_base < xfer_len; img_base += 4, mem_base += 4) { + if (((img_base / 4) % 8) == 0) + printk(KERN_INFO "%s %08x ->", type, mem_base); + printk(KERN_CONT " %08x", *(u32 *)(img + img_base)); + } + } + + img += xfer_len; + len -= xfer_len; + } while (len); + + return 0; +} + int nvkm_falcon_pio_wr(struct nvkm_falcon *falcon, const u8 *img, u32 img_base, u8 port, enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec) @@ -103,35 +141,6 @@ nvkm_falcon_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, mutex_unlock(&falcon->dmem_mutex); } -void -nvkm_falcon_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port, - void *data) -{ - mutex_lock(&falcon->dmem_mutex); - - falcon->func->read_dmem(falcon, start, size, port, data); - - mutex_unlock(&falcon->dmem_mutex); -} - -void -nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *inst) -{ - if (!falcon->func->bind_context) { - nvkm_error(falcon->user, - "Context binding not supported on this falcon!\n"); - return; - } - - falcon->func->bind_context(falcon, inst); -} - -void -nvkm_falcon_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr) -{ - falcon->func->set_start_addr(falcon, start_addr); -} - void nvkm_falcon_start(struct nvkm_falcon *falcon) { @@ -150,18 +159,6 @@ nvkm_falcon_reset(struct nvkm_falcon *falcon) return nvkm_falcon_enable(falcon); } -int -nvkm_falcon_wait_for_halt(struct nvkm_falcon *falcon, u32 ms) -{ - return falcon->func->wait_for_halt(falcon, ms); -} - -int -nvkm_falcon_clear_interrupt(struct nvkm_falcon *falcon, u32 mask) -{ - return falcon->func->clear_interrupt(falcon, mask); -} - static int nvkm_falcon_oneinit(struct nvkm_falcon *falcon) { diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index 44cf6a8862e1..211ebe7afac6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -51,7 +51,7 @@ static void nvkm_falcon_cmdq_push(struct nvkm_falcon_cmdq *cmdq, void *data, u32 size) { struct nvkm_falcon *falcon = cmdq->qmgr->falcon; - nvkm_falcon_load_dmem(falcon, data, cmdq->position, size, 0); + nvkm_falcon_pio_wr(falcon, data, 0, 0, DMEM, cmdq->position, size, 0, false); cmdq->position += ALIGN(size, QUEUE_ALIGNMENT); } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c index 12a899dbec35..13d52d7e4f60 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c @@ -93,6 +93,12 @@ nvkm_falcon_fw_boot(struct nvkm_falcon_fw *fw, struct nvkm_subdev *user, fw->func->reset(fw); FLCNFW_DBG(fw, "loading"); + if (fw->func->setup) { + ret = fw->func->setup(fw); + if (ret) + goto done; + } + ret = fw->func->load(fw); if (ret) goto done; @@ -114,21 +120,45 @@ int nvkm_falcon_fw_oneinit(struct nvkm_falcon_fw *fw, struct nvkm_falcon *falcon, struct nvkm_vmm *vmm, struct nvkm_memory *inst) { + int ret; + fw->falcon = falcon; fw->vmm = nvkm_vmm_ref(vmm); fw->inst = nvkm_memory_ref(inst); + + if (fw->boot) { + FLCN_DBG(falcon, "mapping %s fw", fw->fw.name); + ret = nvkm_vmm_get(fw->vmm, 12, nvkm_memory_size(&fw->fw.mem.memory), &fw->vma); + if (ret) { + FLCN_ERR(falcon, "get %d", ret); + return ret; + } + + ret = nvkm_memory_map(&fw->fw.mem.memory, 0, fw->vmm, fw->vma, NULL, 0); + if (ret) { + FLCN_ERR(falcon, "map %d", ret); + return ret; + } + } + return 0; } void nvkm_falcon_fw_dtor(struct nvkm_falcon_fw *fw) { + nvkm_vmm_put(fw->vmm, &fw->vma); nvkm_vmm_unref(&fw->vmm); nvkm_memory_unref(&fw->inst); nvkm_falcon_fw_dtor_sigs(fw); nvkm_firmware_dtor(&fw->fw); } +static const struct nvkm_firmware_func +nvkm_falcon_fw_dma = { + .type = NVKM_FIRMWARE_IMG_DMA, +}; + static const struct nvkm_firmware_func nvkm_falcon_fw = { .type = NVKM_FIRMWARE_IMG_RAM, @@ -160,7 +190,7 @@ nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *func, const char *name, struct nvkm_device *device, bool dma, const void *src, u32 len, struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw) { - const struct nvkm_firmware_func *type = &nvkm_falcon_fw; + const struct nvkm_firmware_func *type = dma ? &nvkm_falcon_fw_dma : &nvkm_falcon_fw; int ret; fw->func = func; @@ -181,6 +211,7 @@ nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *func, const char *name, const struct nvfw_bin_hdr *hdr; const struct nvfw_hs_header *hshdr; const struct nvfw_hs_load_header *lhdr; + const struct nvfw_bl_desc *desc; u32 loc, sig; int ret; @@ -190,14 +221,31 @@ nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *func, const char *name, hdr = nvfw_bin_hdr(subdev, blob->data); hshdr = nvfw_hs_header(subdev, blob->data + hdr->header_offset); - loc = *(u32 *)(blob->data + hshdr->patch_loc); - sig = *(u32 *)(blob->data + hshdr->patch_sig); ret = nvkm_falcon_fw_ctor(func, name, subdev->device, bl != NULL, blob->data + hdr->data_offset, hdr->data_size, falcon, fw); if (ret) goto done; + /* Earlier FW releases by NVIDIA for Nouveau's use aren't in NVIDIA's + * standard format, and don't have the indirection seen in the 0x10de + * case. + */ + switch (hdr->bin_magic) { + case 0x000010de: + loc = *(u32 *)(blob->data + hshdr->patch_loc); + sig = *(u32 *)(blob->data + hshdr->patch_sig); + break; + case 0x3b1d14f0: + loc = hshdr->patch_loc; + sig = hshdr->patch_sig; + break; + default: + WARN_ON(1); + ret = -EINVAL; + goto done; + } + ret = nvkm_falcon_fw_sign(fw, loc, hshdr->sig_prod_size, blob->data, 1, hshdr->sig_prod_offset + sig, 1, hshdr->sig_dbg_offset + sig); @@ -219,7 +267,26 @@ nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *func, const char *name, fw->dmem_size = lhdr->data_size; fw->dmem_sign = loc - lhdr->data_dma_base; - fw->boot_addr = fw->nmem_base; + if (bl) { + nvkm_firmware_put(blob); + + ret = nvkm_firmware_load_name(subdev, bl, "", ver, &blob); + if (ret) + return ret; + + hdr = nvfw_bin_hdr(subdev, blob->data); + desc = nvfw_bl_desc(subdev, blob->data + hdr->header_offset); + + fw->boot_addr = desc->start_tag << 8; + fw->boot_size = desc->code_size; + fw->boot = kmemdup(blob->data + hdr->data_offset + desc->code_off, + fw->boot_size, GFP_KERNEL); + if (!fw->boot) + ret = -ENOMEM; + } else { + fw->boot_addr = fw->nmem_base; + } + done: if (ret) nvkm_falcon_fw_dtor(fw); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c index 014ca38b8ff3..b61506776105 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c @@ -21,9 +21,26 @@ */ #include "priv.h" +#include #include #include +static void +gm200_flcn_pio_dmem_rd(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len) +{ + while (len >= 4) { + *(u32 *)img = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8)); + img += 4; + len -= 4; + } +} + +static void +gm200_flcn_pio_dmem_rd_init(struct nvkm_falcon *falcon, u8 port, u32 dmem_base) +{ + nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), BIT(25) | dmem_base); +} + static void gm200_flcn_pio_dmem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag) { @@ -46,6 +63,8 @@ gm200_flcn_dmem_pio = { .max = 0x100, .wr_init = gm200_flcn_pio_dmem_wr_init, .wr = gm200_flcn_pio_dmem_wr, + .rd_init = gm200_flcn_pio_dmem_rd_init, + .rd = gm200_flcn_pio_dmem_rd, }; static void @@ -73,6 +92,24 @@ gm200_flcn_imem_pio = { .wr = gm200_flcn_pio_imem_wr, }; +int +gm200_flcn_bind_stat(struct nvkm_falcon *falcon, bool intr) +{ + if (intr && !(nvkm_falcon_rd32(falcon, 0x008) & 0x00000008)) + return -1; + + return (nvkm_falcon_rd32(falcon, 0x0dc) & 0x00007000) >> 12; +} + +void +gm200_flcn_bind_inst(struct nvkm_falcon *falcon, int target, u64 addr) +{ + nvkm_falcon_mask(falcon, 0x604, 0x00000007, 0x00000000); /* DMAIDX_VIRT */ + nvkm_falcon_wr32(falcon, 0x054, (1 << 30) | (target << 28) | (addr >> 12)); + nvkm_falcon_mask(falcon, 0x090, 0x00010000, 0x00010000); + nvkm_falcon_mask(falcon, 0x0a4, 0x00000008, 0x00000008); +} + int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon) { @@ -166,13 +203,60 @@ int gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) { struct nvkm_falcon *falcon = fw->falcon; - int ret; + int target, ret; + + if (fw->inst) { + nvkm_falcon_mask(falcon, 0x048, 0x00000001, 0x00000001); + + switch (nvkm_memory_target(fw->inst)) { + case NVKM_MEM_TARGET_VRAM: target = 0; break; + case NVKM_MEM_TARGET_HOST: target = 2; break; + case NVKM_MEM_TARGET_NCOH: target = 3; break; + default: + WARN_ON(1); + return -EINVAL; + } + + falcon->func->bind_inst(falcon, target, nvkm_memory_addr(fw->inst)); + + if (nvkm_msec(falcon->owner->device, 10, + if (falcon->func->bind_stat(falcon, falcon->func->bind_intr) == 5) + break; + ) < 0) + return -ETIMEDOUT; - if (1) { + nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008); + nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002); + + if (nvkm_msec(falcon->owner->device, 10, + if (falcon->func->bind_stat(falcon, false) == 0) + break; + ) < 0) + return -ETIMEDOUT; + } else { nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080); nvkm_falcon_wr32(falcon, 0x10c, 0x00000000); } + if (fw->boot) { + switch (nvkm_memory_target(&fw->fw.mem.memory)) { + case NVKM_MEM_TARGET_VRAM: target = 4; break; + case NVKM_MEM_TARGET_HOST: target = 5; break; + case NVKM_MEM_TARGET_NCOH: target = 6; break; + default: + WARN_ON(1); + return -EINVAL; + } + + ret = nvkm_falcon_pio_wr(falcon, fw->boot, 0, 0, + IMEM, falcon->code.limit - fw->boot_size, fw->boot_size, + fw->boot_addr >> 8, false); + if (ret) + return ret; + + return fw->func->load_bld(fw); + } + ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->nmem_base_img, fw->nmem_base_img, 0, IMEM, fw->nmem_base, fw->nmem_size, fw->nmem_base >> 8, false); if (ret) diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c index f49918530d0b..c70beacb8d30 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c @@ -21,6 +21,48 @@ */ #include "priv.h" +static void +gp102_flcn_pio_emem_rd(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len) +{ + while (len >= 4) { + *(u32 *)img = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8)); + img += 4; + len -= 4; + } +} + +static void +gp102_flcn_pio_emem_rd_init(struct nvkm_falcon *falcon, u8 port, u32 dmem_base) +{ + nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), BIT(25) | dmem_base); +} + +static void +gp102_flcn_pio_emem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag) +{ + while (len >= 4) { + nvkm_falcon_wr32(falcon, 0xac4 + (port * 8), *(u32 *)img); + img += 4; + len -= 4; + } +} + +static void +gp102_flcn_pio_emem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 emem_base) +{ + nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), BIT(24) | emem_base); +} + +const struct nvkm_falcon_func_pio +gp102_flcn_emem_pio = { + .min = 4, + .max = 0x100, + .wr_init = gp102_flcn_pio_emem_wr_init, + .wr = gp102_flcn_pio_emem_wr, + .rd_init = gp102_flcn_pio_emem_rd_init, + .rd = gp102_flcn_pio_emem_rd, +}; + int gp102_flcn_reset_eng(struct nvkm_falcon *falcon) { diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 04f853151648..16b246fda666 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -68,7 +68,7 @@ nvkm_falcon_msgq_pop(struct nvkm_falcon_msgq *msgq, void *data, u32 size) return -EINVAL; } - nvkm_falcon_read_dmem(falcon, tail, size, 0, data); + nvkm_falcon_pio_rd(falcon, 0, DMEM, tail, data, 0, size); msgq->position += ALIGN(size, QUEUE_ALIGNMENT); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index 9a9e1e6f70a6..dd2ddc54ac60 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -64,44 +64,13 @@ nvkm_falcon_v1_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, nvkm_falcon_wr32(falcon, 0x184 + (port * 16), 0); } -static void -nvkm_falcon_v1_load_emem(struct nvkm_falcon *falcon, void *data, u32 start, - u32 size, u8 port) -{ - u8 rem = size % 4; - int i; - - size -= rem; - - nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), start | (0x1 << 24)); - for (i = 0; i < size / 4; i++) - nvkm_falcon_wr32(falcon, 0xac4 + (port * 8), ((u32 *)data)[i]); - - /* - * If size is not a multiple of 4, mask the last word to ensure garbage - * does not get written - */ - if (rem) { - u32 extra = ((u32 *)data)[i]; - - nvkm_falcon_wr32(falcon, 0xac4 + (port * 8), - extra & (BIT(rem * 8) - 1)); - } -} - void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, u32 size, u8 port) { - const struct nvkm_falcon_func *func = falcon->func; u8 rem = size % 4; int i; - if (func->emem_addr && start >= func->emem_addr) - return nvkm_falcon_v1_load_emem(falcon, data, - start - func->emem_addr, size, - port); - size -= rem; nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 24)); @@ -120,113 +89,6 @@ nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, } } -static void -nvkm_falcon_v1_read_emem(struct nvkm_falcon *falcon, u32 start, u32 size, - u8 port, void *data) -{ - u8 rem = size % 4; - int i; - - size -= rem; - - nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), start | (0x1 << 25)); - for (i = 0; i < size / 4; i++) - ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8)); - - /* - * If size is not a multiple of 4, mask the last word to ensure garbage - * does not get read - */ - if (rem) { - u32 extra = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8)); - - for (i = size; i < size + rem; i++) { - ((u8 *)data)[i] = (u8)(extra & 0xff); - extra >>= 8; - } - } -} - -void -nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, - u8 port, void *data) -{ - const struct nvkm_falcon_func *func = falcon->func; - u8 rem = size % 4; - int i; - - if (func->emem_addr && start >= func->emem_addr) - return nvkm_falcon_v1_read_emem(falcon, start - func->emem_addr, - size, port, data); - - size -= rem; - - nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 25)); - for (i = 0; i < size / 4; i++) - ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8)); - - /* - * If size is not a multiple of 4, mask the last word to ensure garbage - * does not get read - */ - if (rem) { - u32 extra = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8)); - - for (i = size; i < size + rem; i++) { - ((u8 *)data)[i] = (u8)(extra & 0xff); - extra >>= 8; - } - } -} - -void -nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) -{ - const u32 fbif = falcon->func->fbif; - u32 inst_loc; - - /* disable instance block binding */ - if (ctx == NULL) { - nvkm_falcon_wr32(falcon, 0x10c, 0x0); - return; - } - - nvkm_falcon_wr32(falcon, 0x10c, 0x1); - - /* setup apertures - virtual */ - nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_UCODE, 0x4); - nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_VIRT, 0x0); - /* setup apertures - physical */ - nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_VID, 0x4); - nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_COH, 0x5); - nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6); - - /* Set context */ - switch (nvkm_memory_target(ctx)) { - case NVKM_MEM_TARGET_VRAM: inst_loc = 0; break; - case NVKM_MEM_TARGET_HOST: inst_loc = 2; break; - case NVKM_MEM_TARGET_NCOH: inst_loc = 3; break; - default: - WARN_ON(1); - return; - } - - /* Enable context */ - nvkm_falcon_mask(falcon, 0x048, 0x1, 0x1); - nvkm_falcon_wr32(falcon, 0x054, - ((nvkm_memory_addr(ctx) >> 12) & 0xfffffff) | - (inst_loc << 28) | (1 << 30)); - - nvkm_falcon_mask(falcon, 0x090, 0x10000, 0x10000); - nvkm_falcon_mask(falcon, 0x0a4, 0x8, 0x8); -} - -void -nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr) -{ - nvkm_falcon_wr32(falcon, 0x104, start_addr); -} - void nvkm_falcon_v1_start(struct nvkm_falcon *falcon) { @@ -237,32 +99,3 @@ nvkm_falcon_v1_start(struct nvkm_falcon *falcon) else nvkm_falcon_wr32(falcon, 0x100, 0x2); } - -int -nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *falcon, u32 ms) -{ - struct nvkm_device *device = falcon->owner->device; - int ret; - - ret = nvkm_wait_msec(device, ms, falcon->addr + 0x100, 0x10, 0x10); - if (ret < 0) - return ret; - - return 0; -} - -int -nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *falcon, u32 mask) -{ - struct nvkm_device *device = falcon->owner->device; - int ret; - - /* clear interrupt(s) */ - nvkm_falcon_mask(falcon, 0x004, mask, mask); - /* wait until interrupts are cleared */ - ret = nvkm_wait_msec(device, 10, falcon->addr + 0x008, mask, 0x0); - if (ret < 0) - return ret; - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild index 5b9f64a8957f..ce6ece75f07e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild @@ -1,10 +1,10 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/subdev/acr/base.o -nvkm-y += nvkm/subdev/acr/hsfw.o nvkm-y += nvkm/subdev/acr/lsfw.o nvkm-y += nvkm/subdev/acr/gm200.o nvkm-y += nvkm/subdev/acr/gm20b.o nvkm-y += nvkm/subdev/acr/gp102.o nvkm-y += nvkm/subdev/acr/gp108.o +nvkm-y += nvkm/subdev/acr/gv100.o nvkm-y += nvkm/subdev/acr/gp10b.o nvkm-y += nvkm/subdev/acr/tu102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index 882d8d30bd64..795f3a649b12 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -24,43 +24,36 @@ #include #include #include +#include +#include +#include +#include -static struct nvkm_acr_hsf * -nvkm_acr_hsf_find(struct nvkm_acr *acr, const char *name) +static struct nvkm_acr_hsfw * +nvkm_acr_hsfw_find(struct nvkm_acr *acr, const char *name) { - struct nvkm_acr_hsf *hsf; - list_for_each_entry(hsf, &acr->hsf, head) { - if (!strcmp(hsf->name, name)) - return hsf; + struct nvkm_acr_hsfw *hsfw; + + list_for_each_entry(hsfw, &acr->hsfw, head) { + if (!strcmp(hsfw->fw.fw.name, name)) + return hsfw; } + return NULL; } int -nvkm_acr_hsf_boot(struct nvkm_acr *acr, const char *name) +nvkm_acr_hsfw_boot(struct nvkm_acr *acr, const char *name) { struct nvkm_subdev *subdev = &acr->subdev; - struct nvkm_acr_hsf *hsf; - int ret; + struct nvkm_acr_hsfw *hsfw; - hsf = nvkm_acr_hsf_find(acr, name); - if (!hsf) + hsfw = nvkm_acr_hsfw_find(acr, name); + if (!hsfw) return -EINVAL; - nvkm_debug(subdev, "executing %s binary\n", hsf->name); - ret = nvkm_falcon_get(hsf->falcon, subdev); - if (ret) - return ret; - - ret = hsf->func->boot(acr, hsf); - nvkm_falcon_put(hsf->falcon, subdev); - if (ret) { - nvkm_error(subdev, "%s binary failed\n", hsf->name); - return ret; - } - - nvkm_debug(subdev, "%s binary completed successfully\n", hsf->name); - return 0; + return nvkm_falcon_fw_boot(&hsfw->fw, subdev, true, NULL, NULL, + hsfw->boot_mbox0, hsfw->intr_clear); } static struct nvkm_acr_lsf * @@ -87,7 +80,7 @@ nvkm_acr_unload(struct nvkm_acr *acr) acr->rtos = NULL; } - nvkm_acr_hsf_boot(acr, "unload"); + nvkm_acr_hsfw_boot(acr, "unload"); acr->done = false; } } @@ -213,7 +206,7 @@ static void nvkm_acr_cleanup(struct nvkm_acr *acr) { nvkm_acr_lsfw_del_all(acr); - nvkm_acr_hsfw_del_all(acr); + nvkm_firmware_put(acr->wpr_fw); acr->wpr_fw = NULL; } @@ -226,6 +219,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) struct nvkm_acr_hsfw *hsfw; struct nvkm_acr_lsfw *lsfw, *lsft; struct nvkm_acr_lsf *lsf, *rtos; + struct nvkm_falcon *falcon; u32 wpr_size = 0; u64 falcons; int ret, i; @@ -343,8 +337,16 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) /* Load HS firmware blobs into ACR VMM. */ list_for_each_entry(hsfw, &acr->hsfw, head) { - nvkm_debug(subdev, "loading %s fw\n", hsfw->name); - ret = hsfw->func->load(acr, hsfw); + switch (hsfw->falcon_id) { + case NVKM_ACR_HSF_PMU : falcon = &device->pmu->falcon; break; + case NVKM_ACR_HSF_SEC2: falcon = &device->sec2->falcon; break; + case NVKM_ACR_HSF_GSP : falcon = &device->gsp->falcon; break; + default: + WARN_ON(1); + return -EINVAL; + } + + ret = nvkm_falcon_fw_oneinit(&hsfw->fw, falcon, acr->vmm, acr->inst); if (ret) return ret; } @@ -358,15 +360,13 @@ static void * nvkm_acr_dtor(struct nvkm_subdev *subdev) { struct nvkm_acr *acr = nvkm_acr(subdev); - struct nvkm_acr_hsf *hsf, *hst; + struct nvkm_acr_hsfw *hsfw, *hsft; struct nvkm_acr_lsf *lsf, *lst; - list_for_each_entry_safe(hsf, hst, &acr->hsf, head) { - nvkm_vmm_put(acr->vmm, &hsf->vma); - nvkm_memory_unref(&hsf->ucode); - kfree(hsf->imem); - list_del(&hsf->head); - kfree(hsf); + list_for_each_entry_safe(hsfw, hsft, &acr->hsfw, head) { + nvkm_falcon_fw_dtor(&hsfw->fw); + list_del(&hsfw->head); + kfree(hsfw); } nvkm_vmm_part(acr->vmm, acr->inst); @@ -427,7 +427,6 @@ nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device, nvkm_subdev_ctor(&nvkm_acr, device, type, inst, &acr->subdev); INIT_LIST_HEAD(&acr->hsfw); INIT_LIST_HEAD(&acr->lsfw); - INIT_LIST_HEAD(&acr->hsf); INIT_LIST_HEAD(&acr->lsf); fwif = nvkm_firmware_load(&acr->subdev, fwif, "Acr", acr); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c index 82b4c8e1457c..7a11151af3bd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c @@ -46,7 +46,7 @@ gm200_acr_nofw(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) int gm200_acr_init(struct nvkm_acr *acr) { - return nvkm_acr_hsf_boot(acr, "load"); + return nvkm_acr_hsfw_boot(acr, "load"); } void @@ -219,162 +219,50 @@ gm200_acr_wpr_parse(struct nvkm_acr *acr) return 0; } -void -gm200_acr_hsfw_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +int +gm200_acr_hsfw_load_bld(struct nvkm_falcon_fw *fw) { struct flcn_bl_dmem_desc_v1 hsdesc = { .ctx_dma = FALCON_DMAIDX_VIRT, - .code_dma_base = hsf->vma->addr, - .non_sec_code_off = hsf->non_sec_addr, - .non_sec_code_size = hsf->non_sec_size, - .sec_code_off = hsf->sec_addr, - .sec_code_size = hsf->sec_size, + .code_dma_base = fw->vma->addr, + .non_sec_code_off = fw->nmem_base, + .non_sec_code_size = fw->nmem_size, + .sec_code_off = fw->imem_base, + .sec_code_size = fw->imem_size, .code_entry_point = 0, - .data_dma_base = hsf->vma->addr + hsf->data_addr, - .data_size = hsf->data_size, + .data_dma_base = fw->vma->addr + fw->dmem_base_img, + .data_size = fw->dmem_size, }; - flcn_bl_dmem_desc_v1_dump(&acr->subdev, &hsdesc); - - nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0); -} - -int -gm200_acr_hsfw_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf, - u32 intr_clear, u32 mbox0_ok) -{ - struct nvkm_subdev *subdev = &acr->subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_falcon *falcon = hsf->falcon; - u32 mbox0, mbox1; - int ret; - - /* Reset falcon. */ - nvkm_falcon_reset(falcon); - nvkm_falcon_bind_context(falcon, acr->inst); - - /* Load bootloader into IMEM. */ - nvkm_falcon_load_imem(falcon, hsf->imem, - falcon->code.limit - hsf->imem_size, - hsf->imem_size, - hsf->imem_tag, - 0, false); - - /* Load bootloader data into DMEM. */ - hsf->func->bld(acr, hsf); - - /* Boot the falcon. */ - nvkm_mc_intr_mask(device, falcon->owner->type, falcon->owner->inst, false); + flcn_bl_dmem_desc_v1_dump(fw->falcon->user, &hsdesc); - nvkm_falcon_wr32(falcon, 0x040, 0xdeada5a5); - nvkm_falcon_set_start_addr(falcon, hsf->imem_tag << 8); - nvkm_falcon_start(falcon); - ret = nvkm_falcon_wait_for_halt(falcon, 100); - if (ret) - return ret; - - /* Check for successful completion. */ - mbox0 = nvkm_falcon_rd32(falcon, 0x040); - mbox1 = nvkm_falcon_rd32(falcon, 0x044); - nvkm_debug(subdev, "mailbox %08x %08x\n", mbox0, mbox1); - if (mbox0 && mbox0 != mbox0_ok) - return -EIO; - - nvkm_falcon_clear_interrupt(falcon, intr_clear); - nvkm_mc_intr_mask(device, falcon->owner->type, falcon->owner->inst, true); - return ret; + return nvkm_falcon_pio_wr(fw->falcon, (u8 *)&hsdesc, 0, 0, DMEM, 0, sizeof(hsdesc), 0, 0); } int -gm200_acr_hsfw_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw, - struct nvkm_falcon *falcon) +gm200_acr_hsfw_ctor(struct nvkm_acr *acr, const char *bl, const char *fw, const char *name, int ver, + const struct nvkm_acr_hsf_fwif *fwif) { - struct nvkm_subdev *subdev = &acr->subdev; - struct nvkm_acr_hsf *hsf; - int ret; - - /* Patch the appropriate signature (production/debug) into the FW - * image, as determined by the mode the falcon is in. - */ - ret = nvkm_falcon_get(falcon, subdev); - if (ret) - return ret; - - if (hsfw->sig.patch_loc) { - if (!falcon->debug) { - nvkm_debug(subdev, "patching production signature\n"); - memcpy(hsfw->image + hsfw->sig.patch_loc, - hsfw->sig.prod.data, - hsfw->sig.prod.size); - } else { - nvkm_debug(subdev, "patching debug signature\n"); - memcpy(hsfw->image + hsfw->sig.patch_loc, - hsfw->sig.dbg.data, - hsfw->sig.dbg.size); - } - } - - nvkm_falcon_put(falcon, subdev); + struct nvkm_acr_hsfw *hsfw; - if (!(hsf = kzalloc(sizeof(*hsf), GFP_KERNEL))) + if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL))) return -ENOMEM; - hsf->func = hsfw->func; - hsf->name = hsfw->name; - list_add_tail(&hsf->head, &acr->hsf); - - hsf->imem_size = hsfw->imem_size; - hsf->imem_tag = hsfw->imem_tag; - hsf->imem = kmemdup(hsfw->imem, hsfw->imem_size, GFP_KERNEL); - if (!hsf->imem) - return -ENOMEM; - - hsf->non_sec_addr = hsfw->non_sec_addr; - hsf->non_sec_size = hsfw->non_sec_size; - hsf->sec_addr = hsfw->sec_addr; - hsf->sec_size = hsfw->sec_size; - hsf->data_addr = hsfw->data_addr; - hsf->data_size = hsfw->data_size; - - /* Make the FW image accessible to the HS bootloader. */ - ret = nvkm_memory_new(subdev->device, NVKM_MEM_TARGET_INST, - hsfw->image_size, 0x1000, false, &hsf->ucode); - if (ret) - return ret; - - nvkm_kmap(hsf->ucode); - nvkm_wobj(hsf->ucode, 0, hsfw->image, hsfw->image_size); - nvkm_done(hsf->ucode); - - ret = nvkm_vmm_get(acr->vmm, 12, nvkm_memory_size(hsf->ucode), - &hsf->vma); - if (ret) - return ret; - - ret = nvkm_memory_map(hsf->ucode, 0, acr->vmm, hsf->vma, NULL, 0); - if (ret) - return ret; - - hsf->falcon = falcon; - return 0; -} -int -gm200_acr_unload_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) -{ - return gm200_acr_hsfw_boot(acr, hsf, 0, 0x1d); -} + hsfw->falcon_id = fwif->falcon_id; + hsfw->boot_mbox0 = fwif->boot_mbox0; + hsfw->intr_clear = fwif->intr_clear; + list_add_tail(&hsfw->head, &acr->hsfw); -int -gm200_acr_unload_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) -{ - return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon); + return nvkm_falcon_fw_ctor_hs(fwif->func, name, &acr->subdev, bl, fw, ver, NULL, &hsfw->fw); } -const struct nvkm_acr_hsf_func +const struct nvkm_falcon_fw_func gm200_acr_unload_0 = { - .load = gm200_acr_unload_load, - .boot = gm200_acr_unload_boot, - .bld = gm200_acr_hsfw_bld, + .signature = gm200_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .load = gm200_flcn_fw_load, + .load_bld = gm200_acr_hsfw_load_bld, + .boot = gm200_flcn_fw_boot, }; MODULE_FIRMWARE("nvidia/gm200/acr/ucode_unload.bin"); @@ -384,20 +272,15 @@ MODULE_FIRMWARE("nvidia/gp100/acr/ucode_unload.bin"); static const struct nvkm_acr_hsf_fwif gm200_acr_unload_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gm200_acr_unload_0 }, + { 0, gm200_acr_hsfw_ctor, &gm200_acr_unload_0, NVKM_ACR_HSF_PMU, 0, 0x00000010 }, {} }; -int -gm200_acr_load_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) -{ - return gm200_acr_hsfw_boot(acr, hsf, 0x10, 0); -} - static int -gm200_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) +gm200_acr_load_setup(struct nvkm_falcon_fw *fw) { - struct flcn_acr_desc *desc = (void *)&hsfw->image[hsfw->data_addr]; + struct flcn_acr_desc *desc = (void *)&fw->fw.img[fw->dmem_base_img]; + struct nvkm_acr *acr = fw->falcon->owner->device->acr; desc->wpr_region_id = 1; desc->regions.no_regions = 2; @@ -408,15 +291,17 @@ gm200_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) desc->regions.region_props[0].write_mask = 0xc; desc->regions.region_props[0].client_mask = 0x2; flcn_acr_desc_dump(&acr->subdev, desc); - - return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon); + return 0; } -static const struct nvkm_acr_hsf_func +static const struct nvkm_falcon_fw_func gm200_acr_load_0 = { - .load = gm200_acr_load_load, - .boot = gm200_acr_load_boot, - .bld = gm200_acr_hsfw_bld, + .signature = gm200_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .setup = gm200_acr_load_setup, + .load = gm200_flcn_fw_load, + .load_bld = gm200_acr_hsfw_load_bld, + .boot = gm200_flcn_fw_boot, }; MODULE_FIRMWARE("nvidia/gm200/acr/bl.bin"); @@ -433,7 +318,7 @@ MODULE_FIRMWARE("nvidia/gp100/acr/ucode_load.bin"); static const struct nvkm_acr_hsf_fwif gm200_acr_load_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gm200_acr_load_0 }, + { 0, gm200_acr_hsfw_ctor, &gm200_acr_load_0, NVKM_ACR_HSF_PMU, 0, 0x00000010 }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c index 54e996f2f630..ef5fb79128b1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c @@ -45,43 +45,47 @@ gm20b_acr_wpr_alloc(struct nvkm_acr *acr, u32 wpr_size) wpr_size, 0, true, &acr->wpr); } -static void -gm20b_acr_load_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +static int +gm20b_acr_hsfw_load_bld(struct nvkm_falcon_fw *fw) { struct flcn_bl_dmem_desc hsdesc = { .ctx_dma = FALCON_DMAIDX_VIRT, - .code_dma_base = hsf->vma->addr >> 8, - .non_sec_code_off = hsf->non_sec_addr, - .non_sec_code_size = hsf->non_sec_size, - .sec_code_off = hsf->sec_addr, - .sec_code_size = hsf->sec_size, + .code_dma_base = fw->vma->addr >> 8, + .non_sec_code_off = fw->nmem_base, + .non_sec_code_size = fw->nmem_size, + .sec_code_off = fw->imem_base, + .sec_code_size = fw->imem_size, .code_entry_point = 0, - .data_dma_base = (hsf->vma->addr + hsf->data_addr) >> 8, - .data_size = hsf->data_size, + .data_dma_base = (fw->vma->addr + fw->dmem_base_img) >> 8, + .data_size = fw->dmem_size, }; - flcn_bl_dmem_desc_dump(&acr->subdev, &hsdesc); + flcn_bl_dmem_desc_dump(fw->falcon->user, &hsdesc); - nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0); + return nvkm_falcon_pio_wr(fw->falcon, (u8 *)&hsdesc, 0, 0, DMEM, 0, sizeof(hsdesc), 0, 0); } + static int -gm20b_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) +gm20b_acr_load_setup(struct nvkm_falcon_fw *fw) { - struct flcn_acr_desc *desc = (void *)&hsfw->image[hsfw->data_addr]; + struct flcn_acr_desc *desc = (void *)&fw->fw.img[fw->dmem_base_img]; + struct nvkm_acr *acr = fw->falcon->owner->device->acr; desc->ucode_blob_base = nvkm_memory_addr(acr->wpr); desc->ucode_blob_size = nvkm_memory_size(acr->wpr); flcn_acr_desc_dump(&acr->subdev, desc); - - return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon); + return 0; } -const struct nvkm_acr_hsf_func +const struct nvkm_falcon_fw_func gm20b_acr_load_0 = { - .load = gm20b_acr_load_load, - .boot = gm200_acr_load_boot, - .bld = gm20b_acr_load_bld, + .signature = gm200_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .setup = gm20b_acr_load_setup, + .load = gm200_flcn_fw_load, + .load_bld = gm20b_acr_hsfw_load_bld, + .boot = gm200_flcn_fw_boot, }; #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) @@ -91,7 +95,7 @@ MODULE_FIRMWARE("nvidia/gm20b/acr/ucode_load.bin"); static const struct nvkm_acr_hsf_fwif gm20b_acr_load_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gm20b_acr_load_0 }, + { 0, gm200_acr_hsfw_ctor, &gm20b_acr_load_0, NVKM_ACR_HSF_PMU, 0, 0x10 }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c index fd97a935a380..f4c2d3729feb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c @@ -187,14 +187,15 @@ MODULE_FIRMWARE("nvidia/gp107/acr/ucode_unload.bin"); static const struct nvkm_acr_hsf_fwif gp102_acr_unload_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gm200_acr_unload_0 }, + { 0, gm200_acr_hsfw_ctor, &gm200_acr_unload_0, NVKM_ACR_HSF_PMU, 0x1d, 0x00000010 }, {} }; int -gp102_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) +gp102_acr_load_setup(struct nvkm_falcon_fw *fw) { - struct flcn_acr_desc_v1 *desc = (void *)&hsfw->image[hsfw->data_addr]; + struct flcn_acr_desc_v1 *desc = (void *)&fw->fw.img[fw->dmem_base_img]; + struct nvkm_acr *acr = fw->falcon->owner->device->acr; desc->wpr_region_id = 1; desc->regions.no_regions = 2; @@ -204,19 +205,19 @@ gp102_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) desc->regions.region_props[0].read_mask = 0xf; desc->regions.region_props[0].write_mask = 0xc; desc->regions.region_props[0].client_mask = 0x2; - desc->regions.region_props[0].shadow_mem_start_addr = - acr->shadow_start >> 8; + desc->regions.region_props[0].shadow_mem_start_addr = acr->shadow_start >> 8; flcn_acr_desc_v1_dump(&acr->subdev, desc); - - return gm200_acr_hsfw_load(acr, hsfw, - &acr->subdev.device->sec2->falcon); + return 0; } -static const struct nvkm_acr_hsf_func +static const struct nvkm_falcon_fw_func gp102_acr_load_0 = { - .load = gp102_acr_load_load, - .boot = gm200_acr_load_boot, - .bld = gm200_acr_hsfw_bld, + .signature = gm200_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .setup = gp102_acr_load_setup, + .load = gm200_flcn_fw_load, + .load_bld = gm200_acr_hsfw_load_bld, + .boot = gm200_flcn_fw_boot, }; MODULE_FIRMWARE("nvidia/gp102/acr/bl.bin"); @@ -233,7 +234,7 @@ MODULE_FIRMWARE("nvidia/gp107/acr/ucode_load.bin"); static const struct nvkm_acr_hsf_fwif gp102_acr_load_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gp102_acr_load_0 }, + { 0, gm200_acr_hsfw_ctor, &gp102_acr_load_0, NVKM_ACR_HSF_SEC2, 0, 0x00000010 }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c index 373d638a2177..6ab9d4959c17 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c @@ -25,63 +25,62 @@ #include -void -gp108_acr_hsfw_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +int +gp108_acr_hsfw_load_bld(struct nvkm_falcon_fw *fw) { struct flcn_bl_dmem_desc_v2 hsdesc = { .ctx_dma = FALCON_DMAIDX_VIRT, - .code_dma_base = hsf->vma->addr, - .non_sec_code_off = hsf->non_sec_addr, - .non_sec_code_size = hsf->non_sec_size, - .sec_code_off = hsf->sec_addr, - .sec_code_size = hsf->sec_size, + .code_dma_base = fw->vma->addr, + .non_sec_code_off = fw->nmem_base, + .non_sec_code_size = fw->nmem_size, + .sec_code_off = fw->imem_base, + .sec_code_size = fw->imem_size, .code_entry_point = 0, - .data_dma_base = hsf->vma->addr + hsf->data_addr, - .data_size = hsf->data_size, + .data_dma_base = fw->vma->addr + fw->dmem_base_img, + .data_size = fw->dmem_size, .argc = 0, .argv = 0, }; - flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hsdesc); + flcn_bl_dmem_desc_v2_dump(fw->falcon->user, &hsdesc); - nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0); + return nvkm_falcon_pio_wr(fw->falcon, (u8 *)&hsdesc, 0, 0, DMEM, 0, sizeof(hsdesc), 0, 0); } -const struct nvkm_acr_hsf_func -gp108_acr_unload_0 = { - .load = gm200_acr_unload_load, - .boot = gm200_acr_unload_boot, - .bld = gp108_acr_hsfw_bld, +const struct nvkm_falcon_fw_func +gp108_acr_hsfw_0 = { + .signature = gm200_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .load = gm200_flcn_fw_load, + .load_bld = gp108_acr_hsfw_load_bld, + .boot = gm200_flcn_fw_boot, }; MODULE_FIRMWARE("nvidia/gp108/acr/unload_bl.bin"); MODULE_FIRMWARE("nvidia/gp108/acr/ucode_unload.bin"); -MODULE_FIRMWARE("nvidia/gv100/acr/unload_bl.bin"); -MODULE_FIRMWARE("nvidia/gv100/acr/ucode_unload.bin"); - static const struct nvkm_acr_hsf_fwif gp108_acr_unload_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 }, + { 0, gm200_acr_hsfw_ctor, &gp108_acr_hsfw_0, NVKM_ACR_HSF_PMU, 0x1d, 0x00000010 }, {} }; -static const struct nvkm_acr_hsf_func +const struct nvkm_falcon_fw_func gp108_acr_load_0 = { - .load = gp102_acr_load_load, - .boot = gm200_acr_load_boot, - .bld = gp108_acr_hsfw_bld, + .signature = gm200_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .setup = gp102_acr_load_setup, + .load = gm200_flcn_fw_load, + .load_bld = gp108_acr_hsfw_load_bld, + .boot = gm200_flcn_fw_boot, }; MODULE_FIRMWARE("nvidia/gp108/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gp108/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gv100/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gv100/acr/ucode_load.bin"); - static const struct nvkm_acr_hsf_fwif gp108_acr_load_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gp108_acr_load_0 }, + { 0, gm200_acr_hsfw_ctor, &gp108_acr_load_0, NVKM_ACR_HSF_SEC2, 0, 0x00000010 }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c index f03ba028867b..a3422ab6deab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c @@ -28,7 +28,7 @@ MODULE_FIRMWARE("nvidia/gp10b/acr/ucode_load.bin"); static const struct nvkm_acr_hsf_fwif gp10b_acr_load_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gm20b_acr_load_0 }, + { 0, gm200_acr_hsfw_ctor, &gm20b_acr_load_0, NVKM_ACR_HSF_PMU, 0, 0x00000010 }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c new file mode 100644 index 000000000000..4c5ca6b40027 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c @@ -0,0 +1,67 @@ +/* + * Copyright 2022 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +MODULE_FIRMWARE("nvidia/gv100/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/gv100/acr/ucode_unload.bin"); + +static const struct nvkm_acr_hsf_fwif +gv100_acr_unload_fwif[] = { + { 0, gm200_acr_hsfw_ctor, &gp108_acr_hsfw_0, NVKM_ACR_HSF_PMU, 0, 0x00000000 }, + {} +}; + +MODULE_FIRMWARE("nvidia/gv100/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gv100/acr/ucode_load.bin"); + +static const struct nvkm_acr_hsf_fwif +gv100_acr_load_fwif[] = { + { 0, gm200_acr_hsfw_ctor, &gp108_acr_load_0, NVKM_ACR_HSF_SEC2, 0, 0x00000010 }, + {} +}; + +static const struct nvkm_acr_func +gv100_acr = { + .load = gv100_acr_load_fwif, + .unload = gv100_acr_unload_fwif, + .wpr_parse = gp102_acr_wpr_parse, + .wpr_layout = gp102_acr_wpr_layout, + .wpr_alloc = gp102_acr_wpr_alloc, + .wpr_build = gp102_acr_wpr_build, + .wpr_patch = gp102_acr_wpr_patch, + .wpr_check = gm200_acr_wpr_check, + .init = gm200_acr_init, +}; + +static const struct nvkm_acr_fwif +gv100_acr_fwif[] = { + { 0, gp102_acr_load, &gv100_acr }, + { -1, gm200_acr_nofw, &gm200_acr }, + {} +}; + +int +gv100_acr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_acr **pacr) +{ + return nvkm_acr_new_(gv100_acr_fwif, device, type, inst, pacr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c deleted file mode 100644 index a6ea89a5d51a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2019 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "priv.h" - -#include - -#include -#include - -static void -nvkm_acr_hsfw_del(struct nvkm_acr_hsfw *hsfw) -{ - list_del(&hsfw->head); - kfree(hsfw->imem); - kfree(hsfw->image); - kfree(hsfw->sig.prod.data); - kfree(hsfw->sig.dbg.data); - kfree(hsfw); -} - -void -nvkm_acr_hsfw_del_all(struct nvkm_acr *acr) -{ - struct nvkm_acr_hsfw *hsfw, *hsft; - list_for_each_entry_safe(hsfw, hsft, &acr->hsfw, head) { - nvkm_acr_hsfw_del(hsfw); - } -} - -static int -nvkm_acr_hsfw_load_image(struct nvkm_acr *acr, const char *name, int ver, - struct nvkm_acr_hsfw *hsfw) -{ - struct nvkm_subdev *subdev = &acr->subdev; - const struct firmware *fw; - const struct nvfw_bin_hdr *hdr; - const struct nvfw_hs_header *fwhdr; - const struct nvfw_hs_load_header *lhdr; - u32 loc, sig; - int ret; - - ret = nvkm_firmware_get(subdev, name, ver, &fw); - if (ret < 0) - return ret; - - hdr = nvfw_bin_hdr(subdev, fw->data); - fwhdr = nvfw_hs_header(subdev, fw->data + hdr->header_offset); - - /* Earlier FW releases by NVIDIA for Nouveau's use aren't in NVIDIA's - * standard format, and don't have the indirection seen in the 0x10de - * case. - */ - switch (hdr->bin_magic) { - case 0x000010de: - loc = *(u32 *)(fw->data + fwhdr->patch_loc); - sig = *(u32 *)(fw->data + fwhdr->patch_sig); - break; - case 0x3b1d14f0: - loc = fwhdr->patch_loc; - sig = fwhdr->patch_sig; - break; - default: - ret = -EINVAL; - goto done; - } - - lhdr = nvfw_hs_load_header(subdev, fw->data + fwhdr->hdr_offset); - - if (!(hsfw->image = kmalloc(hdr->data_size, GFP_KERNEL))) { - ret = -ENOMEM; - goto done; - } - - memcpy(hsfw->image, fw->data + hdr->data_offset, hdr->data_size); - hsfw->image_size = hdr->data_size; - hsfw->non_sec_addr = lhdr->non_sec_code_off; - hsfw->non_sec_size = lhdr->non_sec_code_size; - hsfw->sec_addr = lhdr->apps[0]; - hsfw->sec_size = lhdr->apps[lhdr->num_apps]; - hsfw->data_addr = lhdr->data_dma_base; - hsfw->data_size = lhdr->data_size; - - hsfw->sig.prod.size = fwhdr->sig_prod_size; - hsfw->sig.prod.data = kmemdup(fw->data + fwhdr->sig_prod_offset + sig, - hsfw->sig.prod.size, GFP_KERNEL); - if (!hsfw->sig.prod.data) { - ret = -ENOMEM; - goto done; - } - - hsfw->sig.dbg.size = fwhdr->sig_dbg_size; - hsfw->sig.dbg.data = kmemdup(fw->data + fwhdr->sig_dbg_offset + sig, - hsfw->sig.dbg.size, GFP_KERNEL); - if (!hsfw->sig.dbg.data) { - ret = -ENOMEM; - goto done; - } - - hsfw->sig.patch_loc = loc; -done: - nvkm_firmware_put(fw); - return ret; -} - -static int -nvkm_acr_hsfw_load_bl(struct nvkm_acr *acr, const char *name, int ver, - struct nvkm_acr_hsfw *hsfw) -{ - struct nvkm_subdev *subdev = &acr->subdev; - const struct nvfw_bin_hdr *hdr; - const struct nvfw_bl_desc *desc; - const struct firmware *fw; - u8 *data; - int ret; - - ret = nvkm_firmware_get(subdev, name, ver, &fw); - if (ret) - return ret; - - hdr = nvfw_bin_hdr(subdev, fw->data); - desc = nvfw_bl_desc(subdev, fw->data + hdr->header_offset); - data = (void *)fw->data + hdr->data_offset; - - hsfw->imem_size = desc->code_size; - hsfw->imem_tag = desc->start_tag; - hsfw->imem = kmemdup(data + desc->code_off, desc->code_size, GFP_KERNEL); - nvkm_firmware_put(fw); - if (!hsfw->imem) - return -ENOMEM; - else - return 0; -} - -int -nvkm_acr_hsfw_load(struct nvkm_acr *acr, const char *bl, const char *fw, - const char *name, int version, - const struct nvkm_acr_hsf_fwif *fwif) -{ - struct nvkm_acr_hsfw *hsfw; - int ret; - - if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL))) - return -ENOMEM; - - hsfw->func = fwif->func; - hsfw->name = name; - list_add_tail(&hsfw->head, &acr->hsfw); - - ret = nvkm_acr_hsfw_load_bl(acr, bl, version, hsfw); - if (ret) - goto done; - - ret = nvkm_acr_hsfw_load_image(acr, fw, version, hsfw); -done: - if (ret) - nvkm_acr_hsfw_del(hsfw); - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h index c30b841c9d35..66a764e24bc6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h @@ -51,93 +51,50 @@ int gp102_acr_wpr_build_lsb(struct nvkm_acr *, struct nvkm_acr_lsfw *); void gp102_acr_wpr_patch(struct nvkm_acr *, s64); struct nvkm_acr_hsfw { - const struct nvkm_acr_hsf_func *func; - const char *name; - struct list_head head; + struct nvkm_falcon_fw fw; + + enum nvkm_acr_hsf_id { + NVKM_ACR_HSF_PMU, + NVKM_ACR_HSF_SEC2, + NVKM_ACR_HSF_GSP, + } falcon_id; + u32 boot_mbox0; + u32 intr_clear; - u32 imem_size; - u32 imem_tag; - u32 *imem; - - u8 *image; - u32 image_size; - u32 non_sec_addr; - u32 non_sec_size; - u32 sec_addr; - u32 sec_size; - u32 data_addr; - u32 data_size; - - struct { - struct { - void *data; - u32 size; - } prod, dbg; - u32 patch_loc; - } sig; + struct list_head head; }; +int nvkm_acr_hsfw_boot(struct nvkm_acr *, const char *name); + struct nvkm_acr_hsf_fwif { int version; int (*load)(struct nvkm_acr *, const char *bl, const char *fw, const char *name, int version, const struct nvkm_acr_hsf_fwif *); - const struct nvkm_acr_hsf_func *func; -}; - -int nvkm_acr_hsfw_load(struct nvkm_acr *, const char *, const char *, - const char *, int, const struct nvkm_acr_hsf_fwif *); -void nvkm_acr_hsfw_del_all(struct nvkm_acr *); - -struct nvkm_acr_hsf { - const struct nvkm_acr_hsf_func *func; - const char *name; - struct list_head head; - - u32 imem_size; - u32 imem_tag; - u32 *imem; - - u32 non_sec_addr; - u32 non_sec_size; - u32 sec_addr; - u32 sec_size; - u32 data_addr; - u32 data_size; - - struct nvkm_memory *ucode; - struct nvkm_vma *vma; - struct nvkm_falcon *falcon; -}; + const struct nvkm_falcon_fw_func *func; -struct nvkm_acr_hsf_func { - int (*load)(struct nvkm_acr *, struct nvkm_acr_hsfw *); - int (*boot)(struct nvkm_acr *, struct nvkm_acr_hsf *); - void (*bld)(struct nvkm_acr *, struct nvkm_acr_hsf *); + enum nvkm_acr_hsf_id falcon_id; + u32 boot_mbox0; + u32 intr_clear; }; -int gm200_acr_hsfw_load(struct nvkm_acr *, struct nvkm_acr_hsfw *, - struct nvkm_falcon *); -int gm200_acr_hsfw_boot(struct nvkm_acr *, struct nvkm_acr_hsf *, - u32 clear_intr, u32 mbox0_ok); -int gm200_acr_load_boot(struct nvkm_acr *, struct nvkm_acr_hsf *); +int gm200_acr_hsfw_ctor(struct nvkm_acr *, const char *, const char *, const char *, int, + const struct nvkm_acr_hsf_fwif *); +int gm200_acr_hsfw_load_bld(struct nvkm_falcon_fw *); +extern const struct nvkm_falcon_fw_func gm200_acr_unload_0; -extern const struct nvkm_acr_hsf_func gm200_acr_unload_0; -int gm200_acr_unload_load(struct nvkm_acr *, struct nvkm_acr_hsfw *); -int gm200_acr_unload_boot(struct nvkm_acr *, struct nvkm_acr_hsf *); -void gm200_acr_hsfw_bld(struct nvkm_acr *, struct nvkm_acr_hsf *); +extern const struct nvkm_falcon_fw_func gm20b_acr_load_0; -extern const struct nvkm_acr_hsf_func gm20b_acr_load_0; +int gp102_acr_load_setup(struct nvkm_falcon_fw *); -int gp102_acr_load_load(struct nvkm_acr *, struct nvkm_acr_hsfw *); +extern const struct nvkm_falcon_fw_func gp108_acr_load_0; -extern const struct nvkm_acr_hsf_func gp108_acr_unload_0; -void gp108_acr_hsfw_bld(struct nvkm_acr *, struct nvkm_acr_hsf *); +extern const struct nvkm_falcon_fw_func gp108_acr_hsfw_0; +int gp108_acr_hsfw_load_bld(struct nvkm_falcon_fw *); int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); -int nvkm_acr_hsf_boot(struct nvkm_acr *, const char *name); struct nvkm_acr_lsf { const struct nvkm_acr_lsf_func *func; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c index 05a87e77525f..ad45f5cb452b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c @@ -32,11 +32,11 @@ static int tu102_acr_init(struct nvkm_acr *acr) { - int ret = nvkm_acr_hsf_boot(acr, "AHESASC"); + int ret = nvkm_acr_hsfw_boot(acr, "AHESASC"); if (ret) return ret; - return nvkm_acr_hsf_boot(acr, "ASB"); + return nvkm_acr_hsfw_boot(acr, "ASB"); } static int @@ -84,12 +84,6 @@ tu102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos) return 0; } -static int -tu102_acr_hsfw_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) -{ - return gm200_acr_hsfw_boot(acr, hsf, 0, 0); -} - static int tu102_acr_hsfw_nofw(struct nvkm_acr *acr, const char *bl, const char *fw, const char *name, int version, @@ -115,24 +109,11 @@ MODULE_FIRMWARE("nvidia/tu117/acr/ucode_unload.bin"); static const struct nvkm_acr_hsf_fwif tu102_acr_unload_fwif[] = { - { 0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 }, + { 0, gm200_acr_hsfw_ctor, &gp108_acr_hsfw_0, NVKM_ACR_HSF_PMU, 0, 0x00000000 }, { -1, tu102_acr_hsfw_nofw }, {} }; -static int -tu102_acr_asb_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) -{ - return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->gsp->falcon); -} - -static const struct nvkm_acr_hsf_func -tu102_acr_asb_0 = { - .load = tu102_acr_asb_load, - .boot = tu102_acr_hsfw_boot, - .bld = gp108_acr_hsfw_bld, -}; - MODULE_FIRMWARE("nvidia/tu102/acr/ucode_asb.bin"); MODULE_FIRMWARE("nvidia/tu104/acr/ucode_asb.bin"); MODULE_FIRMWARE("nvidia/tu106/acr/ucode_asb.bin"); @@ -141,18 +122,11 @@ MODULE_FIRMWARE("nvidia/tu117/acr/ucode_asb.bin"); static const struct nvkm_acr_hsf_fwif tu102_acr_asb_fwif[] = { - { 0, nvkm_acr_hsfw_load, &tu102_acr_asb_0 }, + { 0, gm200_acr_hsfw_ctor, &gp108_acr_hsfw_0, NVKM_ACR_HSF_GSP, 0, 0x00000000 }, { -1, tu102_acr_hsfw_nofw }, {} }; -static const struct nvkm_acr_hsf_func -tu102_acr_ahesasc_0 = { - .load = gp102_acr_load_load, - .boot = tu102_acr_hsfw_boot, - .bld = gp108_acr_hsfw_bld, -}; - MODULE_FIRMWARE("nvidia/tu102/acr/bl.bin"); MODULE_FIRMWARE("nvidia/tu102/acr/ucode_ahesasc.bin"); @@ -170,7 +144,7 @@ MODULE_FIRMWARE("nvidia/tu117/acr/ucode_ahesasc.bin"); static const struct nvkm_acr_hsf_fwif tu102_acr_ahesasc_fwif[] = { - { 0, nvkm_acr_hsfw_load, &tu102_acr_ahesasc_0 }, + { 0, gm200_acr_hsfw_ctor, &gp108_acr_load_0, NVKM_ACR_HSF_SEC2, 0, 0x00000000 }, { -1, tu102_acr_hsfw_nofw }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c index a247e57f7d9f..da6a809cd317 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c @@ -27,15 +27,11 @@ gv100_gsp_flcn = { .enable = gm200_flcn_enable, .reset_eng = gp102_flcn_reset_eng, .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, - .fbif = 0x600, - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = gp102_sec2_flcn_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, - .start = nvkm_falcon_v1_start, + .bind_inst = gm200_flcn_bind_inst, + .bind_stat = gm200_flcn_bind_stat, + .bind_intr = true, + .imem_pio = &gm200_flcn_imem_pio, + .dmem_pio = &gm200_flcn_dmem_pio, }; static const struct nvkm_gsp_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c index 0bd854092da9..7359991f94c2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c @@ -23,6 +23,25 @@ */ #include "priv.h" +static int +gm200_pmu_flcn_bind_stat(struct nvkm_falcon *falcon, bool intr) +{ + nvkm_falcon_wr32(falcon, 0x200, 0x0000030e); + return (nvkm_falcon_rd32(falcon, 0x20c) & 0x00007000) >> 12; +} + +void +gm200_pmu_flcn_bind_inst(struct nvkm_falcon *falcon, int target, u64 addr) +{ + nvkm_falcon_wr32(falcon, 0xe00, 4); /* DMAIDX_UCODE */ + nvkm_falcon_wr32(falcon, 0xe04, 0); /* DMAIDX_VIRT */ + nvkm_falcon_wr32(falcon, 0xe08, 4); /* DMAIDX_PHYS_VID */ + nvkm_falcon_wr32(falcon, 0xe0c, 5); /* DMAIDX_PHYS_SYS_COH */ + nvkm_falcon_wr32(falcon, 0xe10, 6); /* DMAIDX_PHYS_SYS_NCOH */ + nvkm_falcon_mask(falcon, 0x090, 0x00010000, 0x00010000); + nvkm_falcon_wr32(falcon, 0x480, (1 << 30) | (target << 28) | (addr >> 12)); +} + const struct nvkm_falcon_func gm200_pmu_flcn = { .disable = gm200_flcn_disable, @@ -30,14 +49,10 @@ gm200_pmu_flcn = { .reset_pmc = true, .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0xc08, - .fbif = 0xe00, - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, + .bind_inst = gm200_pmu_flcn_bind_inst, + .bind_stat = gm200_pmu_flcn_bind_stat, + .imem_pio = &gm200_flcn_imem_pio, + .dmem_pio = &gm200_flcn_dmem_pio, .start = nvkm_falcon_v1_start, .cmdq = { 0x4a0, 0x4b0, 4 }, .msgq = { 0x4c8, 0x4cc, 0 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c index 47c7412f86e8..cd3148360996 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c @@ -30,14 +30,10 @@ gp102_pmu_flcn = { .reset_eng = gp102_flcn_reset_eng, .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, .debug = 0xc08, - .fbif = 0xe00, - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, + .bind_inst = gm200_pmu_flcn_bind_inst, + .bind_stat = gm200_flcn_bind_stat, + .imem_pio = &gm200_flcn_imem_pio, + .dmem_pio = &gm200_flcn_dmem_pio, .start = nvkm_falcon_v1_start, .cmdq = { 0x4a0, 0x4b0, 4 }, .msgq = { 0x4c8, 0x4cc, 0 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 75ede265a52c..2d0a8fa6f196 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -46,6 +46,7 @@ void gp102_pmu_reset(struct nvkm_pmu *pmu); void gk110_pmu_pgob(struct nvkm_pmu *, bool); extern const struct nvkm_falcon_func gm200_pmu_flcn; +void gm200_pmu_flcn_bind_inst(struct nvkm_falcon *, int, u64); extern const struct nvkm_pmu_func gm20b_pmu; void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64); -- cgit v1.2.3 From d2922879116ca753e454fecde531d509eb0af69f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:47:53 +1000 Subject: drm/nouveau/sec2: dump tracepc info on halt - useful to distinguish between different issues. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 5 +++++ drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 15 +++++++++++++++ 3 files changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 4c8b668bacb4..4868d2cb796f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -47,6 +47,7 @@ void gm200_flcn_bind_inst(struct nvkm_falcon *, int, u64); int gm200_flcn_bind_stat(struct nvkm_falcon *, bool); extern const struct nvkm_falcon_func_pio gm200_flcn_imem_pio; extern const struct nvkm_falcon_func_pio gm200_flcn_dmem_pio; +void gm200_flcn_tracepc(struct nvkm_falcon *); int gp102_flcn_reset_eng(struct nvkm_falcon *); extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index a5c987ce58ed..b1e74bc49d72 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -178,6 +178,11 @@ gp102_sec2_intr(struct nvkm_inth *inth) } if (intr & 0x00000010) { + if (atomic_read(&sec2->running)) { + FLCN_ERR(falcon, "halted"); + gm200_flcn_tracepc(falcon); + } + nvkm_falcon_wr32(falcon, 0x004, 0x00000010); intr &= ~0x00000010; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c index b61506776105..af53cbbc632c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c @@ -25,6 +25,21 @@ #include #include +void +gm200_flcn_tracepc(struct nvkm_falcon *falcon) +{ + u32 sctl = nvkm_falcon_rd32(falcon, 0x240); + u32 tidx = nvkm_falcon_rd32(falcon, 0x148); + int nr = (tidx & 0x00ff0000) >> 16, sp, ip; + + FLCN_ERR(falcon, "TRACEPC SCTL %08x TIDX %08x", sctl, tidx); + for (sp = 0; sp < nr; sp++) { + nvkm_falcon_wr32(falcon, 0x148, sp); + ip = nvkm_falcon_rd32(falcon, 0x14c); + FLCN_ERR(falcon, "TRACEPC: %08x", ip); + } +} + static void gm200_flcn_pio_dmem_rd(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len) { -- cgit v1.2.3 From 1ed02c3f2db00f3c29e88a3d880d64a7e1b7a047 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:02 +1000 Subject: drm/nouveau/engine: add HAL for engine-specific rc reset procedure Will be used to improve gr reset on GF100 and newer. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/core/engine.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/core/engine.c | 10 ++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h index 6d15c13509bf..b67b9c1a6b4e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h @@ -21,6 +21,7 @@ struct nvkm_engine_func { int (*info)(struct nvkm_engine *, u64 mthd, u64 *data); int (*init)(struct nvkm_engine *); int (*fini)(struct nvkm_engine *, bool suspend); + int (*reset)(struct nvkm_engine *); void (*intr)(struct nvkm_engine *); void (*tile)(struct nvkm_engine *, int region, struct nvkm_fb_tile *); bool (*chsw_load)(struct nvkm_engine *); @@ -48,6 +49,7 @@ int nvkm_engine_new_(const struct nvkm_engine_func *, struct nvkm_device *, struct nvkm_engine *nvkm_engine_ref(struct nvkm_engine *); void nvkm_engine_unref(struct nvkm_engine **); +int nvkm_engine_reset(struct nvkm_engine *); void nvkm_engine_tile(struct nvkm_engine *, int region); bool nvkm_engine_chsw_load(struct nvkm_engine *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c index 964615a60997..36a31e9eea22 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c @@ -35,6 +35,16 @@ nvkm_engine_chsw_load(struct nvkm_engine *engine) return false; } +int +nvkm_engine_reset(struct nvkm_engine *engine) +{ + if (engine->func->reset) + return engine->func->reset(engine); + + nvkm_subdev_fini(&engine->subdev, false); + return nvkm_subdev_init(&engine->subdev); +} + void nvkm_engine_unref(struct nvkm_engine **pengine) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c index fe51c075d6c4..b5836cbc29aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c @@ -113,8 +113,8 @@ nvkm_runl_rc(struct nvkm_runl *runl) } ENGN_DEBUG(engn, "resetting..."); - nvkm_subdev_fini(&engn->engine->subdev, false); - WARN_ON(nvkm_subdev_init(&engn->engine->subdev)); + /*TODO: can we do something less of a potential catastrophe on failure? */ + WARN_ON(nvkm_engine_reset(engn->engine)); } /* Submit runlist update, and clear any remaining exception state. */ -- cgit v1.2.3 From 4500031f86691a44ecbbebfc77872c60c5a1b8e6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:03 +1000 Subject: drm/nouveau/ltc: split color vs depth/stencil zbc counts These differ on Ampere. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h | 15 +++++++++------ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 12 ++++++------ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 6 +++--- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c | 10 +++++++--- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h | 3 ++- 13 files changed, 42 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h index d32a326a9290..213d5ff33cae 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h @@ -4,7 +4,8 @@ #include #include -#define NVKM_LTC_MAX_ZBC_CNT 16 +#define NVKM_LTC_MAX_ZBC_COLOR_CNT 16 +#define NVKM_LTC_MAX_ZBC_DEPTH_CNT 16 struct nvkm_ltc { const struct nvkm_ltc_func *func; @@ -18,11 +19,13 @@ struct nvkm_ltc { u32 tag_base; struct nvkm_memory *tag_ram; - int zbc_min; - int zbc_max; - u32 zbc_color[NVKM_LTC_MAX_ZBC_CNT][4]; - u32 zbc_depth[NVKM_LTC_MAX_ZBC_CNT]; - u32 zbc_stencil[NVKM_LTC_MAX_ZBC_CNT]; + int zbc_color_min; + int zbc_color_max; + u32 zbc_color[NVKM_LTC_MAX_ZBC_COLOR_CNT][4]; + int zbc_depth_min; + int zbc_depth_max; + u32 zbc_depth[NVKM_LTC_MAX_ZBC_DEPTH_CNT]; + u32 zbc_stencil[NVKM_LTC_MAX_ZBC_DEPTH_CNT]; }; void nvkm_ltc_tags_clear(struct nvkm_device *, u32 first, u32 count); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index ee14115d669c..1a5ec366b672 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -67,7 +67,7 @@ gf100_gr_zbc_color_get(struct gf100_gr *gr, int format, struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc; int zbc = -ENOSPC, i; - for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) { + for (i = ltc->zbc_color_min; i <= ltc->zbc_color_max; i++) { if (gr->zbc_color[i].format) { if (gr->zbc_color[i].format != format) continue; @@ -114,7 +114,7 @@ gf100_gr_zbc_depth_get(struct gf100_gr *gr, int format, struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc; int zbc = -ENOSPC, i; - for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) { + for (i = ltc->zbc_depth_min; i <= ltc->zbc_depth_max; i++) { if (gr->zbc_depth[i].format) { if (gr->zbc_depth[i].format != format) continue; @@ -955,7 +955,7 @@ gf100_gr_zbc_init(struct gf100_gr *gr) const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc; - int index, c = ltc->zbc_min, d = ltc->zbc_min, s = ltc->zbc_min; + int index, c = ltc->zbc_color_min, d = ltc->zbc_depth_min, s = ltc->zbc_depth_min; if (!gr->zbc_color[0].format) { gf100_gr_zbc_color_get(gr, 1, & zero[0], &zero[4]); c++; @@ -971,13 +971,13 @@ gf100_gr_zbc_init(struct gf100_gr *gr) } } - for (index = c; index <= ltc->zbc_max; index++) + for (index = c; index <= ltc->zbc_color_max; index++) gr->func->zbc->clear_color(gr, index); - for (index = d; index <= ltc->zbc_max; index++) + for (index = d; index <= ltc->zbc_depth_max; index++) gr->func->zbc->clear_depth(gr, index); if (gr->func->zbc->clear_stencil) { - for (index = s; index <= ltc->zbc_max; index++) + for (index = s; index <= ltc->zbc_depth_max; index++) gr->func->zbc->clear_stencil(gr, index); } } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index c0038f906135..e90eb134b561 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -105,9 +105,9 @@ struct gf100_gr { struct gf100_gr_pack *bundle; struct gf100_gr_pack *method; - struct gf100_gr_zbc_color zbc_color[NVKM_LTC_MAX_ZBC_CNT]; - struct gf100_gr_zbc_depth zbc_depth[NVKM_LTC_MAX_ZBC_CNT]; - struct gf100_gr_zbc_stencil zbc_stencil[NVKM_LTC_MAX_ZBC_CNT]; + struct gf100_gr_zbc_color zbc_color[NVKM_LTC_MAX_ZBC_COLOR_CNT]; + struct gf100_gr_zbc_depth zbc_depth[NVKM_LTC_MAX_ZBC_DEPTH_CNT]; + struct gf100_gr_zbc_stencil zbc_stencil[NVKM_LTC_MAX_ZBC_DEPTH_CNT]; u8 rop_nr; u8 gpc_nr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c index 5b001f374be0..1d1f3c0a9014 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c @@ -47,7 +47,7 @@ gp102_gr_zbc_stencil_get(struct gf100_gr *gr, int format, struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc; int zbc = -ENOSPC, i; - for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) { + for (i = ltc->zbc_depth_min; i <= ltc->zbc_depth_max; i++) { if (gr->zbc_stencil[i].format) { if (gr->zbc_stencil[i].format != format) continue; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c index fa683c190795..f742a7b7b175 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c @@ -97,8 +97,10 @@ nvkm_ltc_init(struct nvkm_subdev *subdev) struct nvkm_ltc *ltc = nvkm_ltc(subdev); int i; - for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) { + for (i = ltc->zbc_color_min; i <= ltc->zbc_color_max; i++) ltc->func->zbc_clear_color(ltc, i, ltc->zbc_color[i]); + + for (i = ltc->zbc_depth_min; i <= ltc->zbc_depth_max; i++) { ltc->func->zbc_clear_depth(ltc, i, ltc->zbc_depth[i]); if (ltc->func->zbc_clear_stencil) ltc->func->zbc_clear_stencil(ltc, i, ltc->zbc_stencil[i]); @@ -137,7 +139,9 @@ nvkm_ltc_new_(const struct nvkm_ltc_func *func, struct nvkm_device *device, nvkm_subdev_ctor(&nvkm_ltc, device, type, inst, <c->subdev); ltc->func = func; mutex_init(<c->mutex); - ltc->zbc_min = 1; /* reserve 0 for disabled */ - ltc->zbc_max = min(func->zbc, NVKM_LTC_MAX_ZBC_CNT) - 1; + ltc->zbc_color_min = 1; /* reserve 0 for disabled */ + ltc->zbc_color_max = min(func->zbc_color, NVKM_LTC_MAX_ZBC_COLOR_CNT) - 1; + ltc->zbc_depth_min = 1; /* reserve 0 for disabled */ + ltc->zbc_depth_max = min(func->zbc_depth, NVKM_LTC_MAX_ZBC_DEPTH_CNT) - 1; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c index fd8aeafc812d..de71ba3c9292 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c @@ -241,7 +241,8 @@ gf100_ltc = { .intr = gf100_ltc_intr, .cbc_clear = gf100_ltc_cbc_clear, .cbc_wait = gf100_ltc_cbc_wait, - .zbc = 16, + .zbc_color = 16, + .zbc_depth = 16, .zbc_clear_color = gf100_ltc_zbc_clear_color, .zbc_clear_depth = gf100_ltc_zbc_clear_depth, .invalidate = gf100_ltc_invalidate, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c index 94aa09244d67..5d61e3c6ff59 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c @@ -42,7 +42,8 @@ gk104_ltc = { .intr = gf100_ltc_intr, .cbc_clear = gf100_ltc_cbc_clear, .cbc_wait = gf100_ltc_cbc_wait, - .zbc = 16, + .zbc_color = 16, + .zbc_depth = 16, .zbc_clear_color = gf100_ltc_zbc_clear_color, .zbc_clear_depth = gf100_ltc_zbc_clear_depth, .invalidate = gf100_ltc_invalidate, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c index 54d1d65d5a85..18685d849657 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c @@ -137,7 +137,8 @@ gm107_ltc = { .intr = gm107_ltc_intr, .cbc_clear = gm107_ltc_cbc_clear, .cbc_wait = gm107_ltc_cbc_wait, - .zbc = 16, + .zbc_color = 16, + .zbc_depth = 16, .zbc_clear_color = gm107_ltc_zbc_clear_color, .zbc_clear_depth = gm107_ltc_zbc_clear_depth, .invalidate = gf100_ltc_invalidate, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c index 8cfdbbdd8e8d..7a9464b9def5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c @@ -49,7 +49,8 @@ gm200_ltc = { .intr = gm107_ltc_intr, .cbc_clear = gm107_ltc_cbc_clear, .cbc_wait = gm107_ltc_cbc_wait, - .zbc = 16, + .zbc_color = 16, + .zbc_depth = 16, .zbc_clear_color = gm107_ltc_zbc_clear_color, .zbc_clear_depth = gm107_ltc_zbc_clear_depth, .invalidate = gf100_ltc_invalidate, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c index a4a6cd9b435a..1a17a451754c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c @@ -61,7 +61,8 @@ gp100_ltc = { .intr = gp100_ltc_intr, .cbc_clear = gm107_ltc_cbc_clear, .cbc_wait = gm107_ltc_cbc_wait, - .zbc = 16, + .zbc_color = 16, + .zbc_depth = 16, .zbc_clear_color = gm107_ltc_zbc_clear_color, .zbc_clear_depth = gm107_ltc_zbc_clear_depth, .invalidate = gf100_ltc_invalidate, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c index ff05d617e7f4..265a05fd5f6b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c @@ -36,7 +36,8 @@ gp102_ltc = { .intr = gp100_ltc_intr, .cbc_clear = gm107_ltc_cbc_clear, .cbc_wait = gm107_ltc_cbc_wait, - .zbc = 16, + .zbc_color = 16, + .zbc_depth = 16, .zbc_clear_color = gm107_ltc_zbc_clear_color, .zbc_clear_depth = gm107_ltc_zbc_clear_depth, .zbc_clear_stencil = gp102_ltc_zbc_clear_stencil, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c index dfebd796cb4b..e7e8fdf3adab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c @@ -50,7 +50,8 @@ gp10b_ltc = { .intr = gp100_ltc_intr, .cbc_clear = gm107_ltc_cbc_clear, .cbc_wait = gm107_ltc_cbc_wait, - .zbc = 16, + .zbc_color = 16, + .zbc_depth = 16, .zbc_clear_color = gm107_ltc_zbc_clear_color, .zbc_clear_depth = gm107_ltc_zbc_clear_depth, .zbc_clear_stencil = gp102_ltc_zbc_clear_stencil, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h index 2bebe139005d..134e90c9e861 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h @@ -16,7 +16,8 @@ struct nvkm_ltc_func { void (*cbc_clear)(struct nvkm_ltc *, u32 start, u32 limit); void (*cbc_wait)(struct nvkm_ltc *); - int zbc; + int zbc_color; + int zbc_depth; void (*zbc_clear_color)(struct nvkm_ltc *, int, const u32[4]); void (*zbc_clear_depth)(struct nvkm_ltc *, int, const u32); void (*zbc_clear_stencil)(struct nvkm_ltc *, int, const u32); -- cgit v1.2.3 From 0ceceaa9ae8294b0da91d731027b5c4b1bb4187e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:04 +1000 Subject: drm/nouveau/fifo: expose function to read engine ctxsw status Needed to support Ampere differences in gr/gf100-: Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c | 16 ++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 4825403a2688..221abd6c4310 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -75,6 +75,7 @@ struct nvkm_fifo { void nvkm_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); void nvkm_fifo_pause(struct nvkm_fifo *, unsigned long *); void nvkm_fifo_start(struct nvkm_fifo *, unsigned long *); +bool nvkm_fifo_ctxsw_in_progress(struct nvkm_engine *); int nv04_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); int nv10_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index abce1ecfd4d4..5ea9a2ff0663 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -35,6 +35,22 @@ #include #include +bool +nvkm_fifo_ctxsw_in_progress(struct nvkm_engine *engine) +{ + struct nvkm_runl *runl; + struct nvkm_engn *engn; + + nvkm_runl_foreach(runl, engine->subdev.device->fifo) { + nvkm_runl_foreach_engn(engn, runl) { + if (engn->engine == engine) + return engn->func->chsw ? engn->func->chsw(engn) : false; + } + } + + return false; +} + void nvkm_fifo_pause(struct nvkm_fifo *fifo, unsigned long *flags) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 1a5ec366b672..acc7a74f9cc3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1003,7 +1003,7 @@ gf100_gr_wait_idle(struct gf100_gr *gr) nvkm_rd32(device, 0x400700); gr_enabled = nvkm_rd32(device, 0x200) & 0x1000; - ctxsw_active = nvkm_rd32(device, 0x2640) & 0x8000; + ctxsw_active = nvkm_fifo_ctxsw_in_progress(&gr->base.engine); gr_busy = nvkm_rd32(device, 0x40060c) & 0x1; if (!gr_enabled || (!gr_busy && !ctxsw_active)) -- cgit v1.2.3 From 113750215058a19330858dc41fbaac8f9540d45f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:04 +1000 Subject: drm/nouveau/gr/gf100-: move some code around to make next commits nicer Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 104 ++++++++++++------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index acc7a74f9cc3..662d953eaddb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2055,22 +2055,6 @@ gf100_gr_dtor(struct nvkm_gr *base) return gr; } -static const struct nvkm_gr_func -gf100_gr_ = { - .dtor = gf100_gr_dtor, - .oneinit = gf100_gr_oneinit, - .init = gf100_gr_init_, - .fini = gf100_gr_fini, - .intr = gf100_gr_intr, - .units = gf100_gr_units, - .chan_new = gf100_gr_chan_new, - .object_get = gf100_gr_object_get, - .chsw_load = gf100_gr_chsw_load, - .ctxsw.pause = gf100_gr_fecs_stop_ctxsw, - .ctxsw.resume = gf100_gr_fecs_start_ctxsw, - .ctxsw.inst = gf100_gr_ctxsw_inst, -}; - static const struct nvkm_falcon_func gf100_gr_flcn = { .load_imem = nvkm_falcon_v1_load_imem, @@ -2078,42 +2062,6 @@ gf100_gr_flcn = { .start = nvkm_falcon_v1_start, }; -int -gf100_gr_new_(const struct gf100_gr_fwif *fwif, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr) -{ - struct gf100_gr *gr; - int ret; - - if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) - return -ENOMEM; - *pgr = &gr->base; - - ret = nvkm_gr_ctor(&gf100_gr_, device, type, inst, true, &gr->base); - if (ret) - return ret; - - fwif = nvkm_firmware_load(&gr->base.engine.subdev, fwif, "Gr", gr); - if (IS_ERR(fwif)) - return PTR_ERR(fwif); - - gr->func = fwif->func; - - ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev, - "fecs", 0x409000, &gr->fecs.falcon); - if (ret) - return ret; - - mutex_init(&gr->fecs.mutex); - - ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev, - "gpccs", 0x41a000, &gr->gpccs.falcon); - if (ret) - return ret; - - return 0; -} - void gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *gr, bool pd, bool ds) { @@ -2383,6 +2331,22 @@ gf100_gr_gpccs_ucode = { .data.size = sizeof(gf100_grgpc_data), }; +static const struct nvkm_gr_func +gf100_gr_ = { + .dtor = gf100_gr_dtor, + .oneinit = gf100_gr_oneinit, + .init = gf100_gr_init_, + .fini = gf100_gr_fini, + .intr = gf100_gr_intr, + .units = gf100_gr_units, + .chan_new = gf100_gr_chan_new, + .object_get = gf100_gr_object_get, + .chsw_load = gf100_gr_chsw_load, + .ctxsw.pause = gf100_gr_fecs_stop_ctxsw, + .ctxsw.resume = gf100_gr_fecs_start_ctxsw, + .ctxsw.inst = gf100_gr_ctxsw_inst, +}; + static const struct gf100_gr_func gf100_gr = { .oneinit_tiles = gf100_gr_oneinit_tiles, @@ -2474,6 +2438,42 @@ gf100_gr_fwif[] = { {} }; +int +gf100_gr_new_(const struct gf100_gr_fwif *fwif, struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr) +{ + struct gf100_gr *gr; + int ret; + + if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) + return -ENOMEM; + *pgr = &gr->base; + + ret = nvkm_gr_ctor(&gf100_gr_, device, type, inst, true, &gr->base); + if (ret) + return ret; + + fwif = nvkm_firmware_load(&gr->base.engine.subdev, fwif, "Gr", gr); + if (IS_ERR(fwif)) + return PTR_ERR(fwif); + + gr->func = fwif->func; + + ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev, + "fecs", 0x409000, &gr->fecs.falcon); + if (ret) + return ret; + + mutex_init(&gr->fecs.mutex); + + ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev, + "gpccs", 0x41a000, &gr->gpccs.falcon); + if (ret) + return ret; + + return 0; +} + int gf100_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr) { -- cgit v1.2.3 From ca081fff6ecc63c86a99918230cc9b947bebae8a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:05 +1000 Subject: drm/nouveau/gr/gf100-: generate golden context during first object alloc Needed for GV100 (and only GV100 for some reason) for WFI_GOLDEN_SAVE. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 45 +++++++---------------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 28 ++++++-------- 3 files changed, 26 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 297915719bf2..45db67d55169 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -26,6 +26,7 @@ #include #include #include +#include /******************************************************************************* * PGRAPH context register lists @@ -1433,14 +1434,12 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) #define CB_RESERVED 0x80000 int -gf100_grctx_generate(struct gf100_gr *gr) +gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvkm_gpuobj *inst) { const struct gf100_grctx_func *grctx = gr->func->grctx; struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_memory *inst = NULL; struct nvkm_memory *data = NULL; - struct nvkm_vmm *vmm = NULL; struct nvkm_vma *ctx = NULL; struct gf100_grctx info; int ret, i; @@ -1472,38 +1471,20 @@ gf100_grctx_generate(struct gf100_gr *gr) /* Init SCC RAM. */ nvkm_wr32(device, 0x40802c, 0x00000001); - /* Allocate memory to for a "channel", which we'll use to generate - * the default context values. - */ - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - 0x1000, 0x1000, true, &inst); - if (ret) - goto done; - - ret = nvkm_vmm_new(device, 0, 0, NULL, 0, NULL, "grctx", &vmm); - if (ret) - goto done; - - vmm->debug = subdev->debug; - - ret = nvkm_vmm_join(vmm, inst); - if (ret) - goto done; - + /* Allocate memory to store context, and dummy global context buffers. */ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, CB_RESERVED + gr->size, 0, true, &data); if (ret) goto done; - ret = nvkm_vmm_get(vmm, 0, nvkm_memory_size(data), &ctx); + ret = nvkm_vmm_get(chan->vmm, 0, nvkm_memory_size(data), &ctx); if (ret) goto done; - ret = nvkm_memory_map(data, 0, vmm, ctx, NULL, 0); + ret = nvkm_memory_map(data, 0, chan->vmm, ctx, NULL, 0); if (ret) goto done; - /* Setup context pointer. */ nvkm_kmap(inst); nvkm_wo32(inst, 0x0210, lower_32_bits(ctx->addr + CB_RESERVED) | 4); @@ -1518,11 +1499,11 @@ gf100_grctx_generate(struct gf100_gr *gr) info.buffer_nr = 0; /* Make channel current. */ - addr = nvkm_memory_addr(inst) >> 12; + addr = inst->addr >> 12; if (gr->firmware) { ret = gf100_gr_fecs_bind_pointer(gr, 0x80000000 | addr); if (ret) - goto done; + goto done_inst; nvkm_kmap(data); nvkm_wo32(data, 0x1c, 1); @@ -1552,7 +1533,7 @@ gf100_grctx_generate(struct gf100_gr *gr) break; ) < 0) { ret = -EBUSY; - goto done; + goto done_inst; } gr->data = kmalloc(gr->size, GFP_KERNEL); @@ -1566,12 +1547,14 @@ gf100_grctx_generate(struct gf100_gr *gr) ret = -ENOMEM; } +done_inst: + nvkm_kmap(inst); + nvkm_wo32(inst, 0x0210, 0); + nvkm_wo32(inst, 0x0214, 0); + nvkm_done(inst); done: - nvkm_vmm_put(vmm, &ctx); + nvkm_vmm_put(chan->vmm, &ctx); nvkm_memory_unref(&data); - nvkm_vmm_part(vmm, inst); - nvkm_vmm_unref(&vmm); - nvkm_memory_unref(&inst); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 32bbddc0993e..7b968ef68191 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -81,7 +81,7 @@ struct gf100_grctx_func { }; extern const struct gf100_grctx_func gf100_grctx; -int gf100_grctx_generate(struct gf100_gr *); +int gf100_grctx_generate(struct gf100_gr *, struct gf100_gr_chan *, struct nvkm_gpuobj *inst); void gf100_grctx_generate_main(struct gf100_gr *, struct gf100_grctx *); void gf100_grctx_generate_bundle(struct gf100_grctx *); void gf100_grctx_generate_pagepool(struct gf100_grctx *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 662d953eaddb..310949c641ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -394,6 +394,17 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, chan->vmm = nvkm_vmm_ref(fifoch->vmm); *pobject = &chan->object; + /* Generate golden context image. */ + mutex_lock(&gr->fecs.mutex); + if (gr->data == NULL) { + ret = gf100_grctx_generate(gr, chan, fifoch->inst); + if (ret) { + nvkm_error(&base->engine.subdev, "failed to construct context\n"); + return ret; + } + } + mutex_unlock(&gr->fecs.mutex); + /* allocate memory for a "mmio list" buffer that's used by the HUB * fuc to modify some per-context register settings on first load * of the context. @@ -1763,15 +1774,6 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) return ret; } - /* Generate golden context image. */ - if (gr->data == NULL) { - int ret = gf100_grctx_generate(gr); - if (ret) { - nvkm_error(subdev, "failed to construct context\n"); - return ret; - } - } - return 0; } @@ -1823,14 +1825,6 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr) } gr->size = nvkm_rd32(device, 0x409804); - if (gr->data == NULL) { - int ret = gf100_grctx_generate(gr); - if (ret) { - nvkm_error(subdev, "failed to construct context\n"); - return ret; - } - } - return 0; } -- cgit v1.2.3 From d05095b53cd41c7e1db8f680610386f73c0f7290 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:05 +1000 Subject: drm/nouveau/gr/gf100-: make global pagepool actually global This was thought to be per-channel initially - it's not. The backing pages for the VMM mappings are shared for all channels. - switches to more straight-forward patch interfaces - prepares for sub-context support Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 32 +++++++++++++++-------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 15 ++++++----- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c | 12 +++------ drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c | 5 ++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c | 13 +++------ drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c | 5 ++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c | 13 ++++----- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 22 +++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 4 +++ 9 files changed, 71 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 45db67d55169..291d98fece32 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -991,6 +991,18 @@ gf100_grctx_pack_tpc[] = { * PGRAPH context implementation ******************************************************************************/ +void +gf100_grctx_patch_wr32(struct gf100_gr_chan *chan, u32 addr, u32 data) +{ + if (unlikely(!chan->mmio)) { + nvkm_wr32(chan->gr->base.engine.subdev.device, addr, data); + return; + } + + nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, addr); + nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data); +} + int gf100_grctx_mmio_data(struct gf100_grctx *info, u32 size, u32 align, bool priv) { @@ -1050,15 +1062,12 @@ gf100_grctx_generate_bundle(struct gf100_grctx *info) } void -gf100_grctx_generate_pagepool(struct gf100_grctx *info) +gf100_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr) { - const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const int s = 8; - const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); - mmio_refn(info, 0x40800c, 0x00000000, s, b); - mmio_wr32(info, 0x408010, 0x80000000); - mmio_refn(info, 0x419004, 0x00000000, s, b); - mmio_wr32(info, 0x419008, 0x00000000); + gf100_grctx_patch_wr32(chan, 0x40800c, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x408010, 0x80000000); + gf100_grctx_patch_wr32(chan, 0x419004, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x419008, 0x00000000); } void @@ -1362,8 +1371,9 @@ gf100_grctx_generate_floorsweep(struct gf100_gr *gr) } void -gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) +gf100_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) { + struct gf100_gr *gr = chan->gr; struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_grctx_func *grctx = gr->func->grctx; u32 idle_timeout; @@ -1385,7 +1395,7 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000); - grctx->pagepool(info); + grctx->pagepool(chan, chan->pagepool->addr); grctx->bundle(info); grctx->attrib(info); if (grctx->patch_ltc) @@ -1521,7 +1531,7 @@ gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvk ); } - grctx->main(gr, &info); + grctx->main(chan, &info); /* Trigger a context unload by unsetting the "next channel valid" bit * and faking a context switch interrupt. diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 7b968ef68191..1c68a008c377 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -14,6 +14,7 @@ struct gf100_grctx { int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, bool priv); void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int); +void gf100_grctx_patch_wr32(struct gf100_gr_chan *, u32 addr, u32 data); #define mmio_vram(a,b,c,d) gf100_grctx_mmio_data((a), (b), (c), (d)) #define mmio_refn(a,b,c,d,e) gf100_grctx_mmio_item((a), (b), (c), (d), (e)) @@ -23,7 +24,7 @@ void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int) struct gf100_grctx_func { void (*unkn88c)(struct gf100_gr *, bool on); /* main context generation function */ - void (*main)(struct gf100_gr *, struct gf100_grctx *); + void (*main)(struct gf100_gr_chan *, struct gf100_grctx *); /* context-specific modify-on-first-load list generation function */ void (*unkn)(struct gf100_gr *); /* mmio context data */ @@ -43,7 +44,7 @@ struct gf100_grctx_func { u32 bundle_min_gpm_fifo_depth; u32 bundle_token_limit; /* pagepool */ - void (*pagepool)(struct gf100_grctx *); + void (*pagepool)(struct gf100_gr_chan *, u64 addr); u32 pagepool_size; /* attribute(/alpha) circular buffer */ void (*attrib)(struct gf100_grctx *); @@ -82,9 +83,9 @@ struct gf100_grctx_func { extern const struct gf100_grctx_func gf100_grctx; int gf100_grctx_generate(struct gf100_gr *, struct gf100_gr_chan *, struct nvkm_gpuobj *inst); -void gf100_grctx_generate_main(struct gf100_gr *, struct gf100_grctx *); +void gf100_grctx_generate_main(struct gf100_gr_chan *, struct gf100_grctx *); void gf100_grctx_generate_bundle(struct gf100_grctx *); -void gf100_grctx_generate_pagepool(struct gf100_grctx *); +void gf100_grctx_generate_pagepool(struct gf100_gr_chan *, u64); void gf100_grctx_generate_attrib(struct gf100_grctx *); void gf100_grctx_generate_unkn(struct gf100_gr *); void gf100_grctx_generate_floorsweep(struct gf100_gr *); @@ -116,7 +117,7 @@ void gk104_grctx_generate_gpc_tpc_nr(struct gf100_gr *); extern const struct gf100_grctx_func gk20a_grctx; void gk104_grctx_generate_bundle(struct gf100_grctx *); -void gk104_grctx_generate_pagepool(struct gf100_grctx *); +void gk104_grctx_generate_pagepool(struct gf100_gr_chan *, u64); void gk104_grctx_generate_patch_ltc(struct gf100_grctx *); void gk104_grctx_generate_unkn(struct gf100_gr *); void gk104_grctx_generate_r418800(struct gf100_gr *); @@ -129,7 +130,7 @@ extern const struct gf100_grctx_func gk208_grctx; extern const struct gf100_grctx_func gm107_grctx; void gm107_grctx_generate_bundle(struct gf100_grctx *); -void gm107_grctx_generate_pagepool(struct gf100_grctx *); +void gm107_grctx_generate_pagepool(struct gf100_gr_chan *, u64); void gm107_grctx_generate_attrib(struct gf100_grctx *); void gm107_grctx_generate_sm_id(struct gf100_gr *, int, int, int); @@ -143,7 +144,7 @@ void gm200_grctx_generate_r419a3c(struct gf100_gr *); extern const struct gf100_grctx_func gm20b_grctx; extern const struct gf100_grctx_func gp100_grctx; -void gp100_grctx_generate_pagepool(struct gf100_grctx *); +void gp100_grctx_generate_pagepool(struct gf100_gr_chan *, u64); void gp100_grctx_generate_smid_config(struct gf100_gr *); extern const struct gf100_grctx_func gp102_grctx; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index 304e9d268bad..10e78639a816 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -888,16 +888,10 @@ gk104_grctx_generate_bundle(struct gf100_grctx *info) } void -gk104_grctx_generate_pagepool(struct gf100_grctx *info) +gk104_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr) { - const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const int s = 8; - const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); - mmio_refn(info, 0x40800c, 0x00000000, s, b); - mmio_wr32(info, 0x408010, 0x80000000); - mmio_refn(info, 0x419004, 0x00000000, s, b); - mmio_wr32(info, 0x419008, 0x00000000); - mmio_wr32(info, 0x4064cc, 0x80000000); + gf100_grctx_generate_pagepool(chan, addr); + gf100_grctx_patch_wr32(chan, 0x4064cc, 0x80000000); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c index c0d36bc601f9..46d64c208754 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c @@ -25,8 +25,9 @@ #include static void -gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) +gk20a_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) { + struct gf100_gr *gr = chan->gr; struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_grctx_func *grctx = gr->func->grctx; u32 idle_timeout; @@ -60,7 +61,7 @@ gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) gf100_gr_wait_idle(gr); gf100_gr_icmd(gr, gr->bundle); - grctx->pagepool(info); + grctx->pagepool(chan, chan->pagepool->addr); grctx->bundle(info); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index 0b3964e6b36e..11ccee875ed7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -892,17 +892,10 @@ gm107_grctx_generate_bundle(struct gf100_grctx *info) } void -gm107_grctx_generate_pagepool(struct gf100_grctx *info) +gm107_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr) { - const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const int s = 8; - const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); - mmio_refn(info, 0x40800c, 0x00000000, s, b); - mmio_wr32(info, 0x408010, 0x80000000); - mmio_refn(info, 0x419004, 0x00000000, s, b); - mmio_wr32(info, 0x419008, 0x00000000); - mmio_wr32(info, 0x4064cc, 0x80000000); - mmio_wr32(info, 0x418e30, 0x80000000); /* guess at it being related */ + gk104_grctx_generate_pagepool(chan, addr); + gf100_grctx_patch_wr32(chan, 0x418e30, 0x80000000); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c index 6b92f8aa18a3..d0b45d1074a2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c @@ -22,8 +22,9 @@ #include "ctxgf100.h" static void -gm20b_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) +gm20b_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) { + struct gf100_gr *gr = chan->gr; struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_grctx_func *grctx = gr->func->grctx; u32 idle_timeout; @@ -63,7 +64,7 @@ gm20b_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) gf100_gr_wait_idle(gr); gf100_gr_icmd(gr, gr->bundle); - grctx->pagepool(info); + grctx->pagepool(chan, chan->pagepool->addr); grctx->bundle(info); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c index 0b3326262e12..b2fa7c943c49 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c @@ -30,15 +30,12 @@ ******************************************************************************/ void -gp100_grctx_generate_pagepool(struct gf100_grctx *info) +gp100_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr) { - const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const int s = 8; - const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); - mmio_refn(info, 0x40800c, 0x00000000, s, b); - mmio_wr32(info, 0x408010, 0x8007d800); - mmio_refn(info, 0x419004, 0x00000000, s, b); - mmio_wr32(info, 0x419008, 0x00000000); + gf100_grctx_patch_wr32(chan, 0x40800c, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x408010, 0x8007d800); + gf100_grctx_patch_wr32(chan, 0x419004, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x419008, 0x00000000); } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 310949c641ce..56f662fa37d3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -364,6 +364,8 @@ gf100_gr_chan_dtor(struct nvkm_object *object) nvkm_vmm_put(chan->vmm, &chan->mmio_vma); nvkm_memory_unref(&chan->mmio); + + nvkm_vmm_put(chan->vmm, &chan->pagepool); nvkm_vmm_unref(&chan->vmm); return chan; } @@ -394,6 +396,15 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, chan->vmm = nvkm_vmm_ref(fifoch->vmm); *pobject = &chan->object; + /* Map pagepool. */ + ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->pagepool), &chan->pagepool); + if (ret) + return ret; + + ret = nvkm_memory_map(gr->pagepool, 0, chan->vmm, chan->pagepool, &args, sizeof(args)); + if (ret) + return ret; + /* Generate golden context image. */ mutex_lock(&gr->fecs.mutex); if (gr->data == NULL) { @@ -449,6 +460,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, /* finally, fill in the mmio list and point the context at it */ nvkm_kmap(chan->mmio); + gr->func->grctx->pagepool(chan, chan->pagepool->addr); for (i = 0; mmio->addr && i < ARRAY_SIZE(gr->mmio_list); i++) { u32 addr = mmio->addr; u32 data = mmio->data; @@ -1938,7 +1950,7 @@ gf100_gr_oneinit(struct nvkm_gr *base) struct gf100_gr *gr = gf100_gr(base); struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - int i, j; + int ret, i, j; nvkm_pmu_pgob(device->pmu, false); @@ -1964,6 +1976,12 @@ gf100_gr_oneinit(struct nvkm_gr *base) } } + /* Allocate global context buffers. */ + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->pagepool_size, + 0x100, false, &gr->pagepool); + if (ret) + return ret; + memset(gr->tile, 0xff, sizeof(gr->tile)); gr->func->oneinit_tiles(gr); gr->func->oneinit_sm_id(gr); @@ -2033,6 +2051,8 @@ gf100_gr_dtor(struct nvkm_gr *base) kfree(gr->data); + nvkm_memory_unref(&gr->pagepool); + nvkm_falcon_dtor(&gr->gpccs.falcon); nvkm_falcon_dtor(&gr->fecs.falcon); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index e90eb134b561..c74cc23859a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -121,6 +121,8 @@ struct gf100_gr { u8 ppc_tpc_min; u8 ppc_tpc_max; + struct nvkm_memory *pagepool; + u8 screen_tile_row_offset; u8 tile[TPC_MAX]; @@ -258,6 +260,8 @@ struct gf100_gr_chan { struct gf100_gr *gr; struct nvkm_vmm *vmm; + struct nvkm_vma *pagepool; + struct nvkm_memory *mmio; struct nvkm_vma *mmio_vma; int mmio_nr; -- cgit v1.2.3 From 95f78acd88594101f658a4587f51ccb6a6556cc3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:06 +1000 Subject: drm/nouveau/gr/gf100-: make global bundle_cb actually global This was thought to be per-channel initially - it's not. The backing pages for the VMM mappings are shared for all channels. - switches to more straight-forward patch interfaces - prepares for sub-context support Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 15 ++++++--------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 8 ++++---- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c | 17 ++++++----------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c | 20 +++++++++----------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 17 +++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 2 ++ 8 files changed, 46 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 291d98fece32..3d06ca63e532 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1050,15 +1050,12 @@ gf100_grctx_generate_r419cb8(struct gf100_gr *gr) } void -gf100_grctx_generate_bundle(struct gf100_grctx *info) +gf100_grctx_generate_bundle(struct gf100_gr_chan *chan, u64 addr, u32 size) { - const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const int s = 8; - const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true); - mmio_refn(info, 0x408004, 0x00000000, s, b); - mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); - mmio_refn(info, 0x418808, 0x00000000, s, b); - mmio_wr32(info, 0x41880c, 0x80000000 | (grctx->bundle_size >> s)); + gf100_grctx_patch_wr32(chan, 0x408004, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x408008, 0x80000000 | (size >> 8)); + gf100_grctx_patch_wr32(chan, 0x418808, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x41880c, 0x80000000 | (size >> 8)); } void @@ -1396,7 +1393,7 @@ gf100_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000); grctx->pagepool(chan, chan->pagepool->addr); - grctx->bundle(info); + grctx->bundle(chan, chan->bundle_cb->addr, grctx->bundle_size); grctx->attrib(info); if (grctx->patch_ltc) grctx->patch_ltc(info); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 1c68a008c377..6e5fabf46015 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -39,7 +39,7 @@ struct gf100_grctx_func { const struct gf100_gr_pack *mthd; const struct gf100_gr_pack *sw_veid_bundle_init; /* bundle circular buffer */ - void (*bundle)(struct gf100_grctx *); + void (*bundle)(struct gf100_gr_chan *, u64 addr, u32 size); u32 bundle_size; u32 bundle_min_gpm_fifo_depth; u32 bundle_token_limit; @@ -84,8 +84,8 @@ struct gf100_grctx_func { extern const struct gf100_grctx_func gf100_grctx; int gf100_grctx_generate(struct gf100_gr *, struct gf100_gr_chan *, struct nvkm_gpuobj *inst); void gf100_grctx_generate_main(struct gf100_gr_chan *, struct gf100_grctx *); -void gf100_grctx_generate_bundle(struct gf100_grctx *); void gf100_grctx_generate_pagepool(struct gf100_gr_chan *, u64); +void gf100_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32); void gf100_grctx_generate_attrib(struct gf100_grctx *); void gf100_grctx_generate_unkn(struct gf100_gr *); void gf100_grctx_generate_floorsweep(struct gf100_gr *); @@ -116,8 +116,8 @@ void gk104_grctx_generate_alpha_beta_tables(struct gf100_gr *); void gk104_grctx_generate_gpc_tpc_nr(struct gf100_gr *); extern const struct gf100_grctx_func gk20a_grctx; -void gk104_grctx_generate_bundle(struct gf100_grctx *); void gk104_grctx_generate_pagepool(struct gf100_gr_chan *, u64); +void gk104_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32); void gk104_grctx_generate_patch_ltc(struct gf100_grctx *); void gk104_grctx_generate_unkn(struct gf100_gr *); void gk104_grctx_generate_r418800(struct gf100_gr *); @@ -129,8 +129,8 @@ extern const struct gf100_grctx_func gk110b_grctx; extern const struct gf100_grctx_func gk208_grctx; extern const struct gf100_grctx_func gm107_grctx; -void gm107_grctx_generate_bundle(struct gf100_grctx *); void gm107_grctx_generate_pagepool(struct gf100_gr_chan *, u64); +void gm107_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32); void gm107_grctx_generate_attrib(struct gf100_grctx *); void gm107_grctx_generate_sm_id(struct gf100_gr *, int, int, int); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index 10e78639a816..d897090e829c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -872,19 +872,14 @@ gk104_grctx_generate_patch_ltc(struct gf100_grctx *info) } void -gk104_grctx_generate_bundle(struct gf100_grctx *info) +gk104_grctx_generate_bundle(struct gf100_gr_chan *chan, u64 addr, u32 size) { - const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, - grctx->bundle_size / 0x20); + const struct gf100_grctx_func *grctx = chan->gr->func->grctx; + const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, size / 0x20); const u32 token_limit = grctx->bundle_token_limit; - const int s = 8; - const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true); - mmio_refn(info, 0x408004, 0x00000000, s, b); - mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); - mmio_refn(info, 0x418808, 0x00000000, s, b); - mmio_wr32(info, 0x41880c, 0x80000000 | (grctx->bundle_size >> s)); - mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit); + + gf100_grctx_generate_bundle(chan, addr, size); + gf100_grctx_patch_wr32(chan, 0x4064c8, (state_limit << 16) | token_limit); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c index 46d64c208754..2380ecce8cd6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c @@ -62,7 +62,7 @@ gk20a_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) gf100_gr_icmd(gr, gr->bundle); grctx->pagepool(chan, chan->pagepool->addr); - grctx->bundle(info); + grctx->bundle(chan, chan->bundle_cb->addr, grctx->bundle_size); } const struct gf100_grctx_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index 11ccee875ed7..d968bcdfa90d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -876,19 +876,17 @@ gm107_grctx_generate_r419e00(struct gf100_gr *gr) } void -gm107_grctx_generate_bundle(struct gf100_grctx *info) +gm107_grctx_generate_bundle(struct gf100_gr_chan *chan, u64 addr, u32 size) { - const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, - grctx->bundle_size / 0x20); + const struct gf100_grctx_func *grctx = chan->gr->func->grctx; + const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, size / 0x20); const u32 token_limit = grctx->bundle_token_limit; - const int s = 8; - const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true); - mmio_refn(info, 0x408004, 0x00000000, s, b); - mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); - mmio_refn(info, 0x418e24, 0x00000000, s, b); - mmio_wr32(info, 0x418e28, 0x80000000 | (grctx->bundle_size >> s)); - mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit); + + gf100_grctx_patch_wr32(chan, 0x408004, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x408008, 0x80000000 | (size >> 8)); + gf100_grctx_patch_wr32(chan, 0x418e24, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x418e28, 0x80000000 | (size >> 8)); + gf100_grctx_patch_wr32(chan, 0x4064c8, (state_limit << 16) | token_limit); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c index d0b45d1074a2..cb02b02a4c86 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c @@ -65,7 +65,7 @@ gm20b_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) gf100_gr_icmd(gr, gr->bundle); grctx->pagepool(chan, chan->pagepool->addr); - grctx->bundle(info); + grctx->bundle(chan, chan->bundle_cb->addr, grctx->bundle_size); } const struct gf100_grctx_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 56f662fa37d3..0a45e78a2f83 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -365,6 +365,7 @@ gf100_gr_chan_dtor(struct nvkm_object *object) nvkm_vmm_put(chan->vmm, &chan->mmio_vma); nvkm_memory_unref(&chan->mmio); + nvkm_vmm_put(chan->vmm, &chan->bundle_cb); nvkm_vmm_put(chan->vmm, &chan->pagepool); nvkm_vmm_unref(&chan->vmm); return chan; @@ -405,6 +406,15 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, if (ret) return ret; + /* Map bundle circular buffer. */ + ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->bundle_cb), &chan->bundle_cb); + if (ret) + return ret; + + ret = nvkm_memory_map(gr->bundle_cb, 0, chan->vmm, chan->bundle_cb, &args, sizeof(args)); + if (ret) + return ret; + /* Generate golden context image. */ mutex_lock(&gr->fecs.mutex); if (gr->data == NULL) { @@ -461,6 +471,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, /* finally, fill in the mmio list and point the context at it */ nvkm_kmap(chan->mmio); gr->func->grctx->pagepool(chan, chan->pagepool->addr); + gr->func->grctx->bundle(chan, chan->bundle_cb->addr, gr->func->grctx->bundle_size); for (i = 0; mmio->addr && i < ARRAY_SIZE(gr->mmio_list); i++) { u32 addr = mmio->addr; u32 data = mmio->data; @@ -1982,6 +1993,11 @@ gf100_gr_oneinit(struct nvkm_gr *base) if (ret) return ret; + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->bundle_size, + 0x100, false, &gr->bundle_cb); + if (ret) + return ret; + memset(gr->tile, 0xff, sizeof(gr->tile)); gr->func->oneinit_tiles(gr); gr->func->oneinit_sm_id(gr); @@ -2051,6 +2067,7 @@ gf100_gr_dtor(struct nvkm_gr *base) kfree(gr->data); + nvkm_memory_unref(&gr->bundle_cb); nvkm_memory_unref(&gr->pagepool); nvkm_falcon_dtor(&gr->gpccs.falcon); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index c74cc23859a5..7ac5e740aece 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -122,6 +122,7 @@ struct gf100_gr { u8 ppc_tpc_max; struct nvkm_memory *pagepool; + struct nvkm_memory *bundle_cb; u8 screen_tile_row_offset; u8 tile[TPC_MAX]; @@ -261,6 +262,7 @@ struct gf100_gr_chan { struct nvkm_vmm *vmm; struct nvkm_vma *pagepool; + struct nvkm_vma *bundle_cb; struct nvkm_memory *mmio; struct nvkm_vma *mmio_vma; -- cgit v1.2.3 From 5eee9fdd69d6e65d2eff9826a638f8da10066e25 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:06 +1000 Subject: drm/nouveau/gr/gf100-: move misc context patching out of attrib_cb funcs Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 4 +++- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 9 ++++++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c | 9 ++++---- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c | 22 ++++++++------------ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 25 +++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 2 ++ 6 files changed, 51 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 3d06ca63e532..076861eebc29 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1396,7 +1396,9 @@ gf100_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) grctx->bundle(chan, chan->bundle_cb->addr, grctx->bundle_size); grctx->attrib(info); if (grctx->patch_ltc) - grctx->patch_ltc(info); + grctx->patch_ltc(chan); + if (grctx->unknown_size) + grctx->unknown(chan, chan->unknown->addr, grctx->unknown_size); grctx->unkn(gr); gf100_grctx_generate_floorsweep(gr); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 6e5fabf46015..57b778e6b86f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -53,8 +53,11 @@ struct gf100_grctx_func { u32 alpha_nr_max; u32 alpha_nr; u32 gfxp_nr; + /* some other context buffer */ + void (*unknown)(struct gf100_gr_chan *, u64 addr, u32 size); + u32 unknown_size; /* other patch buffer stuff */ - void (*patch_ltc)(struct gf100_grctx *); + void (*patch_ltc)(struct gf100_gr_chan *); /* floorsweeping */ void (*sm_id)(struct gf100_gr *, int gpc, int tpc, int sm); void (*tpc_nr)(struct gf100_gr *, int gpc); @@ -118,7 +121,7 @@ void gk104_grctx_generate_gpc_tpc_nr(struct gf100_gr *); extern const struct gf100_grctx_func gk20a_grctx; void gk104_grctx_generate_pagepool(struct gf100_gr_chan *, u64); void gk104_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32); -void gk104_grctx_generate_patch_ltc(struct gf100_grctx *); +void gk104_grctx_generate_patch_ltc(struct gf100_gr_chan *); void gk104_grctx_generate_unkn(struct gf100_gr *); void gk104_grctx_generate_r418800(struct gf100_gr *); @@ -164,6 +167,8 @@ void gv100_grctx_generate_attrib(struct gf100_grctx *); void gv100_grctx_generate_rop_mapping(struct gf100_gr *); void gv100_grctx_generate_r400088(struct gf100_gr *, bool); +void tu102_grctx_generate_unknown(struct gf100_gr_chan *, u64, u32); + /* context init value lists */ extern const struct gf100_gr_pack gf100_grctx_pack_icmd[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index d897090e829c..ec347405c3d8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -861,14 +861,15 @@ gk104_grctx_generate_r418800(struct gf100_gr *gr) } void -gk104_grctx_generate_patch_ltc(struct gf100_grctx *info) +gk104_grctx_generate_patch_ltc(struct gf100_gr_chan *chan) { - struct nvkm_device *device = info->gr->base.engine.subdev.device; + struct nvkm_device *device = chan->gr->base.engine.subdev.device; u32 data0 = nvkm_rd32(device, 0x17e91c); u32 data1 = nvkm_rd32(device, 0x17e920); + /*XXX: Figure out how to modify this correctly! */ - mmio_wr32(info, 0x17e91c, data0); - mmio_wr32(info, 0x17e920, data1); + gf100_grctx_patch_wr32(chan, 0x17e91c, data0); + gf100_grctx_patch_wr32(chan, 0x17e920, data1); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c index 2299ca07d04a..1abad38c6767 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c @@ -53,19 +53,13 @@ tu102_grctx_pack_sw_veid_bundle_init[] = { {} }; -static void -tu102_grctx_generate_attrib(struct gf100_grctx *info) +void +tu102_grctx_generate_unknown(struct gf100_gr_chan *chan, u64 addr, u32 size) { - const u64 size = 0x80000; /*XXX: educated guess */ - const int s = 8; - const int b = mmio_vram(info, size, (1 << s), true); - - gv100_grctx_generate_attrib(info); - - mmio_refn(info, 0x408070, 0x00000000, s, b); - mmio_wr32(info, 0x408074, size >> s); /*XXX: guess */ - mmio_refn(info, 0x419034, 0x00000000, s, b); - mmio_wr32(info, 0x408078, 0x00000000); + gf100_grctx_patch_wr32(chan, 0x408070, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x408074, size >> 8); /*XXX: guess */ + gf100_grctx_patch_wr32(chan, 0x419034, addr >> 8); + gf100_grctx_patch_wr32(chan, 0x408078, 0x00000000); } const struct gf100_grctx_func @@ -80,9 +74,11 @@ tu102_grctx = { .bundle_token_limit = 0xa80, .pagepool = gp100_grctx_generate_pagepool, .pagepool_size = 0x20000, - .attrib = tu102_grctx_generate_attrib, + .attrib = gv100_grctx_generate_attrib, .attrib_nr_max = 0x800, .attrib_nr = 0x700, + .unknown_size = 0x80000, + .unknown = tu102_grctx_generate_unknown, .alpha_nr_max = 0xc00, .alpha_nr = 0x800, .gfxp_nr = 0xfa8, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 0a45e78a2f83..5d1e45b635b9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -365,6 +365,7 @@ gf100_gr_chan_dtor(struct nvkm_object *object) nvkm_vmm_put(chan->vmm, &chan->mmio_vma); nvkm_memory_unref(&chan->mmio); + nvkm_vmm_put(chan->vmm, &chan->unknown); nvkm_vmm_put(chan->vmm, &chan->bundle_cb); nvkm_vmm_put(chan->vmm, &chan->pagepool); nvkm_vmm_unref(&chan->vmm); @@ -415,6 +416,18 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, if (ret) return ret; + /* Map some context buffer of unknown purpose. */ + if (gr->func->grctx->unknown_size) { + ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->unknown), &chan->unknown); + if (ret) + return ret; + + ret = nvkm_memory_map(gr->unknown, 0, chan->vmm, chan->unknown, + &args, sizeof(args)); + if (ret) + return ret; + } + /* Generate golden context image. */ mutex_lock(&gr->fecs.mutex); if (gr->data == NULL) { @@ -485,6 +498,10 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data); mmio++; } + if (gr->func->grctx->patch_ltc) + gr->func->grctx->patch_ltc(chan); + if (gr->func->grctx->unknown_size) + gr->func->grctx->unknown(chan, chan->unknown->addr, gr->func->grctx->unknown_size); nvkm_done(chan->mmio); return 0; } @@ -1998,6 +2015,13 @@ gf100_gr_oneinit(struct nvkm_gr *base) if (ret) return ret; + if (gr->func->grctx->unknown_size) { + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->unknown_size, + 0x100, false, &gr->unknown); + if (ret) + return ret; + } + memset(gr->tile, 0xff, sizeof(gr->tile)); gr->func->oneinit_tiles(gr); gr->func->oneinit_sm_id(gr); @@ -2067,6 +2091,7 @@ gf100_gr_dtor(struct nvkm_gr *base) kfree(gr->data); + nvkm_memory_unref(&gr->unknown); nvkm_memory_unref(&gr->bundle_cb); nvkm_memory_unref(&gr->pagepool); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 7ac5e740aece..ae3eee650d8e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -123,6 +123,7 @@ struct gf100_gr { struct nvkm_memory *pagepool; struct nvkm_memory *bundle_cb; + struct nvkm_memory *unknown; u8 screen_tile_row_offset; u8 tile[TPC_MAX]; @@ -263,6 +264,7 @@ struct gf100_gr_chan { struct nvkm_vma *pagepool; struct nvkm_vma *bundle_cb; + struct nvkm_vma *unknown; struct nvkm_memory *mmio; struct nvkm_vma *mmio_vma; -- cgit v1.2.3 From 78a43c7e3b2ff5aed1809f93b4f87a418355789e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:07 +1000 Subject: drm/nouveau/gr/gf100-: make global attrib_cb actually global This was thought to be per-channel initially - it's not. The backing pages for the VMM mappings are shared for all channels. - switches to more straight-forward patch interfaces - prepares for sub-context support - this is saving a *sizeable* amount of vram v2: - whitespace Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 86 +++++++--------------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 42 +++++------ drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c | 21 +++--- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c | 22 +++--- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c | 7 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c | 36 +++++---- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c | 7 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c | 65 +++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c | 58 ++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c | 50 +++++++------ drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 72 +++++++----------- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 22 +----- 23 files changed, 241 insertions(+), 269 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 076861eebc29..332590f861fb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1003,45 +1003,6 @@ gf100_grctx_patch_wr32(struct gf100_gr_chan *chan, u32 addr, u32 data) nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data); } -int -gf100_grctx_mmio_data(struct gf100_grctx *info, u32 size, u32 align, bool priv) -{ - if (info->data) { - info->buffer[info->buffer_nr] = round_up(info->addr, align); - info->addr = info->buffer[info->buffer_nr] + size; - info->data->size = size; - info->data->align = align; - info->data->priv = priv; - info->data++; - return info->buffer_nr++; - } - return -1; -} - -void -gf100_grctx_mmio_item(struct gf100_grctx *info, u32 addr, u32 data, - int shift, int buffer) -{ - struct nvkm_device *device = info->gr->base.engine.subdev.device; - if (info->data) { - if (shift >= 0) { - info->mmio->addr = addr; - info->mmio->data = data; - info->mmio->shift = shift; - info->mmio->buffer = buffer; - if (buffer >= 0) - data |= info->buffer[buffer] >> shift; - info->mmio++; - } else - return; - } else { - if (buffer >= 0) - return; - } - - nvkm_wr32(device, addr, data); -} - void gf100_grctx_generate_r419cb8(struct gf100_gr *gr) { @@ -1068,31 +1029,41 @@ gf100_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr) } void -gf100_grctx_generate_attrib(struct gf100_grctx *info) +gf100_grctx_generate_attrib(struct gf100_gr_chan *chan) { - struct gf100_gr *gr = info->gr; + struct gf100_gr *gr = chan->gr; const struct gf100_grctx_func *grctx = gr->func->grctx; const u32 attrib = grctx->attrib_nr; - const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); - const int s = 12; - const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false); int gpc, tpc; u32 bo = 0; - mmio_refn(info, 0x418810, 0x80000000, s, b); - mmio_refn(info, 0x419848, 0x10000000, s, b); - mmio_wr32(info, 0x405830, (attrib << 16)); + gf100_grctx_patch_wr32(chan, 0x405830, (attrib << 16)); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { const u32 o = TPC_UNIT(gpc, tpc, 0x0520); - mmio_skip(info, o, (attrib << 16) | ++bo); - mmio_wr32(info, o, (attrib << 16) | --bo); + + gf100_grctx_patch_wr32(chan, o, (attrib << 16) | bo); bo += grctx->attrib_nr_max; } } } +void +gf100_grctx_generate_attrib_cb(struct gf100_gr_chan *chan, u64 addr, u32 size) +{ + gf100_grctx_patch_wr32(chan, 0x418810, 0x80000000 | addr >> 12); + gf100_grctx_patch_wr32(chan, 0x419848, 0x10000000 | addr >> 12); +} + +u32 +gf100_grctx_generate_attrib_cb_size(struct gf100_gr *gr) +{ + const struct gf100_grctx_func *grctx = gr->func->grctx; + + return 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max) * gr->tpc_total; +} + void gf100_grctx_generate_unkn(struct gf100_gr *gr) { @@ -1368,7 +1339,7 @@ gf100_grctx_generate_floorsweep(struct gf100_gr *gr) } void -gf100_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) +gf100_grctx_generate_main(struct gf100_gr_chan *chan) { struct gf100_gr *gr = chan->gr; struct nvkm_device *device = gr->base.engine.subdev.device; @@ -1394,7 +1365,8 @@ gf100_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) grctx->pagepool(chan, chan->pagepool->addr); grctx->bundle(chan, chan->bundle_cb->addr, grctx->bundle_size); - grctx->attrib(info); + grctx->attrib_cb(chan, chan->attrib_cb->addr, grctx->attrib_cb_size(gr)); + grctx->attrib(chan); if (grctx->patch_ltc) grctx->patch_ltc(chan); if (grctx->unknown_size) @@ -1450,7 +1422,6 @@ gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvk struct nvkm_device *device = subdev->device; struct nvkm_memory *data = NULL; struct nvkm_vma *ctx = NULL; - struct gf100_grctx info; int ret, i; u64 addr; @@ -1500,13 +1471,6 @@ gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvk nvkm_wo32(inst, 0x0214, upper_32_bits(ctx->addr + CB_RESERVED)); nvkm_done(inst); - /* Setup default state for mmio list construction. */ - info.gr = gr; - info.data = gr->mmio_data; - info.mmio = gr->mmio_list; - info.addr = ctx->addr; - info.buffer_nr = 0; - /* Make channel current. */ addr = inst->addr >> 12; if (gr->firmware) { @@ -1530,7 +1494,7 @@ gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvk ); } - grctx->main(chan, &info); + grctx->main(chan); /* Trigger a context unload by unsetting the "next channel valid" bit * and faking a context switch interrupt. @@ -1582,6 +1546,8 @@ gf100_grctx = { .bundle_size = 0x1800, .pagepool = gf100_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf100_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 57b778e6b86f..99bb9af4955a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -3,28 +3,12 @@ #define __NVKM_GRCTX_NVC0_H__ #include "gf100.h" -struct gf100_grctx { - struct gf100_gr *gr; - struct gf100_gr_data *data; - struct gf100_gr_mmio *mmio; - int buffer_nr; - u64 buffer[4]; - u64 addr; -}; - -int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, bool priv); -void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int); void gf100_grctx_patch_wr32(struct gf100_gr_chan *, u32 addr, u32 data); -#define mmio_vram(a,b,c,d) gf100_grctx_mmio_data((a), (b), (c), (d)) -#define mmio_refn(a,b,c,d,e) gf100_grctx_mmio_item((a), (b), (c), (d), (e)) -#define mmio_skip(a,b,c) mmio_refn((a), (b), (c), -1, -1) -#define mmio_wr32(a,b,c) mmio_refn((a), (b), (c), 0, -1) - struct gf100_grctx_func { void (*unkn88c)(struct gf100_gr *, bool on); /* main context generation function */ - void (*main)(struct gf100_gr_chan *, struct gf100_grctx *); + void (*main)(struct gf100_gr_chan *); /* context-specific modify-on-first-load list generation function */ void (*unkn)(struct gf100_gr *); /* mmio context data */ @@ -47,7 +31,9 @@ struct gf100_grctx_func { void (*pagepool)(struct gf100_gr_chan *, u64 addr); u32 pagepool_size; /* attribute(/alpha) circular buffer */ - void (*attrib)(struct gf100_grctx *); + u32 (*attrib_cb_size)(struct gf100_gr *); + void (*attrib_cb)(struct gf100_gr_chan *, u64 addr, u32 size); + void (*attrib)(struct gf100_gr_chan *); u32 attrib_nr_max; u32 attrib_nr; u32 alpha_nr_max; @@ -86,10 +72,12 @@ struct gf100_grctx_func { extern const struct gf100_grctx_func gf100_grctx; int gf100_grctx_generate(struct gf100_gr *, struct gf100_gr_chan *, struct nvkm_gpuobj *inst); -void gf100_grctx_generate_main(struct gf100_gr_chan *, struct gf100_grctx *); +void gf100_grctx_generate_main(struct gf100_gr_chan *); void gf100_grctx_generate_pagepool(struct gf100_gr_chan *, u64); void gf100_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32); -void gf100_grctx_generate_attrib(struct gf100_grctx *); +u32 gf100_grctx_generate_attrib_cb_size(struct gf100_gr *); +void gf100_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32); +void gf100_grctx_generate_attrib(struct gf100_gr_chan *); void gf100_grctx_generate_unkn(struct gf100_gr *); void gf100_grctx_generate_floorsweep(struct gf100_gr *); void gf100_grctx_generate_sm_id(struct gf100_gr *, int, int, int); @@ -101,14 +89,14 @@ void gf100_grctx_generate_max_ways_evict(struct gf100_gr *); void gf100_grctx_generate_r419cb8(struct gf100_gr *); extern const struct gf100_grctx_func gf108_grctx; -void gf108_grctx_generate_attrib(struct gf100_grctx *); +void gf108_grctx_generate_attrib(struct gf100_gr_chan *); void gf108_grctx_generate_unkn(struct gf100_gr *); extern const struct gf100_grctx_func gf104_grctx; extern const struct gf100_grctx_func gf110_grctx; extern const struct gf100_grctx_func gf117_grctx; -void gf117_grctx_generate_attrib(struct gf100_grctx *); +void gf117_grctx_generate_attrib(struct gf100_gr_chan *); void gf117_grctx_generate_rop_mapping(struct gf100_gr *); void gf117_grctx_generate_dist_skip_table(struct gf100_gr *); @@ -134,7 +122,8 @@ extern const struct gf100_grctx_func gk208_grctx; extern const struct gf100_grctx_func gm107_grctx; void gm107_grctx_generate_pagepool(struct gf100_gr_chan *, u64); void gm107_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32); -void gm107_grctx_generate_attrib(struct gf100_grctx *); +void gm107_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32); +void gm107_grctx_generate_attrib(struct gf100_gr_chan *); void gm107_grctx_generate_sm_id(struct gf100_gr *, int, int, int); extern const struct gf100_grctx_func gm200_grctx; @@ -148,10 +137,12 @@ extern const struct gf100_grctx_func gm20b_grctx; extern const struct gf100_grctx_func gp100_grctx; void gp100_grctx_generate_pagepool(struct gf100_gr_chan *, u64); +void gp100_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32); void gp100_grctx_generate_smid_config(struct gf100_gr *); extern const struct gf100_grctx_func gp102_grctx; -void gp102_grctx_generate_attrib(struct gf100_grctx *); +u32 gp102_grctx_generate_attrib_cb_size(struct gf100_gr *); +void gp102_grctx_generate_attrib(struct gf100_gr_chan *); extern const struct gf100_grctx_func gp104_grctx; @@ -163,7 +154,8 @@ extern const struct gf100_grctx_func tu102_grctx; void gv100_grctx_unkn88c(struct gf100_gr *, bool); void gv100_grctx_generate_unkn(struct gf100_gr *); extern const struct gf100_gr_init gv100_grctx_init_sw_veid_bundle_init_0[]; -void gv100_grctx_generate_attrib(struct gf100_grctx *); +void gv100_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32); +void gv100_grctx_generate_attrib(struct gf100_gr_chan *); void gv100_grctx_generate_rop_mapping(struct gf100_gr *); void gv100_grctx_generate_r400088(struct gf100_gr *, bool); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c index 7a0564b6e3c7..ba63a3b46518 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c @@ -94,6 +94,8 @@ gf104_grctx = { .bundle_size = 0x1800, .pagepool = gf100_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf100_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c index dda2c32e6232..0bc2eab6ad98 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c @@ -733,25 +733,20 @@ gf108_grctx_pack_tpc[] = { ******************************************************************************/ void -gf108_grctx_generate_attrib(struct gf100_grctx *info) +gf108_grctx_generate_attrib(struct gf100_gr_chan *chan) { - struct gf100_gr *gr = info->gr; + struct gf100_gr *gr = chan->gr; const struct gf100_grctx_func *grctx = gr->func->grctx; const u32 alpha = grctx->alpha_nr; const u32 beta = grctx->attrib_nr; - const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); - const int s = 12; - const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false); const int timeslice_mode = 1; const int max_batches = 0xffff; u32 bo = 0; u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total; int gpc, tpc; - mmio_refn(info, 0x418810, 0x80000000, s, b); - mmio_refn(info, 0x419848, 0x10000000, s, b); - mmio_wr32(info, 0x405830, (beta << 16) | alpha); - mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); + gf100_grctx_patch_wr32(chan, 0x405830, (beta << 16) | alpha); + gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { @@ -759,10 +754,10 @@ gf108_grctx_generate_attrib(struct gf100_grctx *info) const u32 b = beta; const u32 t = timeslice_mode; const u32 o = TPC_UNIT(gpc, tpc, 0x500); - mmio_skip(info, o + 0x20, (t << 28) | (b << 16) | ++bo); - mmio_wr32(info, o + 0x20, (t << 28) | (b << 16) | --bo); + + gf100_grctx_patch_wr32(chan, o + 0x20, (t << 28) | (b << 16) | bo); bo += grctx->attrib_nr_max; - mmio_wr32(info, o + 0x44, (a << 16) | ao); + gf100_grctx_patch_wr32(chan, o + 0x44, (a << 16) | ao); ao += grctx->alpha_nr_max; } } @@ -795,6 +790,8 @@ gf108_grctx = { .bundle_size = 0x1800, .pagepool = gf100_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf108_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c index f5cca5e6a4f2..64b723b0afb5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c @@ -342,6 +342,8 @@ gf110_grctx = { .bundle_size = 0x1800, .pagepool = gf100_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf100_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c index 276c282d19aa..6c1f631eebd5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c @@ -241,25 +241,20 @@ gf117_grctx_generate_rop_mapping(struct gf100_gr *gr) } void -gf117_grctx_generate_attrib(struct gf100_grctx *info) +gf117_grctx_generate_attrib(struct gf100_gr_chan *chan) { - struct gf100_gr *gr = info->gr; + struct gf100_gr *gr = chan->gr; const struct gf100_grctx_func *grctx = gr->func->grctx; const u32 alpha = grctx->alpha_nr; const u32 beta = grctx->attrib_nr; - const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); - const int s = 12; - const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false); const int timeslice_mode = 1; const int max_batches = 0xffff; u32 bo = 0; u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total; int gpc, ppc; - mmio_refn(info, 0x418810, 0x80000000, s, b); - mmio_refn(info, 0x419848, 0x10000000, s, b); - mmio_wr32(info, 0x405830, (beta << 16) | alpha); - mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); + gf100_grctx_patch_wr32(chan, 0x405830, (beta << 16) | alpha); + gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) { @@ -267,12 +262,13 @@ gf117_grctx_generate_attrib(struct gf100_grctx *info) const u32 b = beta * gr->ppc_tpc_nr[gpc][ppc]; const u32 t = timeslice_mode; const u32 o = PPC_UNIT(gpc, ppc, 0); + if (!(gr->ppc_mask[gpc] & (1 << ppc))) continue; - mmio_skip(info, o + 0xc0, (t << 28) | (b << 16) | ++bo); - mmio_wr32(info, o + 0xc0, (t << 28) | (b << 16) | --bo); + + gf100_grctx_patch_wr32(chan, o + 0xc0, (t << 28) | (b << 16) | bo); bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc]; - mmio_wr32(info, o + 0xe4, (a << 16) | ao); + gf100_grctx_patch_wr32(chan, o + 0xe4, (a << 16) | ao); ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc]; } } @@ -294,6 +290,8 @@ gf117_grctx = { .bundle_size = 0x1800, .pagepool = gf100_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf117_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c index 0cfe46366af6..426ad1b8d426 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c @@ -510,6 +510,8 @@ gf119_grctx = { .bundle_size = 0x1800, .pagepool = gf100_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf108_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index ec347405c3d8..94233d0119df 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -981,6 +981,8 @@ gk104_grctx = { .bundle_token_limit = 0x600, .pagepool = gk104_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf117_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c index 86547cfc38dc..4391458e1fb2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c @@ -838,6 +838,8 @@ gk110_grctx = { .bundle_token_limit = 0x7c0, .pagepool = gk104_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf117_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c index ebb947bd1446..7b9a34f9ec3c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c @@ -87,6 +87,8 @@ gk110b_grctx = { .bundle_token_limit = 0x600, .pagepool = gk104_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf117_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c index 4d40512b5c99..c78d07a8bb7d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c @@ -553,6 +553,8 @@ gk208_grctx = { .bundle_token_limit = 0x200, .pagepool = gk104_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf117_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c index 2380ecce8cd6..ac5fdcb5cd3f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c @@ -25,7 +25,7 @@ #include static void -gk20a_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) +gk20a_grctx_generate_main(struct gf100_gr_chan *chan) { struct gf100_gr *gr = chan->gr; struct nvkm_device *device = gr->base.engine.subdev.device; @@ -39,7 +39,8 @@ gk20a_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000); - grctx->attrib(info); + grctx->attrib_cb(chan, chan->attrib_cb->addr, grctx->attrib_cb_size(gr)); + grctx->attrib(chan); grctx->unkn(gr); @@ -75,6 +76,8 @@ gk20a_grctx = { .bundle_token_limit = 0x100, .pagepool = gk104_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gf100_grctx_generate_attrib_cb, .attrib = gf117_grctx_generate_attrib, .attrib_nr_max = 0x240, .attrib_nr = 0x240, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index d968bcdfa90d..019c698eb5a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -897,25 +897,19 @@ gm107_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr) } void -gm107_grctx_generate_attrib(struct gf100_grctx *info) +gm107_grctx_generate_attrib(struct gf100_gr_chan *chan) { - struct gf100_gr *gr = info->gr; + struct gf100_gr *gr = chan->gr; const struct gf100_grctx_func *grctx = gr->func->grctx; const u32 alpha = grctx->alpha_nr; const u32 attrib = grctx->attrib_nr; - const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); - const int s = 12; - const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false); const int max_batches = 0xffff; u32 bo = 0; u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total; int gpc, ppc, n = 0; - mmio_refn(info, 0x418810, 0x80000000, s, b); - mmio_refn(info, 0x419848, 0x10000000, s, b); - mmio_refn(info, 0x419c2c, 0x10000000, s, b); - mmio_wr32(info, 0x405830, (attrib << 16) | alpha); - mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); + gf100_grctx_patch_wr32(chan, 0x405830, (attrib << 16) | alpha); + gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { @@ -923,19 +917,29 @@ gm107_grctx_generate_attrib(struct gf100_grctx *info) const u32 bs = attrib * gr->ppc_tpc_nr[gpc][ppc]; const u32 u = 0x418ea0 + (n * 0x04); const u32 o = PPC_UNIT(gpc, ppc, 0); + if (!(gr->ppc_mask[gpc] & (1 << ppc))) continue; - mmio_wr32(info, o + 0xc0, bs); - mmio_wr32(info, o + 0xf4, bo); + + gf100_grctx_patch_wr32(chan, o + 0xc0, bs); + gf100_grctx_patch_wr32(chan, o + 0xf4, bo); bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc]; - mmio_wr32(info, o + 0xe4, as); - mmio_wr32(info, o + 0xf8, ao); + gf100_grctx_patch_wr32(chan, o + 0xe4, as); + gf100_grctx_patch_wr32(chan, o + 0xf8, ao); ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc]; - mmio_wr32(info, u, ((bs / 3) << 16) | bs); + gf100_grctx_patch_wr32(chan, u, ((bs / 3) << 16) | bs); } } } +void +gm107_grctx_generate_attrib_cb(struct gf100_gr_chan *chan, u64 addr, u32 size) +{ + gf100_grctx_generate_attrib_cb(chan, addr, size); + + gf100_grctx_patch_wr32(chan, 0x419c2c, 0x10000000 | addr >> 12); +} + static void gm107_grctx_generate_r406500(struct gf100_gr *gr) { @@ -969,6 +973,8 @@ gm107_grctx = { .bundle_token_limit = 0x2c0, .pagepool = gm107_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gm107_grctx_generate_attrib_cb, .attrib = gm107_grctx_generate_attrib, .attrib_nr_max = 0xff0, .attrib_nr = 0xaa0, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c index 013d05a0f0f6..6b7034b2ff76 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c @@ -111,6 +111,8 @@ gm200_grctx = { .bundle_token_limit = 0x780, .pagepool = gm107_grctx_generate_pagepool, .pagepool_size = 0x20000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gm107_grctx_generate_attrib_cb, .attrib = gm107_grctx_generate_attrib, .attrib_nr_max = 0x600, .attrib_nr = 0x400, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c index cb02b02a4c86..b8edccfada58 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c @@ -22,7 +22,7 @@ #include "ctxgf100.h" static void -gm20b_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) +gm20b_grctx_generate_main(struct gf100_gr_chan *chan) { struct gf100_gr *gr = chan->gr; struct nvkm_device *device = gr->base.engine.subdev.device; @@ -36,7 +36,8 @@ gm20b_grctx_generate_main(struct gf100_gr_chan *chan, struct gf100_grctx *info) idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000); - grctx->attrib(info); + grctx->attrib_cb(chan, chan->attrib_cb->addr, grctx->attrib_cb_size(gr)); + grctx->attrib(chan); grctx->unkn(gr); @@ -78,6 +79,8 @@ gm20b_grctx = { .bundle_token_limit = 0x1c0, .pagepool = gm107_grctx_generate_pagepool, .pagepool_size = 0x8000, + .attrib_cb_size = gf100_grctx_generate_attrib_cb_size, + .attrib_cb = gm107_grctx_generate_attrib_cb, .attrib = gm107_grctx_generate_attrib, .attrib_nr_max = 0x600, .attrib_nr = 0x400, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c index b2fa7c943c49..d8977caa0d04 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c @@ -39,32 +39,21 @@ gp100_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr) } static void -gp100_grctx_generate_attrib(struct gf100_grctx *info) +gp100_grctx_generate_attrib(struct gf100_gr_chan *chan) { - struct gf100_gr *gr = info->gr; + struct gf100_gr *gr = chan->gr; const struct gf100_grctx_func *grctx = gr->func->grctx; const u32 alpha = grctx->alpha_nr; const u32 attrib = grctx->attrib_nr; - const int s = 12; const int max_batches = 0xffff; u32 size = grctx->alpha_nr_max * gr->tpc_total; u32 ao = 0; u32 bo = ao + size; - int gpc, ppc, b, n = 0; + int gpc, ppc, n = 0; - for (gpc = 0; gpc < gr->gpc_nr; gpc++) - size += grctx->attrib_nr_max * gr->ppc_nr[gpc] * gr->ppc_tpc_max; - size = ((size * 0x20) + 128) & ~127; - b = mmio_vram(info, size, (1 << s), false); - - mmio_refn(info, 0x418810, 0x80000000, s, b); - mmio_refn(info, 0x419848, 0x10000000, s, b); - mmio_refn(info, 0x419c2c, 0x10000000, s, b); - mmio_refn(info, 0x419b00, 0x00000000, s, b); - mmio_wr32(info, 0x419b04, 0x80000000 | size >> 7); - mmio_wr32(info, 0x405830, attrib); - mmio_wr32(info, 0x40585c, alpha); - mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); + gf100_grctx_patch_wr32(chan, 0x405830, attrib); + gf100_grctx_patch_wr32(chan, 0x40585c, alpha); + gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { @@ -72,21 +61,45 @@ gp100_grctx_generate_attrib(struct gf100_grctx *info) const u32 bs = attrib * gr->ppc_tpc_max; const u32 u = 0x418ea0 + (n * 0x04); const u32 o = PPC_UNIT(gpc, ppc, 0); + if (!(gr->ppc_mask[gpc] & (1 << ppc))) continue; - mmio_wr32(info, o + 0xc0, bs); - mmio_wr32(info, o + 0xf4, bo); - mmio_wr32(info, o + 0xf0, bs); + + gf100_grctx_patch_wr32(chan, o + 0xc0, bs); + gf100_grctx_patch_wr32(chan, o + 0xf4, bo); + gf100_grctx_patch_wr32(chan, o + 0xf0, bs); bo += grctx->attrib_nr_max * gr->ppc_tpc_max; - mmio_wr32(info, o + 0xe4, as); - mmio_wr32(info, o + 0xf8, ao); + gf100_grctx_patch_wr32(chan, o + 0xe4, as); + gf100_grctx_patch_wr32(chan, o + 0xf8, ao); ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc]; - mmio_wr32(info, u, bs); + gf100_grctx_patch_wr32(chan, u, bs); } } - mmio_wr32(info, 0x418eec, 0x00000000); - mmio_wr32(info, 0x41befc, 0x00000000); + gf100_grctx_patch_wr32(chan, 0x418eec, 0x00000000); + gf100_grctx_patch_wr32(chan, 0x41befc, 0x00000000); +} + +void +gp100_grctx_generate_attrib_cb(struct gf100_gr_chan *chan, u64 addr, u32 size) +{ + gm107_grctx_generate_attrib_cb(chan, addr, size); + + gf100_grctx_patch_wr32(chan, 0x419b00, 0x00000000 | addr >> 12); + gf100_grctx_patch_wr32(chan, 0x419b04, 0x80000000 | size >> 7); +} + +static u32 +gp100_grctx_generate_attrib_cb_size(struct gf100_gr *gr) +{ + const struct gf100_grctx_func *grctx = gr->func->grctx; + u32 size = grctx->alpha_nr_max * gr->tpc_total; + int gpc; + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) + size += grctx->attrib_nr_max * gr->func->ppc_nr * gr->ppc_tpc_max; + + return ((size * 0x20) + 128) & ~127; } void @@ -120,6 +133,8 @@ gp100_grctx = { .bundle_token_limit = 0x1080, .pagepool = gp100_grctx_generate_pagepool, .pagepool_size = 0x20000, + .attrib_cb_size = gp100_grctx_generate_attrib_cb_size, + .attrib_cb = gp100_grctx_generate_attrib_cb, .attrib = gp100_grctx_generate_attrib, .attrib_nr_max = 0x660, .attrib_nr = 0x440, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c index daee17bf7d0d..7d372d786b8b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c @@ -37,33 +37,22 @@ gp102_grctx_generate_r408840(struct gf100_gr *gr) } void -gp102_grctx_generate_attrib(struct gf100_grctx *info) +gp102_grctx_generate_attrib(struct gf100_gr_chan *chan) { - struct gf100_gr *gr = info->gr; + struct gf100_gr *gr = chan->gr; const struct gf100_grctx_func *grctx = gr->func->grctx; const u32 alpha = grctx->alpha_nr; const u32 attrib = grctx->attrib_nr; const u32 gfxp = grctx->gfxp_nr; - const int s = 12; const int max_batches = 0xffff; u32 size = grctx->alpha_nr_max * gr->tpc_total; u32 ao = 0; u32 bo = ao + size; - int gpc, ppc, b, n = 0; + int gpc, ppc, n = 0; - for (gpc = 0; gpc < gr->gpc_nr; gpc++) - size += grctx->gfxp_nr * gr->ppc_nr[gpc] * gr->ppc_tpc_max; - size = ((size * 0x20) + 128) & ~127; - b = mmio_vram(info, size, (1 << s), false); - - mmio_refn(info, 0x418810, 0x80000000, s, b); - mmio_refn(info, 0x419848, 0x10000000, s, b); - mmio_refn(info, 0x419c2c, 0x10000000, s, b); - mmio_refn(info, 0x419b00, 0x00000000, s, b); - mmio_wr32(info, 0x419b04, 0x80000000 | size >> 7); - mmio_wr32(info, 0x405830, attrib); - mmio_wr32(info, 0x40585c, alpha); - mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); + gf100_grctx_patch_wr32(chan, 0x405830, attrib); + gf100_grctx_patch_wr32(chan, 0x40585c, alpha); + gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { @@ -73,22 +62,37 @@ gp102_grctx_generate_attrib(struct gf100_grctx *info) const u32 u = 0x418ea0 + (n * 0x04); const u32 o = PPC_UNIT(gpc, ppc, 0); const u32 p = GPC_UNIT(gpc, 0xc44 + (ppc * 4)); + if (!(gr->ppc_mask[gpc] & (1 << ppc))) continue; - mmio_wr32(info, o + 0xc0, gs); - mmio_wr32(info, p, bs); - mmio_wr32(info, o + 0xf4, bo); - mmio_wr32(info, o + 0xf0, bs); + + gf100_grctx_patch_wr32(chan, o + 0xc0, gs); + gf100_grctx_patch_wr32(chan, p, bs); + gf100_grctx_patch_wr32(chan, o + 0xf4, bo); + gf100_grctx_patch_wr32(chan, o + 0xf0, bs); bo += gs; - mmio_wr32(info, o + 0xe4, as); - mmio_wr32(info, o + 0xf8, ao); + gf100_grctx_patch_wr32(chan, o + 0xe4, as); + gf100_grctx_patch_wr32(chan, o + 0xf8, ao); ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc]; - mmio_wr32(info, u, bs); + gf100_grctx_patch_wr32(chan, u, bs); } } - mmio_wr32(info, 0x4181e4, 0x00000100); - mmio_wr32(info, 0x41befc, 0x00000100); + gf100_grctx_patch_wr32(chan, 0x4181e4, 0x00000100); + gf100_grctx_patch_wr32(chan, 0x41befc, 0x00000100); +} + +u32 +gp102_grctx_generate_attrib_cb_size(struct gf100_gr *gr) +{ + const struct gf100_grctx_func *grctx = gr->func->grctx; + u32 size = grctx->alpha_nr_max * gr->tpc_total; + int gpc; + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) + size += grctx->gfxp_nr * gr->func->ppc_nr * gr->ppc_tpc_max; + + return ((size * 0x20) + 127) & ~127; } const struct gf100_grctx_func @@ -101,6 +105,8 @@ gp102_grctx = { .bundle_token_limit = 0x900, .pagepool = gp100_grctx_generate_pagepool, .pagepool_size = 0x20000, + .attrib_cb_size = gp102_grctx_generate_attrib_cb_size, + .attrib_cb = gp100_grctx_generate_attrib_cb, .attrib = gp102_grctx_generate_attrib, .attrib_nr_max = 0x4b0, .attrib_nr = 0x320, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c index 3b85e3d326b2..90b5f793e567 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c @@ -31,6 +31,8 @@ gp104_grctx = { .bundle_token_limit = 0x900, .pagepool = gp100_grctx_generate_pagepool, .pagepool_size = 0x20000, + .attrib_cb_size = gp102_grctx_generate_attrib_cb_size, + .attrib_cb = gp100_grctx_generate_attrib_cb, .attrib = gp102_grctx_generate_attrib, .attrib_nr_max = 0x4b0, .attrib_nr = 0x320, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c index 5060c5ee5ce0..d191761a0471 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c @@ -39,6 +39,8 @@ gp107_grctx = { .bundle_token_limit = 0x300, .pagepool = gp100_grctx_generate_pagepool, .pagepool_size = 0x20000, + .attrib_cb_size = gp102_grctx_generate_attrib_cb_size, + .attrib_cb = gp100_grctx_generate_attrib_cb, .attrib = gp102_grctx_generate_attrib, .attrib_nr_max = 0x15de, .attrib_nr = 0x540, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c index 39553d55d3f3..c2e5d43b1c37 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c @@ -59,31 +59,20 @@ gv100_grctx_pack_sw_veid_bundle_init[] = { }; void -gv100_grctx_generate_attrib(struct gf100_grctx *info) +gv100_grctx_generate_attrib(struct gf100_gr_chan *chan) { - struct gf100_gr *gr = info->gr; + struct gf100_gr *gr = chan->gr; const struct gf100_grctx_func *grctx = gr->func->grctx; const u32 alpha = grctx->alpha_nr; const u32 attrib = grctx->attrib_nr; const u32 gfxp = grctx->gfxp_nr; - const int s = 12; u32 size = grctx->alpha_nr_max * gr->tpc_total; u32 ao = 0; u32 bo = ao + size; - int gpc, ppc, b, n = 0; + int gpc, ppc, n = 0; - for (gpc = 0; gpc < gr->gpc_nr; gpc++) - size += grctx->gfxp_nr * gr->ppc_nr[gpc] * gr->ppc_tpc_max; - size = ((size * 0x20) + 127) & ~127; - b = mmio_vram(info, size, (1 << s), false); - - mmio_refn(info, 0x418810, 0x80000000, s, b); - mmio_refn(info, 0x419848, 0x10000000, s, b); - mmio_refn(info, 0x419c2c, 0x10000000, s, b); - mmio_refn(info, 0x419e00, 0x00000000, s, b); - mmio_wr32(info, 0x419e04, 0x80000000 | size >> 7); - mmio_wr32(info, 0x405830, attrib); - mmio_wr32(info, 0x40585c, alpha); + gf100_grctx_patch_wr32(chan, 0x405830, attrib); + gf100_grctx_patch_wr32(chan, 0x40585c, alpha); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { @@ -92,21 +81,32 @@ gv100_grctx_generate_attrib(struct gf100_grctx *info) const u32 gs = gfxp * gr->ppc_tpc_max; const u32 u = 0x418ea0 + (n * 0x04); const u32 o = PPC_UNIT(gpc, ppc, 0); + if (!(gr->ppc_mask[gpc] & (1 << ppc))) continue; - mmio_wr32(info, o + 0xc0, gs); - mmio_wr32(info, o + 0xf4, bo); - mmio_wr32(info, o + 0xf0, bs); + + gf100_grctx_patch_wr32(chan, o + 0xc0, gs); + gf100_grctx_patch_wr32(chan, o + 0xf4, bo); + gf100_grctx_patch_wr32(chan, o + 0xf0, bs); bo += gs; - mmio_wr32(info, o + 0xe4, as); - mmio_wr32(info, o + 0xf8, ao); + gf100_grctx_patch_wr32(chan, o + 0xe4, as); + gf100_grctx_patch_wr32(chan, o + 0xf8, ao); ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc]; - mmio_wr32(info, u, bs); + gf100_grctx_patch_wr32(chan, u, bs); } } - mmio_wr32(info, 0x4181e4, 0x00000100); - mmio_wr32(info, 0x41befc, 0x00000100); + gf100_grctx_patch_wr32(chan, 0x4181e4, 0x00000100); + gf100_grctx_patch_wr32(chan, 0x41befc, 0x00000100); +} + +void +gv100_grctx_generate_attrib_cb(struct gf100_gr_chan *chan, u64 addr, u32 size) +{ + gm107_grctx_generate_attrib_cb(chan, addr, size); + + gf100_grctx_patch_wr32(chan, 0x419e00, 0x00000000 | addr >> 12); + gf100_grctx_patch_wr32(chan, 0x419e04, 0x80000000 | size >> 7); } void @@ -198,6 +198,8 @@ gv100_grctx = { .bundle_token_limit = 0x1680, .pagepool = gp100_grctx_generate_pagepool, .pagepool_size = 0x20000, + .attrib_cb_size = gp102_grctx_generate_attrib_cb_size, + .attrib_cb = gv100_grctx_generate_attrib_cb, .attrib = gv100_grctx_generate_attrib, .attrib_nr_max = 0x6c0, .attrib_nr = 0x480, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c index 1abad38c6767..1a151e89ea05 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c @@ -74,6 +74,8 @@ tu102_grctx = { .bundle_token_limit = 0xa80, .pagepool = gp100_grctx_generate_pagepool, .pagepool_size = 0x20000, + .attrib_cb_size = gp102_grctx_generate_attrib_cb_size, + .attrib_cb = gv100_grctx_generate_attrib_cb, .attrib = gv100_grctx_generate_attrib, .attrib_nr_max = 0x800, .attrib_nr = 0x700, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 5d1e45b635b9..09141b1b4220 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -355,16 +355,11 @@ static void * gf100_gr_chan_dtor(struct nvkm_object *object) { struct gf100_gr_chan *chan = gf100_gr_chan(object); - int i; - - for (i = 0; i < ARRAY_SIZE(chan->data); i++) { - nvkm_vmm_put(chan->vmm, &chan->data[i].vma); - nvkm_memory_unref(&chan->data[i].mem); - } nvkm_vmm_put(chan->vmm, &chan->mmio_vma); nvkm_memory_unref(&chan->mmio); + nvkm_vmm_put(chan->vmm, &chan->attrib_cb); nvkm_vmm_put(chan->vmm, &chan->unknown); nvkm_vmm_put(chan->vmm, &chan->bundle_cb); nvkm_vmm_put(chan->vmm, &chan->pagepool); @@ -384,12 +379,10 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, struct nvkm_object **pobject) { struct gf100_gr *gr = gf100_gr(base); - struct gf100_gr_data *data = gr->mmio_data; - struct gf100_gr_mmio *mmio = gr->mmio_list; struct gf100_gr_chan *chan; struct gf100_vmm_map_v0 args = { .priv = 1 }; struct nvkm_device *device = gr->base.engine.subdev.device; - int ret, i; + int ret; if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) return -ENOMEM; @@ -416,6 +409,22 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, if (ret) return ret; + /* Map attribute circular buffer. */ + ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->attrib_cb), &chan->attrib_cb); + if (ret) + return ret; + + if (device->card_type < GP100) { + ret = nvkm_memory_map(gr->attrib_cb, 0, chan->vmm, chan->attrib_cb, NULL, 0); + if (ret) + return ret; + } else { + ret = nvkm_memory_map(gr->attrib_cb, 0, chan->vmm, chan->attrib_cb, + &args, sizeof(args));; + if (ret) + return ret; + } + /* Map some context buffer of unknown purpose. */ if (gr->func->grctx->unknown_size) { ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->unknown), &chan->unknown); @@ -457,47 +466,12 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, if (ret) return ret; - /* allocate buffers referenced by mmio list */ - for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) { - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - data->size, data->align, false, - &chan->data[i].mem); - if (ret) - return ret; - - ret = nvkm_vmm_get(fifoch->vmm, 12, - nvkm_memory_size(chan->data[i].mem), - &chan->data[i].vma); - if (ret) - return ret; - - args.priv = data->priv; - - ret = nvkm_memory_map(chan->data[i].mem, 0, chan->vmm, - chan->data[i].vma, &args, sizeof(args)); - if (ret) - return ret; - - data++; - } - /* finally, fill in the mmio list and point the context at it */ nvkm_kmap(chan->mmio); gr->func->grctx->pagepool(chan, chan->pagepool->addr); gr->func->grctx->bundle(chan, chan->bundle_cb->addr, gr->func->grctx->bundle_size); - for (i = 0; mmio->addr && i < ARRAY_SIZE(gr->mmio_list); i++) { - u32 addr = mmio->addr; - u32 data = mmio->data; - - if (mmio->buffer >= 0) { - u64 info = chan->data[mmio->buffer].vma->addr; - data |= info >> mmio->shift; - } - - nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, addr); - nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data); - mmio++; - } + gr->func->grctx->attrib_cb(chan, chan->attrib_cb->addr, gr->func->grctx->attrib_cb_size(gr)); + gr->func->grctx->attrib(chan); if (gr->func->grctx->patch_ltc) gr->func->grctx->patch_ltc(chan); if (gr->func->grctx->unknown_size) @@ -2015,6 +1989,11 @@ gf100_gr_oneinit(struct nvkm_gr *base) if (ret) return ret; + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->attrib_cb_size(gr), + 0x1000, false, &gr->attrib_cb); + if (ret) + return ret; + if (gr->func->grctx->unknown_size) { ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->unknown_size, 0x100, false, &gr->unknown); @@ -2092,6 +2071,7 @@ gf100_gr_dtor(struct nvkm_gr *base) kfree(gr->data); nvkm_memory_unref(&gr->unknown); + nvkm_memory_unref(&gr->attrib_cb); nvkm_memory_unref(&gr->bundle_cb); nvkm_memory_unref(&gr->pagepool); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index ae3eee650d8e..7f467f6d0462 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -44,19 +44,6 @@ struct nvkm_acr_lsfw; #define PPC_UNIT(t, m, r) (0x503000 + (t) * 0x8000 + (m) * 0x200 + (r)) #define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) -struct gf100_gr_data { - u32 size; - u32 align; - bool priv; -}; - -struct gf100_gr_mmio { - u32 addr; - u32 data; - u32 shift; - int buffer; -}; - struct gf100_gr_zbc_color { u32 format; u32 ds[4]; @@ -123,6 +110,7 @@ struct gf100_gr { struct nvkm_memory *pagepool; struct nvkm_memory *bundle_cb; + struct nvkm_memory *attrib_cb; struct nvkm_memory *unknown; u8 screen_tile_row_offset; @@ -134,8 +122,6 @@ struct gf100_gr { } sm[TPC_MAX]; u8 sm_nr; - struct gf100_gr_data mmio_data[4]; - struct gf100_gr_mmio mmio_list[4096/8]; u32 size; u32 *data; u32 size_zcull; @@ -264,16 +250,12 @@ struct gf100_gr_chan { struct nvkm_vma *pagepool; struct nvkm_vma *bundle_cb; + struct nvkm_vma *attrib_cb; struct nvkm_vma *unknown; struct nvkm_memory *mmio; struct nvkm_vma *mmio_vma; int mmio_nr; - - struct { - struct nvkm_memory *mem; - struct nvkm_vma *vma; - } data[4]; }; void gf100_gr_ctxctl_debug(struct gf100_gr *); -- cgit v1.2.3 From 6c55b5947b174cce16fcc56dc79f50df2b48e737 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:07 +1000 Subject: drm/nouveau/gr/gf100-: stop using NV_PGRAPH_FECS_CTXSW_MAILBOX_CLEAR This doesn't work on Ampere for some reason, switch to directly modifying NV_PGRAPH_FECS_CTXSW_MAILBOX instead. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 09141b1b4220..30dce77ffa11 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -752,7 +752,7 @@ gf100_gr_fecs_ctrl_ctxsw(struct gf100_gr *gr, u32 mthd) struct nvkm_device *device = gr->base.engine.subdev.device; nvkm_wr32(device, 0x409804, 0xffffffff); - nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409800, 0x00000000); nvkm_wr32(device, 0x409500, 0xffffffff); nvkm_wr32(device, 0x409504, mthd); nvkm_msec(device, 2000, @@ -801,7 +801,7 @@ gf100_gr_fecs_bind_pointer(struct gf100_gr *gr, u32 inst) { struct nvkm_device *device = gr->base.engine.subdev.device; - nvkm_wr32(device, 0x409840, 0x00000030); + nvkm_mask(device, 0x409800, 0x00000030, 0x00000000); nvkm_wr32(device, 0x409500, inst); nvkm_wr32(device, 0x409504, 0x00000003); nvkm_msec(device, 2000, @@ -892,7 +892,7 @@ gf100_gr_fecs_discover_pm_image_size(struct gf100_gr *gr, u32 *psize) { struct nvkm_device *device = gr->base.engine.subdev.device; - nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409800, 0x00000000); nvkm_wr32(device, 0x409500, 0x00000000); nvkm_wr32(device, 0x409504, 0x00000025); nvkm_msec(device, 2000, @@ -908,7 +908,7 @@ gf100_gr_fecs_discover_zcull_image_size(struct gf100_gr *gr, u32 *psize) { struct nvkm_device *device = gr->base.engine.subdev.device; - nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409800, 0x00000000); nvkm_wr32(device, 0x409500, 0x00000000); nvkm_wr32(device, 0x409504, 0x00000016); nvkm_msec(device, 2000, @@ -924,7 +924,7 @@ gf100_gr_fecs_discover_image_size(struct gf100_gr *gr, u32 *psize) { struct nvkm_device *device = gr->base.engine.subdev.device; - nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409800, 0x00000000); nvkm_wr32(device, 0x409500, 0x00000000); nvkm_wr32(device, 0x409504, 0x00000010); nvkm_msec(device, 2000, @@ -940,7 +940,7 @@ gf100_gr_fecs_set_watchdog_timeout(struct gf100_gr *gr, u32 timeout) { struct nvkm_device *device = gr->base.engine.subdev.device; - nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409800, 0x00000000); nvkm_wr32(device, 0x409500, timeout); nvkm_wr32(device, 0x409504, 0x00000021); } @@ -1746,7 +1746,7 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) nvkm_mc_unk260(device, 1); /* start both of them running */ - nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409800, 0x00000000); nvkm_wr32(device, 0x41a10c, 0x00000000); nvkm_wr32(device, 0x40910c, 0x00000000); -- cgit v1.2.3 From 6762510bc8447dc4eb4c3d99541de6b31843e649 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:08 +1000 Subject: drm/nouveau/gr/gf100-: call FECS WFI_GOLDEN_SAVE method This won't work on Ampere, and, it's questionable whether we should have been using our FW's method of storing the golden context image with NV's firmware to begin with. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 30 ++++++++++++++--------- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 19 ++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 1 + 3 files changed, 39 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 332590f861fb..eef9b3f065fd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1496,17 +1496,25 @@ gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvk grctx->main(chan); - /* Trigger a context unload by unsetting the "next channel valid" bit - * and faking a context switch interrupt. - */ - nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000); - nvkm_wr32(device, 0x409000, 0x00000100); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x409b00) & 0x80000000)) - break; - ) < 0) { - ret = -EBUSY; - goto done_inst; + if (!gr->firmware) { + /* Trigger a context unload by unsetting the "next channel valid" bit + * and faking a context switch interrupt. + */ + nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000); + nvkm_wr32(device, 0x409000, 0x00000100); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x409b00) & 0x80000000)) + break; + ) < 0) { + ret = -EBUSY; + goto done_inst; + } + } else { + ret = gf100_gr_fecs_wfi_golden_save(gr, 0x80000000 | addr); + if (ret) + goto done_inst; + + nvkm_mask(device, 0x409b00, 0x80000000, 0x00000000); } gr->data = kmalloc(gr->size, GFP_KERNEL); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 30dce77ffa11..22f360df1b3a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -796,6 +796,25 @@ gf100_gr_fecs_stop_ctxsw(struct nvkm_gr *base) return ret; } +int +gf100_gr_fecs_wfi_golden_save(struct gf100_gr *gr, u32 inst) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_mask(device, 0x409800, 0x00000003, 0x00000000); + nvkm_wr32(device, 0x409500, inst); + nvkm_wr32(device, 0x409504, 0x00000009); + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x409800); + if (stat & 0x00000002) + return -EIO; + if (stat & 0x00000001) + return 0; + ); + + return -ETIMEDOUT; +} + int gf100_gr_fecs_bind_pointer(struct gf100_gr *gr, u32 inst) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 7f467f6d0462..66aefc972a18 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -129,6 +129,7 @@ struct gf100_gr { }; int gf100_gr_fecs_bind_pointer(struct gf100_gr *, u32 inst); +int gf100_gr_fecs_wfi_golden_save(struct gf100_gr *, u32 inst); struct gf100_gr_func_zbc { void (*clear_color)(struct gf100_gr *, int zbc); -- cgit v1.2.3 From f1f4d9181484a80928aaf5dfed96897ee3257e13 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:08 +1000 Subject: drm/nouveau/gr/gf100-: call FECS HALT_PIPE method before RC reset Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c | 12 ++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 33 ++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h | 1 + 3 files changed, 46 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c index 61759f54406e..71b824e6da9d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c @@ -135,6 +135,17 @@ nvkm_gr_oneinit(struct nvkm_engine *engine) return 0; } +static int +nvkm_gr_reset(struct nvkm_engine *engine) +{ + struct nvkm_gr *gr = nvkm_gr(engine); + + if (gr->func->reset) + return gr->func->reset(gr); + + return -ENOSYS; +} + static int nvkm_gr_init(struct nvkm_engine *engine) { @@ -166,6 +177,7 @@ nvkm_gr = { .oneinit = nvkm_gr_oneinit, .init = nvkm_gr_init, .fini = nvkm_gr_fini, + .reset = nvkm_gr_reset, .intr = nvkm_gr_intr, .tile = nvkm_gr_tile, .chsw_load = nvkm_gr_chsw_load, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 22f360df1b3a..ffdb5c38afee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -796,6 +796,20 @@ gf100_gr_fecs_stop_ctxsw(struct nvkm_gr *base) return ret; } +static int +gf100_gr_fecs_halt_pipeline(struct gf100_gr *gr) +{ + int ret = 0; + + if (gr->firmware) { + mutex_lock(&gr->fecs.mutex); + ret = gf100_gr_fecs_ctrl_ctxsw(gr, 0x04); + mutex_unlock(&gr->fecs.mutex); + } + + return ret; +} + int gf100_gr_fecs_wfi_golden_save(struct gf100_gr *gr, u32 inst) { @@ -2247,6 +2261,24 @@ gf100_gr_init_vsc_stream_master(struct gf100_gr *gr) nvkm_mask(device, TPC_UNIT(0, 0, 0x05c), 0x00000001, 0x00000001); } +static int +gf100_gr_reset(struct nvkm_gr *base) +{ + struct nvkm_subdev *subdev = &base->engine.subdev; + struct nvkm_device *device = subdev->device; + struct gf100_gr *gr = gf100_gr(base); + + nvkm_mask(device, 0x400500, 0x00000001, 0x00000000); + + WARN_ON(gf100_gr_fecs_halt_pipeline(gr)); + + subdev->func->fini(subdev, false); + nvkm_mc_disable(device, subdev->type, subdev->inst); + + nvkm_mc_enable(device, subdev->type, subdev->inst); + return subdev->func->init(subdev); +} + int gf100_gr_init(struct gf100_gr *gr) { @@ -2392,6 +2424,7 @@ gf100_gr_ = { .oneinit = gf100_gr_oneinit, .init = gf100_gr_init_, .fini = gf100_gr_fini, + .reset = gf100_gr_reset, .intr = gf100_gr_intr, .units = gf100_gr_units, .chan_new = gf100_gr_chan_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h index 9b2c66e8be90..08d5c96e6458 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h @@ -17,6 +17,7 @@ struct nvkm_gr_func { int (*oneinit)(struct nvkm_gr *); int (*init)(struct nvkm_gr *); int (*fini)(struct nvkm_gr *, bool); + int (*reset)(struct nvkm_gr *); void (*intr)(struct nvkm_gr *); void (*tile)(struct nvkm_gr *, int region, struct nvkm_fb_tile *); int (*tlb_flush)(struct nvkm_gr *); -- cgit v1.2.3 From 366e01092a050579b1f28129bdb72bc7c65ba47a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:09 +1000 Subject: drm/nouveau/gr/gf100-: wait for FE_PWR_MODE_AUTO This doesn't fix any known issue, but RM started doing it at some point, so presumably it's needed for something. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index eef9b3f065fd..979589676361 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1447,6 +1447,10 @@ gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvk /* NV_PGRAPH_FE_PWR_MODE_AUTO. */ nvkm_wr32(device, 0x404170, 0x00000010); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x404170) & 0x00000010)) + break; + ); /* Init SCC RAM. */ nvkm_wr32(device, 0x40802c, 0x00000001); -- cgit v1.2.3 From 0d7557072414af191cefbaa7c908e1c09f5b7d7b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:10 +1000 Subject: drm/nouveau/gr/gf100-: gpfifo_ctl zero before init Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index ffdb5c38afee..17e1c0dfda47 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2285,6 +2285,8 @@ gf100_gr_init(struct gf100_gr *gr) struct nvkm_device *device = gr->base.engine.subdev.device; int gpc, tpc, rop; + nvkm_mask(device, 0x400500, 0x00010001, 0x00000000); + if (gr->func->init_419bd8) gr->func->init_419bd8(gr); -- cgit v1.2.3 From 40bbee55c114750d2995028603902d7d2ed35ebd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:10 +1000 Subject: drm/nouveau/gr/gf100-: wfi after register-bashing golden init Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 979589676361..edd4b867a1e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1410,6 +1410,8 @@ gf100_grctx_generate_main(struct gf100_gr_chan *chan) grctx->r408840(gr); if (grctx->r419c0c) grctx->r419c0c(gr); + + gf100_gr_wait_idle(gr); } #define CB_RESERVED 0x80000 -- cgit v1.2.3 From be99d041b6b5be6be004366de8c4fc6b9832f195 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:11 +1000 Subject: drm/nouveau/gr/gf100-: move reset during golden ctx init to fecs_reset() Ampere. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 6 +----- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 13 +++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 1 + 23 files changed, 36 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index edd4b867a1e2..a56f4f3f6c1e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1438,11 +1438,7 @@ gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvk grctx->unkn88c(gr, true); /* Reset FECS. */ - nvkm_wr32(device, 0x409614, 0x00000070); - nvkm_usec(device, 10, NVKM_DELAY); - nvkm_mask(device, 0x409614, 0x00000700, 0x00000700); - nvkm_usec(device, 10, NVKM_DELAY); - nvkm_rd32(device, 0x409614); + gr->func->fecs.reset(gr); if (grctx->unkn88c) grctx->unkn88c(gr, false); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 17e1c0dfda47..8f935b9064b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2400,6 +2400,18 @@ gf100_gr_init(struct gf100_gr *gr) return gf100_gr_init_ctxctl(gr); } +void +gf100_gr_fecs_reset(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, 0x409614, 0x00000070); + nvkm_usec(device, 10, NVKM_DELAY); + nvkm_mask(device, 0x409614, 0x00000700, 0x00000700); + nvkm_usec(device, 10, NVKM_DELAY); + nvkm_rd32(device, 0x409614); +} + #include "fuc/hubgf100.fuc3.h" struct gf100_gr_ucode @@ -2456,6 +2468,7 @@ gf100_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gf100_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gf100_gr_gpccs_ucode, .rops = gf100_gr_rops, .grctx = &gf100_grctx, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 66aefc972a18..f98c739fb0b9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -172,6 +172,7 @@ struct gf100_gr_func { const struct gf100_gr_pack *mmio; struct { struct gf100_gr_ucode *ucode; + void (*reset)(struct gf100_gr *); } fecs; struct { struct gf100_gr_ucode *ucode; @@ -202,6 +203,7 @@ void gf100_gr_init_shader_exceptions(struct gf100_gr *, int, int); void gf100_gr_init_400054(struct gf100_gr *); void gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *, bool, bool); extern const struct gf100_gr_func_zbc gf100_gr_zbc; +void gf100_gr_fecs_reset(struct gf100_gr *); void gf117_gr_init_zcull(struct gf100_gr *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c index 3acd99c306f2..bb82c0a25ef8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c @@ -131,6 +131,7 @@ gf104_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gf104_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gf100_gr_gpccs_ucode, .rops = gf100_gr_rops, .grctx = &gf104_grctx, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c index ab3760e804b8..e62520653e40 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c @@ -129,6 +129,7 @@ gf108_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gf108_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gf100_gr_gpccs_ucode, .rops = gf100_gr_rops, .grctx = &gf108_grctx, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c index 616e2def1865..d489602be1d3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c @@ -103,6 +103,7 @@ gf110_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gf110_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gf100_gr_gpccs_ucode, .rops = gf100_gr_rops, .grctx = &gf110_grctx, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c index 669e7536970e..e3e69ab34fa3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c @@ -167,6 +167,7 @@ gf117_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gf117_gr_pack_mmio, .fecs.ucode = &gf117_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gf117_gr_gpccs_ucode, .rops = gf100_gr_rops, .ppc_nr = 1, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c index 5b09bda8110c..4dccf0bf25b7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c @@ -194,6 +194,7 @@ gf119_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gf119_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gf100_gr_gpccs_ucode, .rops = gf100_gr_rops, .grctx = &gf119_grctx, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index b680eaa0f350..cff24a01ddc0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -474,6 +474,7 @@ gk104_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gk104_gr_pack_mmio, .fecs.ucode = &gk104_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gk104_gr_gpccs_ucode, .rops = gf100_gr_rops, .ppc_nr = 1, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index 103e06a77e65..ae430b351d4f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -370,6 +370,7 @@ gk110_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gk110_gr_pack_mmio, .fecs.ucode = &gk110_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gk110_gr_gpccs_ucode, .rops = gf100_gr_rops, .ppc_nr = 2, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c index 034d0b11a17d..c22eadaee161 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c @@ -122,6 +122,7 @@ gk110b_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gk110b_gr_pack_mmio, .fecs.ucode = &gk110_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gk110_gr_gpccs_ucode, .rops = gf100_gr_rops, .ppc_nr = 2, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c index 116d682f9f96..35a70a48ed79 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c @@ -180,6 +180,7 @@ gk208_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gk208_gr_pack_mmio, .fecs.ucode = &gk208_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gk208_gr_gpccs_ucode, .rops = gf100_gr_rops, .ppc_nr = 1, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index be0b2cefd8e8..d5c59ff33d22 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -294,6 +294,7 @@ gk20a_gr = { .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, .trap_mp = gf100_gr_trap_mp, .set_hww_esr_report_mask = gk20a_gr_set_hww_esr_report_mask, + .fecs.reset = gf100_gr_fecs_reset, .rops = gf100_gr_rops, .ppc_nr = 1, .grctx = &gk20a_grctx, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c index 310987174cb5..17c36f30c86c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c @@ -415,6 +415,7 @@ gm107_gr = { .trap_mp = gf100_gr_trap_mp, .mmio = gm107_gr_pack_mmio, .fecs.ucode = &gm107_gr_fecs_ucode, + .fecs.reset = gf100_gr_fecs_reset, .gpccs.ucode = &gm107_gr_gpccs_ucode, .rops = gf100_gr_rops, .ppc_nr = 2, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index 385cfd91b266..31e753f0aaf4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -201,6 +201,7 @@ gm200_gr = { .init_shader_exceptions = gm107_gr_init_shader_exceptions, .init_400054 = gm107_gr_init_400054, .trap_mp = gf100_gr_trap_mp, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .tpc_nr = 4, .ppc_nr = 2, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c index ec1c46e47e00..458cd1a00d3f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c @@ -123,6 +123,7 @@ gm20b_gr = { .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, .trap_mp = gf100_gr_trap_mp, .set_hww_esr_report_mask = gm20b_gr_set_hww_esr_report_mask, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .ppc_nr = 1, .grctx = &gm20b_grctx, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c index 0550dd6f46f1..7a6657bcc7c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c @@ -120,6 +120,7 @@ gp100_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .trap_mp = gf100_gr_trap_mp, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 6, .tpc_nr = 5, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c index 1d1f3c0a9014..ebde815ac9d9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c @@ -116,6 +116,7 @@ gp102_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .trap_mp = gf100_gr_trap_mp, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 6, .tpc_nr = 5, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c index 2655574ec63b..3d824bd7180c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c @@ -44,6 +44,7 @@ gp104_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .trap_mp = gf100_gr_trap_mp, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 6, .tpc_nr = 5, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c index adabc04d4f3a..d4f87d923787 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c @@ -46,6 +46,7 @@ gp107_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .trap_mp = gf100_gr_trap_mp, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 2, .tpc_nr = 3, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c index e13683b6e7b1..a20db4d93b28 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c @@ -56,6 +56,7 @@ gp10b_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .trap_mp = gf100_gr_trap_mp, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 1, .tpc_nr = 2, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index 4d043c1173ea..c57bb3970eb6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -105,6 +105,7 @@ gv100_gr = { .init_shader_exceptions = gv100_gr_init_shader_exceptions, .init_4188a4 = gv100_gr_init_4188a4, .trap_mp = gv100_gr_trap_mp, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 6, .tpc_nr = 5, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 1a8a21844e12..88f768ca8e47 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -110,6 +110,7 @@ tu102_gr = { .init_504430 = gv100_gr_init_504430, .init_shader_exceptions = gv100_gr_init_shader_exceptions, .trap_mp = gv100_gr_trap_mp, + .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 6, .tpc_nr = 5, -- cgit v1.2.3 From b6d93fa74adac565129e6f6df6722acf87a11d49 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:12 +1000 Subject: drm/nouveau/gr/gf100-: move some init to init_rop_exceptions() Ampere. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 24 +++++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 1 + 20 files changed, 37 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 8f935b9064b3..5dcebda6ddc0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2154,6 +2154,20 @@ gf100_gr_init_400054(struct gf100_gr *gr) nvkm_wr32(gr->base.engine.subdev.device, 0x400054, 0x34ce3464); } +void +gf100_gr_init_rop_exceptions(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + int rop; + + for (rop = 0; rop < gr->rop_nr; rop++) { + nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0x40000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0x40000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff); + nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff); + } +} + void gf100_gr_init_shader_exceptions(struct gf100_gr *gr, int gpc, int tpc) { @@ -2283,7 +2297,7 @@ int gf100_gr_init(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; - int gpc, tpc, rop; + int gpc, tpc; nvkm_mask(device, 0x400500, 0x00010001, 0x00000000); @@ -2375,12 +2389,7 @@ gf100_gr_init(struct gf100_gr *gr) nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } - for (rop = 0; rop < gr->rop_nr; rop++) { - nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0x40000000); - nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0x40000000); - nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff); - nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff); - } + gr->func->init_rop_exceptions(gr); nvkm_wr32(device, 0x400108, 0xffffffff); nvkm_wr32(device, 0x400138, 0xffffffff); @@ -2464,6 +2473,7 @@ gf100_gr = { .init_419eb4 = gf100_gr_init_419eb4, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf100_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index f98c739fb0b9..6f1f4fc1fd88 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -165,6 +165,7 @@ struct gf100_gr_func { void (*init_tex_hww_esr)(struct gf100_gr *, int gpc, int tpc); void (*init_504430)(struct gf100_gr *, int gpc, int tpc); void (*init_shader_exceptions)(struct gf100_gr *, int gpc, int tpc); + void (*init_rop_exceptions)(struct gf100_gr *); void (*init_400054)(struct gf100_gr *); void (*init_4188a4)(struct gf100_gr *); void (*trap_mp)(struct gf100_gr *, int gpc, int tpc); @@ -200,6 +201,7 @@ void gf100_gr_init_419cc0(struct gf100_gr *); void gf100_gr_init_419eb4(struct gf100_gr *); void gf100_gr_init_tex_hww_esr(struct gf100_gr *, int, int); void gf100_gr_init_shader_exceptions(struct gf100_gr *, int, int); +void gf100_gr_init_rop_exceptions(struct gf100_gr *); void gf100_gr_init_400054(struct gf100_gr *); void gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *, bool, bool); extern const struct gf100_gr_func_zbc gf100_gr_zbc; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c index bb82c0a25ef8..a1a338c1626a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c @@ -127,6 +127,7 @@ gf104_gr = { .init_419eb4 = gf100_gr_init_419eb4, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf104_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c index e62520653e40..5687835f5fec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c @@ -125,6 +125,7 @@ gf108_gr = { .init_419eb4 = gf100_gr_init_419eb4, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf108_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c index d489602be1d3..f6a77094fb5a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c @@ -99,6 +99,7 @@ gf110_gr = { .init_419eb4 = gf100_gr_init_419eb4, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf110_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c index e3e69ab34fa3..065d1831f1b1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c @@ -163,6 +163,7 @@ gf117_gr = { .init_419eb4 = gf100_gr_init_419eb4, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf117_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c index 4dccf0bf25b7..e4add185d266 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c @@ -190,6 +190,7 @@ gf119_gr = { .init_419eb4 = gf100_gr_init_419eb4, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf119_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index cff24a01ddc0..85db57b50c2c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -470,6 +470,7 @@ gk104_gr = { .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gk104_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index ae430b351d4f..157de0003c18 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -366,6 +366,7 @@ gk110_gr = { .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gk110_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c index c22eadaee161..7f590d36b6f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c @@ -118,6 +118,7 @@ gk110b_gr = { .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gk110b_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c index 35a70a48ed79..68c74d425ddf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c @@ -176,6 +176,7 @@ gk208_gr = { .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gk208_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c index 17c36f30c86c..8ac7131877fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c @@ -411,6 +411,7 @@ gm107_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gm107_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gm107_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gm107_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index 31e753f0aaf4..0145d0cc32ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -199,6 +199,7 @@ gm200_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gm107_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_400054 = gm107_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c index 7a6657bcc7c3..47cb5a20fec6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c @@ -119,6 +119,7 @@ gp100_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c index ebde815ac9d9..e8a5dc8d14a6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c @@ -115,6 +115,7 @@ gp102_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c index 3d824bd7180c..4c9549e5c901 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c @@ -43,6 +43,7 @@ gp104_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c index d4f87d923787..e624162453a2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c @@ -45,6 +45,7 @@ gp107_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c index a20db4d93b28..10348223e9a7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c @@ -55,6 +55,7 @@ gp10b_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index c57bb3970eb6..07507a0ee318 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -103,6 +103,7 @@ gv100_gr = { .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .init_504430 = gv100_gr_init_504430, .init_shader_exceptions = gv100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_4188a4 = gv100_gr_init_4188a4, .trap_mp = gv100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 88f768ca8e47..bc5d77ded240 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -109,6 +109,7 @@ tu102_gr = { .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .init_504430 = gv100_gr_init_504430, .init_shader_exceptions = gv100_gr_init_shader_exceptions, + .init_rop_exceptions = gf100_gr_init_rop_exceptions, .trap_mp = gv100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, -- cgit v1.2.3 From 1a34468855bdd0a8caef2fd6e8e23ecc25407bb2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:12 +1000 Subject: drm/nouveau/gr/gf100-: move some init to init_exception2() Ampere. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 14 ++++++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 1 + 20 files changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 5dcebda6ddc0..b9961d254749 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2154,6 +2154,15 @@ gf100_gr_init_400054(struct gf100_gr *gr) nvkm_wr32(gr->base.engine.subdev.device, 0x400054, 0x34ce3464); } +void +gf100_gr_init_exception2(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, 0x40011c, 0xffffffff); + nvkm_wr32(device, 0x400134, 0xffffffff); +} + void gf100_gr_init_rop_exceptions(struct gf100_gr *gr) { @@ -2395,8 +2404,8 @@ gf100_gr_init(struct gf100_gr *gr) nvkm_wr32(device, 0x400138, 0xffffffff); nvkm_wr32(device, 0x400118, 0xffffffff); nvkm_wr32(device, 0x400130, 0xffffffff); - nvkm_wr32(device, 0x40011c, 0xffffffff); - nvkm_wr32(device, 0x400134, 0xffffffff); + if (gr->func->init_exception2) + gr->func->init_exception2(gr); if (gr->func->init_400054) gr->func->init_400054(gr); @@ -2474,6 +2483,7 @@ gf100_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf100_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 6f1f4fc1fd88..cb1d7b2c0558 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -166,6 +166,7 @@ struct gf100_gr_func { void (*init_504430)(struct gf100_gr *, int gpc, int tpc); void (*init_shader_exceptions)(struct gf100_gr *, int gpc, int tpc); void (*init_rop_exceptions)(struct gf100_gr *); + void (*init_exception2)(struct gf100_gr *); void (*init_400054)(struct gf100_gr *); void (*init_4188a4)(struct gf100_gr *); void (*trap_mp)(struct gf100_gr *, int gpc, int tpc); @@ -202,6 +203,7 @@ void gf100_gr_init_419eb4(struct gf100_gr *); void gf100_gr_init_tex_hww_esr(struct gf100_gr *, int, int); void gf100_gr_init_shader_exceptions(struct gf100_gr *, int, int); void gf100_gr_init_rop_exceptions(struct gf100_gr *); +void gf100_gr_init_exception2(struct gf100_gr *); void gf100_gr_init_400054(struct gf100_gr *); void gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *, bool, bool); extern const struct gf100_gr_func_zbc gf100_gr_zbc; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c index a1a338c1626a..63bd29c22fe1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c @@ -128,6 +128,7 @@ gf104_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf104_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c index 5687835f5fec..495a844f925f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c @@ -126,6 +126,7 @@ gf108_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf108_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c index f6a77094fb5a..70fad235d161 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c @@ -100,6 +100,7 @@ gf110_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf110_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c index 065d1831f1b1..68fd4384b5e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c @@ -164,6 +164,7 @@ gf117_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf117_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c index e4add185d266..75ceb514c06e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c @@ -191,6 +191,7 @@ gf119_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gf119_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index 85db57b50c2c..3f7b4ef3529e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -471,6 +471,7 @@ gk104_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gk104_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index 157de0003c18..c7e1c5dbc6a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -367,6 +367,7 @@ gk110_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gk110_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c index 7f590d36b6f8..458abae571bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c @@ -119,6 +119,7 @@ gk110b_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gk110b_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c index 68c74d425ddf..d3f6b65c21d2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c @@ -177,6 +177,7 @@ gk208_gr = { .init_tex_hww_esr = gf100_gr_init_tex_hww_esr, .init_shader_exceptions = gf100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gf100_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gk208_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c index 8ac7131877fa..797b828a943b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c @@ -412,6 +412,7 @@ gm107_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gm107_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gm107_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .mmio = gm107_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index 0145d0cc32ee..b9d74d65038d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -200,6 +200,7 @@ gm200_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gm107_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_400054 = gm107_gr_init_400054, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c index 47cb5a20fec6..576cabd80a4a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c @@ -120,6 +120,7 @@ gp100_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c index e8a5dc8d14a6..f265ba08c5ef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c @@ -116,6 +116,7 @@ gp102_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c index 4c9549e5c901..6802cb9b199f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c @@ -44,6 +44,7 @@ gp104_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c index e624162453a2..cc2bb0d0a987 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c @@ -46,6 +46,7 @@ gp107_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c index 10348223e9a7..5008881ca079 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c @@ -56,6 +56,7 @@ gp10b_gr = { .init_504430 = gm107_gr_init_504430, .init_shader_exceptions = gp100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .trap_mp = gf100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index 07507a0ee318..25228d09a30b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -104,6 +104,7 @@ gv100_gr = { .init_504430 = gv100_gr_init_504430, .init_shader_exceptions = gv100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .init_4188a4 = gv100_gr_init_4188a4, .trap_mp = gv100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index bc5d77ded240..ce968be6f290 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -110,6 +110,7 @@ tu102_gr = { .init_504430 = gv100_gr_init_504430, .init_shader_exceptions = gv100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, + .init_exception2 = gf100_gr_init_exception2, .trap_mp = gv100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, -- cgit v1.2.3 From 9aa3faced0a3dea04294afe781e07e1ef1118e30 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:13 +1000 Subject: drm/nouveau/gr/gf100-: switch to newer style interrupt handler Ampere. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 27 ++++++++++++++++++++------ drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c | 4 ++-- 4 files changed, 26 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index b9961d254749..6e31ba69ed4a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1600,10 +1600,10 @@ gf100_gr_ctxctl_isr(struct gf100_gr *gr) } } -static void -gf100_gr_intr(struct nvkm_gr *base) +static irqreturn_t +gf100_gr_intr(struct nvkm_inth *inth) { - struct gf100_gr *gr = gf100_gr(base); + struct gf100_gr *gr = container_of(inth, typeof(*gr), base.engine.subdev.inth); struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_chan *chan; @@ -1690,6 +1690,7 @@ gf100_gr_intr(struct nvkm_gr *base) nvkm_wr32(device, 0x400500, 0x00010001); nvkm_chan_put(&chan, flags); + return IRQ_HANDLED; } static void @@ -1985,8 +1986,15 @@ gf100_gr_oneinit(struct nvkm_gr *base) struct gf100_gr *gr = gf100_gr(base); struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; + struct nvkm_intr *intr = &device->mc->intr; + enum nvkm_intr_type intr_type = NVKM_INTR_SUBDEV; int ret, i, j; + ret = nvkm_inth_add(intr, intr_type, NVKM_INTR_PRIO_NORMAL, &gr->base.engine.subdev, + gf100_gr_intr, &gr->base.engine.subdev.inth); + if (ret) + return ret; + nvkm_pmu_pgob(device->pmu, false); gr->rop_nr = gr->func->rops(gr); @@ -2047,7 +2055,7 @@ gf100_gr_init_(struct nvkm_gr *base) struct nvkm_subdev *subdev = &base->engine.subdev; struct nvkm_device *device = subdev->device; bool reset = device->chipset == 0x137 || device->chipset == 0x138; - u32 ret; + int ret; /* On certain GP107/GP108 boards, we trigger a weird issue where * GR will stop responding to PRI accesses after we've asked the @@ -2083,7 +2091,12 @@ gf100_gr_init_(struct nvkm_gr *base) if (ret) return ret; - return gr->func->init(gr); + ret = gr->func->init(gr); + if (ret) + return ret; + + nvkm_inth_allow(&subdev->inth); + return 0; } static int @@ -2091,6 +2104,9 @@ gf100_gr_fini(struct nvkm_gr *base, bool suspend) { struct gf100_gr *gr = gf100_gr(base); struct nvkm_subdev *subdev = &gr->base.engine.subdev; + + nvkm_inth_block(&subdev->inth); + nvkm_falcon_put(&gr->gpccs.falcon, subdev); nvkm_falcon_put(&gr->fecs.falcon, subdev); return 0; @@ -2457,7 +2473,6 @@ gf100_gr_ = { .init = gf100_gr_init_, .fini = gf100_gr_fini, .reset = gf100_gr_reset, - .intr = gf100_gr_intr, .units = gf100_gr_units, .chan_new = gf100_gr_chan_new, .object_get = gf100_gr_object_get, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c index 5118e413d053..ab1eaa37123a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c @@ -41,7 +41,7 @@ gf100_mc_intrs[] = { { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true }, { NVKM_ENGINE_MSPDEC , 0, 0, 0x00020000, true }, { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true }, - { NVKM_ENGINE_GR , 0, 0, 0x00001000, true }, + { NVKM_ENGINE_GR , 0, 0, 0x00001000 }, { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 }, { NVKM_ENGINE_CE , 1, 0, 0x00000040, true }, { NVKM_ENGINE_CE , 0, 0, 0x00000020, true }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c index 9d482f358138..66829586a124 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c @@ -43,7 +43,8 @@ gk104_mc_intrs[] = { { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true }, - { NVKM_SUBDEV_TOP , 0, 0, 0xffffffff, true }, + { NVKM_SUBDEV_TOP , 0, 0, 0x00001000 }, + { NVKM_SUBDEV_TOP , 0, 0, 0xffffefff, true }, {}, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c index 3a99a450b6b0..eb2ab03f4360 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c @@ -37,8 +37,8 @@ gp100_mc_intrs[] = { { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true }, { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true }, { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true }, - { NVKM_SUBDEV_TOP , 0, 0, 0x00008000 }, - { NVKM_SUBDEV_TOP , 0, 0, 0xffff7fff, true }, + { NVKM_SUBDEV_TOP , 0, 0, 0x00009000 }, + { NVKM_SUBDEV_TOP , 0, 0, 0xffff6fff, true }, {}, }; -- cgit v1.2.3 From 0c520ad45a65313c310fe96e17bda51e2c019ec4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:14 +1000 Subject: drm/nouveau/gr/gf117-: make ppc_nr[gpc] accurate We're going to be pulling in a chunk of code from NVGPU to fixup our SMID mappings on Volta and above, which depends on ppc_nr[gpc] reflecting the actual number of PPCs present, not the maximum number. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 6 ++++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c | 2 +- 8 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c index 6c1f631eebd5..e34c5da2a9ff 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c @@ -257,7 +257,7 @@ gf117_grctx_generate_attrib(struct gf100_gr_chan *chan) gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { - for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) { + for (ppc = 0; ppc < gr->func->ppc_nr; ppc++) { const u32 a = alpha * gr->ppc_tpc_nr[gpc][ppc]; const u32 b = beta * gr->ppc_tpc_nr[gpc][ppc]; const u32 t = timeslice_mode; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index 019c698eb5a5..beac66eb2a80 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -912,7 +912,7 @@ gm107_grctx_generate_attrib(struct gf100_gr_chan *chan) gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { - for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { + for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) { const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc]; const u32 bs = attrib * gr->ppc_tpc_nr[gpc][ppc]; const u32 u = 0x418ea0 + (n * 0x04); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c index 6b7034b2ff76..175da8ac656c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c @@ -87,7 +87,7 @@ gm200_grctx_generate_dist_skip_table(struct gf100_gr *gr) int gpc, ppc, i; for (gpc = 0; gpc < gr->gpc_nr; gpc++) { - for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) { + for (ppc = 0; ppc < gr->func->ppc_nr; ppc++) { u8 ppc_tpcs = gr->ppc_tpc_nr[gpc][ppc]; u8 ppc_tpcm = gr->ppc_tpc_mask[gpc][ppc]; while (ppc_tpcs-- > gr->ppc_tpc_min) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c index d8977caa0d04..8485aaeae7a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c @@ -56,7 +56,7 @@ gp100_grctx_generate_attrib(struct gf100_gr_chan *chan) gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { - for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { + for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) { const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc]; const u32 bs = attrib * gr->ppc_tpc_max; const u32 u = 0x418ea0 + (n * 0x04); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c index 7d372d786b8b..7537979a5492 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c @@ -55,7 +55,7 @@ gp102_grctx_generate_attrib(struct gf100_gr_chan *chan) gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { - for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { + for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) { const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc]; const u32 bs = attrib * gr->ppc_tpc_max; const u32 gs = gfxp * gr->ppc_tpc_max; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c index c2e5d43b1c37..9975a4d5c058 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c @@ -75,7 +75,7 @@ gv100_grctx_generate_attrib(struct gf100_gr_chan *chan) gf100_grctx_patch_wr32(chan, 0x40585c, alpha); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { - for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { + for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) { const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc]; const u32 bs = attrib * gr->ppc_tpc_max; const u32 gs = gfxp * gr->ppc_tpc_max; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 6e31ba69ed4a..ebbd7476e0fe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2003,12 +2003,14 @@ gf100_gr_oneinit(struct nvkm_gr *base) gr->tpc_nr[i] = nvkm_rd32(device, GPC_UNIT(i, 0x2608)); gr->tpc_max = max(gr->tpc_max, gr->tpc_nr[i]); gr->tpc_total += gr->tpc_nr[i]; - gr->ppc_nr[i] = gr->func->ppc_nr; - for (j = 0; j < gr->ppc_nr[i]; j++) { + for (j = 0; j < gr->func->ppc_nr; j++) { gr->ppc_tpc_mask[i][j] = nvkm_rd32(device, GPC_UNIT(i, 0x0c30 + (j * 4))); if (gr->ppc_tpc_mask[i][j] == 0) continue; + + gr->ppc_nr[i]++; + gr->ppc_mask[i] |= (1 << j); gr->ppc_tpc_nr[i][j] = hweight8(gr->ppc_tpc_mask[i][j]); if (gr->ppc_tpc_min == 0 || diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index 3f7b4ef3529e..e53ade24ad23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -418,7 +418,7 @@ gk104_gr_init_ppc_exceptions(struct gf100_gr *gr) int gpc, ppc; for (gpc = 0; gpc < gr->gpc_nr; gpc++) { - for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) { + for (ppc = 0; ppc < gr->func->ppc_nr; ppc++) { if (!(gr->ppc_mask[gpc] & (1 << ppc))) continue; nvkm_wr32(device, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000); -- cgit v1.2.3 From e2eeec758c367963c74d56eb89a10920e418bfdf Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:14 +1000 Subject: drm/nouveau/gr/gp100-: fix number of zcull tile regs Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c | 4 +++- drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c index 68fd4384b5e5..f12728248048 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c @@ -125,7 +125,9 @@ gf117_gr_init_zcull(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); - const u8 tile_nr = ALIGN(gr->tpc_total, 32); + /*TODO: fill in litter vals for gf117-gm2xx */ + const u8 tile_nr = !gr->func->gpc_nr ? ALIGN(gr->tpc_total, 32) : + (gr->func->gpc_nr * gr->func->tpc_nr); u8 bank[GPC_MAX] = {}, gpc, i, j; u32 data; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index ce968be6f290..10b6e78bcf8e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -53,7 +53,7 @@ tu102_gr_init_zcull(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); - const u8 tile_nr = ALIGN(gr->tpc_total, 64); + const u8 tile_nr = gr->func->gpc_nr * gr->func->tpc_nr; u8 bank[GPC_MAX] = {}, gpc, i, j; u32 data; @@ -115,7 +115,7 @@ tu102_gr = { .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 6, - .tpc_nr = 5, + .tpc_nr = 6, .ppc_nr = 3, .grctx = &tu102_grctx, .zbc = &gp102_gr_zbc, -- cgit v1.2.3 From de8be616b6ea83f468da3265aff58d25f57494b5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:15 +1000 Subject: drm/nouveau/gr/gk20a,gm20b,gp10b: split out netlist parsing from fw loading We'll want to reuse the former for loading from proper netlist images. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 6 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 110 ++++++++++--------------- 2 files changed, 49 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index cb1d7b2c0558..9c6823672d2e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -223,6 +223,9 @@ void gm107_gr_init_shader_exceptions(struct gf100_gr *, int, int); void gm107_gr_init_400054(struct gf100_gr *); int gk20a_gr_init(struct gf100_gr *); +int gk20a_gr_av_to_init(struct nvkm_blob *, struct gf100_gr_pack **); +int gk20a_gr_aiv_to_init(struct nvkm_blob *, struct gf100_gr_pack **); +int gk20a_gr_av_to_method(struct nvkm_blob *, struct gf100_gr_pack **); void gm200_gr_oneinit_tiles(struct gf100_gr *); void gm200_gr_oneinit_sm_id(struct gf100_gr *); @@ -400,6 +403,9 @@ int gf100_gr_load(struct gf100_gr *, int, const struct gf100_gr_fwif *); int gf100_gr_nofw(struct gf100_gr *, int, const struct gf100_gr_fwif *); int gk20a_gr_load_sw(struct gf100_gr *, const char *path, int ver); +int gk20a_gr_load_net(struct gf100_gr *, const char *, const char *, int, + int (*)(struct nvkm_blob *, struct gf100_gr_pack **), + struct gf100_gr_pack **); int gm200_gr_nofw(struct gf100_gr *, int, const struct gf100_gr_fwif *); int gm200_gr_load(struct gf100_gr *, int, const struct gf100_gr_fwif *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index d5c59ff33d22..2aee0559efca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -33,35 +33,25 @@ struct gk20a_fw_av u32 data; }; -static int -gk20a_gr_av_to_init(struct gf100_gr *gr, const char *path, const char *name, - int ver, struct gf100_gr_pack **ppack) +int +gk20a_gr_av_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) { - struct nvkm_subdev *subdev = &gr->base.engine.subdev; - struct nvkm_blob blob; struct gf100_gr_init *init; struct gf100_gr_pack *pack; int nent; - int ret; int i; - ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob); - if (ret) - return ret; - - nent = (blob.size / sizeof(struct gk20a_fw_av)); + nent = (blob->size / sizeof(struct gk20a_fw_av)); pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1))); - if (!pack) { - ret = -ENOMEM; - goto end; - } + if (!pack) + return -ENOMEM; init = (void *)(pack + 2); pack[0].init = init; for (i = 0; i < nent; i++) { struct gf100_gr_init *ent = &init[i]; - struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob.data)[i]; + struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob->data)[i]; ent->addr = av->addr; ent->data = av->data; @@ -70,10 +60,7 @@ gk20a_gr_av_to_init(struct gf100_gr *gr, const char *path, const char *name, } *ppack = pack; - -end: - nvkm_blob_dtor(&blob); - return ret; + return 0; } struct gk20a_fw_aiv @@ -83,35 +70,25 @@ struct gk20a_fw_aiv u32 data; }; -static int -gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *path, const char *name, - int ver, struct gf100_gr_pack **ppack) +int +gk20a_gr_aiv_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) { - struct nvkm_subdev *subdev = &gr->base.engine.subdev; - struct nvkm_blob blob; struct gf100_gr_init *init; struct gf100_gr_pack *pack; int nent; - int ret; int i; - ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob); - if (ret) - return ret; - - nent = (blob.size / sizeof(struct gk20a_fw_aiv)); + nent = (blob->size / sizeof(struct gk20a_fw_aiv)); pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1))); - if (!pack) { - ret = -ENOMEM; - goto end; - } + if (!pack) + return -ENOMEM; init = (void *)(pack + 2); pack[0].init = init; for (i = 0; i < nent; i++) { struct gf100_gr_init *ent = &init[i]; - struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)blob.data)[i]; + struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)blob->data)[i]; ent->addr = av->addr; ent->data = av->data; @@ -120,44 +97,30 @@ gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *path, const char *name, } *ppack = pack; - -end: - nvkm_blob_dtor(&blob); - return ret; + return 0; } -static int -gk20a_gr_av_to_method(struct gf100_gr *gr, const char *path, const char *name, - int ver, struct gf100_gr_pack **ppack) +int +gk20a_gr_av_to_method(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) { - struct nvkm_subdev *subdev = &gr->base.engine.subdev; - struct nvkm_blob blob; struct gf100_gr_init *init; struct gf100_gr_pack *pack; /* We don't suppose we will initialize more than 16 classes here... */ static const unsigned int max_classes = 16; u32 classidx = 0, prevclass = 0; int nent; - int ret; int i; - ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob); - if (ret) - return ret; - - nent = (blob.size / sizeof(struct gk20a_fw_av)); - + nent = (blob->size / sizeof(struct gk20a_fw_av)); pack = vzalloc((sizeof(*pack) * (max_classes + 1)) + (sizeof(*init) * (nent + max_classes + 1))); - if (!pack) { - ret = -ENOMEM; - goto end; - } + if (!pack) + return -ENOMEM; init = (void *)(pack + max_classes + 1); for (i = 0; i < nent; i++, init++) { - struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob.data)[i]; + struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob->data)[i]; u32 class = av->addr & 0xffff; u32 addr = (av->addr & 0xffff0000) >> 14; @@ -169,8 +132,7 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *path, const char *name, prevclass = class; if (++classidx >= max_classes) { vfree(pack); - ret = -ENOSPC; - goto end; + return -ENOSPC; } } @@ -181,10 +143,7 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *path, const char *name, } *ppack = pack; - -end: - nvkm_blob_dtor(&blob); - return ret; + return 0; } static int @@ -308,13 +267,30 @@ gk20a_gr = { } }; +int +gk20a_gr_load_net(struct gf100_gr *gr, const char *path, const char *name, int ver, + int (*load)(struct nvkm_blob *, struct gf100_gr_pack **), + struct gf100_gr_pack **ppack) +{ + struct nvkm_blob blob; + int ret; + + ret = nvkm_firmware_load_blob(&gr->base.engine.subdev, path, name, ver, &blob); + if (ret) + return ret; + + ret = load(&blob, ppack); + nvkm_blob_dtor(&blob); + return 0; +} + int gk20a_gr_load_sw(struct gf100_gr *gr, const char *path, int ver) { - if (gk20a_gr_av_to_init(gr, path, "sw_nonctx", ver, &gr->sw_nonctx) || - gk20a_gr_aiv_to_init(gr, path, "sw_ctx", ver, &gr->sw_ctx) || - gk20a_gr_av_to_init(gr, path, "sw_bundle_init", ver, &gr->bundle) || - gk20a_gr_av_to_method(gr, path, "sw_method_init", ver, &gr->method)) + if (gk20a_gr_load_net(gr, path, "sw_nonctx", ver, gk20a_gr_av_to_init, &gr->sw_nonctx) || + gk20a_gr_load_net(gr, path, "sw_ctx", ver, gk20a_gr_aiv_to_init, &gr->sw_ctx) || + gk20a_gr_load_net(gr, path, "sw_bundle_init", ver, gk20a_gr_av_to_init, &gr->bundle) || + gk20a_gr_load_net(gr, path, "sw_method_init", ver, gk20a_gr_av_to_method, &gr->method)) return -ENOENT; return 0; -- cgit v1.2.3 From d94ac9dddef792be7741cbb558d3be2b796567d7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:16 +1000 Subject: drm/nouveau/gr/gp100-: modify init_fecs_exceptions Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c index 576cabd80a4a..851e743d2cab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c @@ -87,7 +87,7 @@ gp100_gr_init_419c9c(struct gf100_gr *gr) void gp100_gr_init_fecs_exceptions(struct gf100_gr *gr) { - nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x000f0002); + nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x000e0002); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 10b6e78bcf8e..3491005cf5d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -27,7 +27,7 @@ static void tu102_gr_init_fecs_exceptions(struct gf100_gr *gr) { - nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x006f0002); + nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x006e0003); } static void -- cgit v1.2.3 From 3ffa6f329b610029b44ebd7bc2320a92468a0e42 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:17 +1000 Subject: drm/nouveau/gr/gv100-: port smid mapping code from nvgpu Essentially ripped verbatim from NVGPU, comments and all, and adapted to nvkm's structs and style. - maybe fixes an nvgpu bug though, a small tweak was needed to match RM v2: - remove unnecessary WARN_ON Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c | 3 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c | 3 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 11 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 194 +++++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 7 +- 7 files changed, 219 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c index 9975a4d5c058..d68741a81a58 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c @@ -157,6 +157,9 @@ static void gv100_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm) { struct nvkm_device *device = gr->base.engine.subdev.device; + + tpc = gv100_gr_nonpes_aware_tpc(gr, gpc, tpc); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x608), sm); nvkm_wr32(device, GPC_UNIT(gpc, 0x0c10 + tpc * 4), sm); nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), sm); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c index 1a151e89ea05..da1bac3963a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c @@ -34,6 +34,9 @@ static void tu102_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm) { struct nvkm_device *device = gr->base.engine.subdev.device; + + tpc = gv100_gr_nonpes_aware_tpc(gr, gpc, tpc); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x608), sm); nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), sm); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index ebbd7476e0fe..5ce83b915ebb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1889,10 +1889,11 @@ gf100_gr_init_ctxctl(struct gf100_gr *gr) return ret; } -void +int gf100_gr_oneinit_sm_id(struct gf100_gr *gr) { int tpc, gpc; + for (tpc = 0; tpc < gr->tpc_max; tpc++) { for (gpc = 0; gpc < gr->gpc_nr; gpc++) { if (tpc < gr->tpc_nr[gpc]) { @@ -1902,6 +1903,8 @@ gf100_gr_oneinit_sm_id(struct gf100_gr *gr) } } } + + return 0; } void @@ -2019,6 +2022,8 @@ gf100_gr_oneinit(struct nvkm_gr *base) if (gr->ppc_tpc_max < gr->ppc_tpc_nr[i][j]) gr->ppc_tpc_max = gr->ppc_tpc_nr[i][j]; } + + gr->ppc_total += gr->ppc_nr[i]; } /* Allocate global context buffers. */ @@ -2046,8 +2051,8 @@ gf100_gr_oneinit(struct nvkm_gr *base) memset(gr->tile, 0xff, sizeof(gr->tile)); gr->func->oneinit_tiles(gr); - gr->func->oneinit_sm_id(gr); - return 0; + + return gr->func->oneinit_sm_id(gr); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 9c6823672d2e..a9ba9af25728 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -107,6 +107,7 @@ struct gf100_gr { u8 ppc_tpc_nr[GPC_MAX][4]; u8 ppc_tpc_min; u8 ppc_tpc_max; + u8 ppc_total; struct nvkm_memory *pagepool; struct nvkm_memory *bundle_cb; @@ -141,7 +142,7 @@ struct gf100_gr_func_zbc { struct gf100_gr_func { void (*oneinit_tiles)(struct gf100_gr *); - void (*oneinit_sm_id)(struct gf100_gr *); + int (*oneinit_sm_id)(struct gf100_gr *); int (*init)(struct gf100_gr *); void (*init_419bd8)(struct gf100_gr *); void (*init_gpc_mmu)(struct gf100_gr *); @@ -191,7 +192,7 @@ struct gf100_gr_func { int gf100_gr_rops(struct gf100_gr *); void gf100_gr_oneinit_tiles(struct gf100_gr *); -void gf100_gr_oneinit_sm_id(struct gf100_gr *); +int gf100_gr_oneinit_sm_id(struct gf100_gr *); int gf100_gr_init(struct gf100_gr *); void gf100_gr_init_vsc_stream_master(struct gf100_gr *); void gf100_gr_init_zcull(struct gf100_gr *); @@ -228,7 +229,7 @@ int gk20a_gr_aiv_to_init(struct nvkm_blob *, struct gf100_gr_pack **); int gk20a_gr_av_to_method(struct nvkm_blob *, struct gf100_gr_pack **); void gm200_gr_oneinit_tiles(struct gf100_gr *); -void gm200_gr_oneinit_sm_id(struct gf100_gr *); +int gm200_gr_oneinit_sm_id(struct gf100_gr *); int gm200_gr_rops(struct gf100_gr *); void gm200_gr_init_num_active_ltcs(struct gf100_gr *); void gm200_gr_init_ds_hww_esr_2(struct gf100_gr *); @@ -245,6 +246,8 @@ extern const struct gf100_gr_func_zbc gp102_gr_zbc; extern const struct gf100_gr_func gp107_gr; +int gv100_gr_oneinit_sm_id(struct gf100_gr *); +u32 gv100_gr_nonpes_aware_tpc(struct gf100_gr *gr, u32 gpc, u32 tpc); void gv100_gr_init_419bd8(struct gf100_gr *); void gv100_gr_init_504430(struct gf100_gr *, int, int); void gv100_gr_init_shader_exceptions(struct gf100_gr *, int, int); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index b9d74d65038d..b5210b31c1b2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -148,11 +148,11 @@ gm200_gr_tile_map_2_8[] = { 0, 1, 1, 0, 0, 1, 1, 0, }; -void +int gm200_gr_oneinit_sm_id(struct gf100_gr *gr) { /*XXX: There's a different algorithm here I've not yet figured out. */ - gf100_gr_oneinit_sm_id(gr); + return gf100_gr_oneinit_sm_id(gr); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index 25228d09a30b..aeb767e582c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -85,10 +85,202 @@ gv100_gr_init_419bd8(struct gf100_gr *gr) nvkm_mask(device, 0x419bd8, 0x00000700, 0x00000000); } +u32 +gv100_gr_nonpes_aware_tpc(struct gf100_gr *gr, u32 gpc, u32 tpc) +{ + u32 pes, temp, tpc_new = 0; + + for (pes = 0; pes < gr->ppc_nr[gpc]; pes++) { + if (gr->ppc_tpc_mask[gpc][pes] & BIT(tpc)) + break; + + tpc_new += gr->ppc_tpc_nr[gpc][pes]; + } + + temp = (BIT(tpc) - 1) & gr->ppc_tpc_mask[gpc][pes]; + temp = hweight32(temp); + return tpc_new + temp; +} + +static int +gv100_gr_scg_estimate_perf(struct gf100_gr *gr, unsigned long *gpc_tpc_mask, + u32 disable_gpc, u32 disable_tpc, int *perf) +{ + const u32 scale_factor = 512UL; /* Use fx23.9 */ + const u32 pix_scale = 1024*1024UL; /* Pix perf in [29:20] */ + const u32 world_scale = 1024UL; /* World performance in [19:10] */ + const u32 tpc_scale = 1; /* TPC balancing in [9:0] */ + u32 scg_num_pes = 0; + u32 min_scg_gpc_pix_perf = scale_factor; /* Init perf as maximum */ + u32 average_tpcs = 0; /* Average of # of TPCs per GPC */ + u32 deviation; /* absolute diff between TPC# and average_tpcs, averaged across GPCs */ + u32 norm_tpc_deviation; /* deviation/max_tpc_per_gpc */ + u32 tpc_balance; + u32 scg_gpc_pix_perf; + u32 scg_world_perf; + u32 gpc; + u32 pes; + int diff; + bool tpc_removed_gpc = false; + bool tpc_removed_pes = false; + u32 max_tpc_gpc = 0; + u32 num_tpc_mask; + u32 *num_tpc_gpc; + int ret = -EINVAL; + + if (!(num_tpc_gpc = kcalloc(gr->gpc_nr, sizeof(*num_tpc_gpc), GFP_KERNEL))) + return -ENOMEM; + + /* Calculate pix-perf-reduction-rate per GPC and find bottleneck TPC */ + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + num_tpc_mask = gpc_tpc_mask[gpc]; + + if ((gpc == disable_gpc) && num_tpc_mask & BIT(disable_tpc)) { + /* Safety check if a TPC is removed twice */ + if (WARN_ON(tpc_removed_gpc)) + goto done; + + /* Remove logical TPC from set */ + num_tpc_mask &= ~BIT(disable_tpc); + tpc_removed_gpc = true; + } + + /* track balancing of tpcs across gpcs */ + num_tpc_gpc[gpc] = hweight32(num_tpc_mask); + average_tpcs += num_tpc_gpc[gpc]; + + /* save the maximum numer of gpcs */ + max_tpc_gpc = num_tpc_gpc[gpc] > max_tpc_gpc ? num_tpc_gpc[gpc] : max_tpc_gpc; + + /* + * Calculate ratio between TPC count and post-FS and post-SCG + * + * ratio represents relative throughput of the GPC + */ + scg_gpc_pix_perf = scale_factor * num_tpc_gpc[gpc] / gr->tpc_nr[gpc]; + if (min_scg_gpc_pix_perf > scg_gpc_pix_perf) + min_scg_gpc_pix_perf = scg_gpc_pix_perf; + + /* Calculate # of surviving PES */ + for (pes = 0; pes < gr->ppc_nr[gpc]; pes++) { + /* Count the number of TPC on the set */ + num_tpc_mask = gr->ppc_tpc_mask[gpc][pes] & gpc_tpc_mask[gpc]; + + if ((gpc == disable_gpc) && (num_tpc_mask & BIT(disable_tpc))) { + if (WARN_ON(tpc_removed_pes)) + goto done; + + num_tpc_mask &= ~BIT(disable_tpc); + tpc_removed_pes = true; + } + + if (hweight32(num_tpc_mask)) + scg_num_pes++; + } + } + + if (WARN_ON(!tpc_removed_gpc || !tpc_removed_pes)) + goto done; + + if (max_tpc_gpc == 0) { + *perf = 0; + goto done_ok; + } + + /* Now calculate perf */ + scg_world_perf = (scale_factor * scg_num_pes) / gr->ppc_total; + deviation = 0; + average_tpcs = scale_factor * average_tpcs / gr->gpc_nr; + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + diff = average_tpcs - scale_factor * num_tpc_gpc[gpc]; + if (diff < 0) + diff = -diff; + + deviation += diff; + } + + deviation /= gr->gpc_nr; + + norm_tpc_deviation = deviation / max_tpc_gpc; + + tpc_balance = scale_factor - norm_tpc_deviation; + + if ((tpc_balance > scale_factor) || + (scg_world_perf > scale_factor) || + (min_scg_gpc_pix_perf > scale_factor) || + (norm_tpc_deviation > scale_factor)) { + WARN_ON(1); + goto done; + } + + *perf = (pix_scale * min_scg_gpc_pix_perf) + + (world_scale * scg_world_perf) + + (tpc_scale * tpc_balance); +done_ok: + ret = 0; +done: + kfree(num_tpc_gpc); + return ret; +} + +int +gv100_gr_oneinit_sm_id(struct gf100_gr *gr) +{ + unsigned long *gpc_tpc_mask; + u32 *tpc_table, *gpc_table; + u32 gpc, tpc, pes, gtpc; + int perf, maxperf, ret = 0; + + gpc_tpc_mask = kcalloc(gr->gpc_nr, sizeof(*gpc_tpc_mask), GFP_KERNEL); + gpc_table = kcalloc(gr->tpc_total, sizeof(*gpc_table), GFP_KERNEL); + tpc_table = kcalloc(gr->tpc_total, sizeof(*tpc_table), GFP_KERNEL); + if (!gpc_table || !tpc_table || !gpc_tpc_mask) { + ret = -ENOMEM; + goto done; + } + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + for (pes = 0; pes < gr->ppc_nr[gpc]; pes++) + gpc_tpc_mask[gpc] |= gr->ppc_tpc_mask[gpc][pes]; + } + + for (gtpc = 0; gtpc < gr->tpc_total; gtpc++) { + for (maxperf = -1, gpc = 0; gpc < gr->gpc_nr; gpc++) { + for_each_set_bit(tpc, &gpc_tpc_mask[gpc], gr->tpc_nr[gpc]) { + ret = gv100_gr_scg_estimate_perf(gr, gpc_tpc_mask, gpc, tpc, &perf); + if (ret) + goto done; + + /* nvgpu does ">=" here, but this gets us RM's numbers. */ + if (perf > maxperf) { + maxperf = perf; + gpc_table[gtpc] = gpc; + tpc_table[gtpc] = tpc; + } + } + } + + gpc_tpc_mask[gpc_table[gtpc]] &= ~BIT(tpc_table[gtpc]); + } + + /*TODO: build table for sm_per_tpc != 1, don't use yet, but might need later? */ + for (gtpc = 0; gtpc < gr->tpc_total; gtpc++) { + gr->sm[gtpc].gpc = gpc_table[gtpc]; + gr->sm[gtpc].tpc = tpc_table[gtpc]; + gr->sm_nr++; + } + +done: + kfree(gpc_table); + kfree(tpc_table); + kfree(gpc_tpc_mask); + return ret; +} + static const struct gf100_gr_func gv100_gr = { .oneinit_tiles = gm200_gr_oneinit_tiles, - .oneinit_sm_id = gm200_gr_oneinit_sm_id, + .oneinit_sm_id = gv100_gr_oneinit_sm_id, .init = gf100_gr_init, .init_419bd8 = gv100_gr_init_419bd8, .init_gpc_mmu = gm200_gr_init_gpc_mmu, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 3491005cf5d7..1b1c6b219fc2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -40,8 +40,9 @@ tu102_gr_init_fs(struct gf100_gr *gr) gk104_grctx_generate_gpc_tpc_nr(gr); for (sm = 0; sm < gr->sm_nr; sm++) { - nvkm_wr32(device, GPC_UNIT(gr->sm[sm].gpc, 0x0c10 + - gr->sm[sm].tpc * 4), sm); + int tpc = gv100_gr_nonpes_aware_tpc(gr, gr->sm[sm].gpc, gr->sm[sm].tpc); + + nvkm_wr32(device, GPC_UNIT(gr->sm[sm].gpc, 0x0c10 + tpc * 4), sm); } gm200_grctx_generate_dist_skip_table(gr); @@ -93,7 +94,7 @@ tu102_gr_init_gpc_mmu(struct gf100_gr *gr) static const struct gf100_gr_func tu102_gr = { .oneinit_tiles = gm200_gr_oneinit_tiles, - .oneinit_sm_id = gm200_gr_oneinit_sm_id, + .oneinit_sm_id = gv100_gr_oneinit_sm_id, .init = gf100_gr_init, .init_419bd8 = gv100_gr_init_419bd8, .init_gpc_mmu = tu102_gr_init_gpc_mmu, -- cgit v1.2.3 From abf8d63113078341c232446d3c2b2bd42c9ca6ef Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:17 +1000 Subject: drm/nouveau/gr/gv100-: fix number of tile map registers Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c index d68741a81a58..5b6ab9e088c5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c @@ -113,13 +113,14 @@ void gv100_grctx_generate_rop_mapping(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 mapregs = DIV_ROUND_UP(gr->func->gpc_nr * gr->func->tpc_nr, 6); u32 data; int i, j; /* Pack tile map into register format. */ nvkm_wr32(device, 0x418bb8, (gr->tpc_total << 8) | gr->screen_tile_row_offset); - for (i = 0; i < 11; i++) { + for (i = 0; i < mapregs; i++) { for (data = 0, j = 0; j < 6; j++) data |= (gr->tile[i * 6 + j] & 0x1f) << (j * 5); nvkm_wr32(device, 0x418b08 + (i * 4), data); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index aeb767e582c8..4951d482f4de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -302,7 +302,7 @@ gv100_gr = { .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, .gpc_nr = 6, - .tpc_nr = 5, + .tpc_nr = 7, .ppc_nr = 3, .grctx = &gv100_grctx, .zbc = &gp102_gr_zbc, -- cgit v1.2.3 From 81d4201e7ffc0d86e3cf3659f8341545d410b023 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:18 +1000 Subject: drm/nouveau/gr/gv100-: add NV_PGRAPH_PRI_PD_AB_DIST_CONFIG_1 to patch list Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c index 5b6ab9e088c5..65812452f149 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c @@ -66,6 +66,7 @@ gv100_grctx_generate_attrib(struct gf100_gr_chan *chan) const u32 alpha = grctx->alpha_nr; const u32 attrib = grctx->attrib_nr; const u32 gfxp = grctx->gfxp_nr; + const int max_batches = 0xffff; u32 size = grctx->alpha_nr_max * gr->tpc_total; u32 ao = 0; u32 bo = ao + size; @@ -73,6 +74,7 @@ gv100_grctx_generate_attrib(struct gf100_gr_chan *chan) gf100_grctx_patch_wr32(chan, 0x405830, attrib); gf100_grctx_patch_wr32(chan, 0x40585c, alpha); + gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) { -- cgit v1.2.3 From 75e637db601acbd2b59ca9f97474203635da5b52 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:19 +1000 Subject: drm/nouveau/gr/gv100-: move init_419bd8() after sw_ctx load Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 3 +++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index a56f4f3f6c1e..7c318cdcb428 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1359,6 +1359,9 @@ gf100_grctx_generate_main(struct gf100_gr_chan *chan) gf100_gr_mmio(gr, gr->sw_ctx); } + if (gr->func->init_419bd8) + gr->func->init_419bd8(gr); + gf100_gr_wait_idle(gr); idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 5ce83b915ebb..ddf06f5e7535 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2333,9 +2333,6 @@ gf100_gr_init(struct gf100_gr *gr) nvkm_mask(device, 0x400500, 0x00010001, 0x00000000); - if (gr->func->init_419bd8) - gr->func->init_419bd8(gr); - gr->func->init_gpc_mmu(gr); if (gr->sw_nonctx) -- cgit v1.2.3 From edc6938f7bc6b954137b073c928dc71af34cc158 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:19 +1000 Subject: drm/nouveau/gr/gv100-: drop a write from init_shader_exceptions() Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index 4951d482f4de..ebf79ea985b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -65,7 +65,6 @@ gv100_gr_init_shader_exceptions(struct gf100_gr *gr, int gpc, int tpc) struct nvkm_device *device = gr->base.engine.subdev.device; int sm; for (sm = 0; sm < 0x100; sm += 0x80) { - nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x728 + sm), 0x0085eb64); nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x610), 0x00000001); nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x72c + sm), 0x00000004); } -- cgit v1.2.3 From 1cd97b5490c860409338eda1d9c16df20621024c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:20 +1000 Subject: drm/nouveau/gr/tu102-: use sw_veid_bundle_init from firmware NVIDIA provided this on Turing, but we kept using the hardcoded version from Volta (where they didn't). Switch to the firmware version prior to Ampere. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 5 +++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 4 ++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 12 +++++++++--- drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 24 +++++++++++++++++++++++ 8 files changed, 44 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 7c318cdcb428..38502dfd984b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1381,12 +1381,17 @@ gf100_grctx_generate_main(struct gf100_gr_chan *chan) gf100_gr_wait_idle(gr); if (grctx->r400088) grctx->r400088(gr, false); + if (gr->bundle) gf100_gr_icmd(gr, gr->bundle); else gf100_gr_icmd(gr, grctx->icmd); + + if (gr->bundle_veid) + gf100_gr_icmd(gr, gr->bundle_veid); if (grctx->sw_veid_bundle_init) gf100_gr_icmd(gr, grctx->sw_veid_bundle_init); + if (grctx->r400088) grctx->r400088(gr, true); nvkm_wr32(device, 0x404154, idle_timeout); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 99bb9af4955a..7a4ce97b033d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -153,7 +153,6 @@ extern const struct gf100_grctx_func gv100_grctx; extern const struct gf100_grctx_func tu102_grctx; void gv100_grctx_unkn88c(struct gf100_gr *, bool); void gv100_grctx_generate_unkn(struct gf100_gr *); -extern const struct gf100_gr_init gv100_grctx_init_sw_veid_bundle_init_0[]; void gv100_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32); void gv100_grctx_generate_attrib(struct gf100_gr_chan *); void gv100_grctx_generate_rop_mapping(struct gf100_gr *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c index 65812452f149..957ea9d6bad4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c @@ -25,7 +25,7 @@ * PGRAPH context implementation ******************************************************************************/ -const struct gf100_gr_init +static const struct gf100_gr_init gv100_grctx_init_sw_veid_bundle_init_0[] = { { 0x00001000, 64, 0x00100000, 0x00000008 }, { 0x00000941, 64, 0x00100000, 0x00000000 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c index da1bac3963a9..54bdfe304ac7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c @@ -51,7 +51,6 @@ tu102_grctx_init_unknown_bundle_init_0[] = { static const struct gf100_gr_pack tu102_grctx_pack_sw_veid_bundle_init[] = { - { gv100_grctx_init_sw_veid_bundle_init_0 }, { tu102_grctx_init_unknown_bundle_init_0 }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index ddf06f5e7535..6b559b2bd8f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2139,6 +2139,7 @@ gf100_gr_dtor(struct nvkm_gr *base) nvkm_blob_dtor(&gr->gpccs.inst); nvkm_blob_dtor(&gr->gpccs.data); + vfree(gr->bundle_veid); vfree(gr->bundle); vfree(gr->method); vfree(gr->sw_ctx); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index a9ba9af25728..6e1c730932b4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -90,6 +90,7 @@ struct gf100_gr { struct gf100_gr_pack *sw_nonctx; struct gf100_gr_pack *sw_ctx; struct gf100_gr_pack *bundle; + struct gf100_gr_pack *bundle_veid; struct gf100_gr_pack *method; struct gf100_gr_zbc_color zbc_color[NVKM_LTC_MAX_ZBC_COLOR_CNT]; @@ -224,6 +225,7 @@ void gm107_gr_init_shader_exceptions(struct gf100_gr *, int, int); void gm107_gr_init_400054(struct gf100_gr *); int gk20a_gr_init(struct gf100_gr *); +int gk20a_gr_av_to_init_(struct nvkm_blob *, u8 count, u32 pitch, struct gf100_gr_pack **); int gk20a_gr_av_to_init(struct nvkm_blob *, struct gf100_gr_pack **); int gk20a_gr_aiv_to_init(struct nvkm_blob *, struct gf100_gr_pack **); int gk20a_gr_av_to_method(struct nvkm_blob *, struct gf100_gr_pack **); @@ -253,6 +255,8 @@ void gv100_gr_init_504430(struct gf100_gr *, int, int); void gv100_gr_init_shader_exceptions(struct gf100_gr *, int, int); void gv100_gr_trap_mp(struct gf100_gr *, int, int); +int tu102_gr_av_to_init_veid(struct nvkm_blob *, struct gf100_gr_pack **); + #define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) #include diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index 2aee0559efca..035ea213f543 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -34,7 +34,7 @@ struct gk20a_fw_av }; int -gk20a_gr_av_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) +gk20a_gr_av_to_init_(struct nvkm_blob *blob, u8 count, u32 pitch, struct gf100_gr_pack **ppack) { struct gf100_gr_init *init; struct gf100_gr_pack *pack; @@ -55,14 +55,20 @@ gk20a_gr_av_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) ent->addr = av->addr; ent->data = av->data; - ent->count = 1; - ent->pitch = 1; + ent->count = ((ent->addr & 0xffff) != 0xe100) ? count : 1; + ent->pitch = pitch; } *ppack = pack; return 0; } +int +gk20a_gr_av_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) +{ + return gk20a_gr_av_to_init_(blob, 1, 1, ppack); +} + struct gk20a_fw_aiv { u32 addr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 1b1c6b219fc2..96ba82a26385 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -141,6 +141,7 @@ MODULE_FIRMWARE("nvidia/tu102/gr/sw_ctx.bin"); MODULE_FIRMWARE("nvidia/tu102/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/tu102/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu102/gr/sw_method_init.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/sw_veid_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu104/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/tu104/gr/fecs_inst.bin"); @@ -154,6 +155,7 @@ MODULE_FIRMWARE("nvidia/tu104/gr/sw_ctx.bin"); MODULE_FIRMWARE("nvidia/tu104/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/tu104/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu104/gr/sw_method_init.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/sw_veid_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu106/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/tu106/gr/fecs_inst.bin"); @@ -167,6 +169,7 @@ MODULE_FIRMWARE("nvidia/tu106/gr/sw_ctx.bin"); MODULE_FIRMWARE("nvidia/tu106/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/tu106/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu106/gr/sw_method_init.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/sw_veid_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu117/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/tu117/gr/fecs_inst.bin"); @@ -180,6 +183,7 @@ MODULE_FIRMWARE("nvidia/tu117/gr/sw_ctx.bin"); MODULE_FIRMWARE("nvidia/tu117/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/tu117/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu117/gr/sw_method_init.bin"); +MODULE_FIRMWARE("nvidia/tu117/gr/sw_veid_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu116/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/tu116/gr/fecs_inst.bin"); @@ -193,6 +197,26 @@ MODULE_FIRMWARE("nvidia/tu116/gr/sw_ctx.bin"); MODULE_FIRMWARE("nvidia/tu116/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/tu116/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/tu116/gr/sw_method_init.bin"); +MODULE_FIRMWARE("nvidia/tu116/gr/sw_veid_bundle_init.bin"); + +int +tu102_gr_av_to_init_veid(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) +{ + return gk20a_gr_av_to_init_(blob, 64, 0x00100000, ppack); +} + +int +tu102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) +{ + int ret; + + ret = gm200_gr_load(gr, ver, fwif); + if (ret) + return ret; + + return gk20a_gr_load_net(gr, "gr/", "sw_veid_bundle_init", ver, tu102_gr_av_to_init_veid, + &gr->bundle_veid); +} static const struct gf100_gr_fwif tu102_gr_fwif[] = { -- cgit v1.2.3 From c4d66f7db67248b110b4183f1b155c28c752121f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:21 +1000 Subject: drm/nouveau/gr/tu102-: fix support for sw_bundle64_init We weren't sending the high bits, though they're zero currently anyway. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 8 +++++++- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c | 6 +++--- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 5 ++++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 3 ++- 5 files changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 38502dfd984b..2a31d4464a32 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1389,9 +1389,15 @@ gf100_grctx_generate_main(struct gf100_gr_chan *chan) if (gr->bundle_veid) gf100_gr_icmd(gr, gr->bundle_veid); - if (grctx->sw_veid_bundle_init) + else gf100_gr_icmd(gr, grctx->sw_veid_bundle_init); + if (gr->bundle64) + gf100_gr_icmd(gr, gr->bundle64); + else + if (grctx->sw_bundle64_init) + gf100_gr_icmd(gr, grctx->sw_bundle64_init); + if (grctx->r400088) grctx->r400088(gr, true); nvkm_wr32(device, 0x404154, idle_timeout); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 7a4ce97b033d..46f94c143936 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -22,6 +22,7 @@ struct gf100_grctx_func { const struct gf100_gr_pack *icmd; const struct gf100_gr_pack *mthd; const struct gf100_gr_pack *sw_veid_bundle_init; + const struct gf100_gr_pack *sw_bundle64_init; /* bundle circular buffer */ void (*bundle)(struct gf100_gr_chan *, u64 addr, u32 size); u32 bundle_size; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c index 54bdfe304ac7..36c38d004087 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c @@ -50,8 +50,8 @@ tu102_grctx_init_unknown_bundle_init_0[] = { }; static const struct gf100_gr_pack -tu102_grctx_pack_sw_veid_bundle_init[] = { - { tu102_grctx_init_unknown_bundle_init_0 }, +tu102_grctx_pack_sw_bundle64_init[] = { + { tu102_grctx_init_unknown_bundle_init_0, .type = 64 }, {} }; @@ -69,7 +69,7 @@ tu102_grctx = { .unkn88c = gv100_grctx_unkn88c, .main = gf100_grctx_generate_main, .unkn = gv100_grctx_generate_unkn, - .sw_veid_bundle_init = tu102_grctx_pack_sw_veid_bundle_init, + .sw_bundle64_init = tu102_grctx_pack_sw_bundle64_init, .bundle = gm107_grctx_generate_bundle, .bundle_size = 0x3000, .bundle_min_gpm_fifo_depth = 0x180, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 6b559b2bd8f8..b82989ef7f3b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1097,7 +1097,7 @@ gf100_gr_icmd(struct gf100_gr *gr, const struct gf100_gr_pack *p) struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_gr_pack *pack; const struct gf100_gr_init *init; - u32 data = 0; + u64 data = 0; nvkm_wr32(device, 0x400208, 0x80000000); @@ -1107,6 +1107,8 @@ gf100_gr_icmd(struct gf100_gr *gr, const struct gf100_gr_pack *p) if ((pack == p && init == p->init) || data != init->data) { nvkm_wr32(device, 0x400204, init->data); + if (pack->type == 64) + nvkm_wr32(device, 0x40020c, upper_32_bits(init->data)); data = init->data; } @@ -2139,6 +2141,7 @@ gf100_gr_dtor(struct nvkm_gr *base) nvkm_blob_dtor(&gr->gpccs.inst); nvkm_blob_dtor(&gr->gpccs.data); + vfree(gr->bundle64); vfree(gr->bundle_veid); vfree(gr->bundle); vfree(gr->method); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 6e1c730932b4..baf21aaf0021 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -91,6 +91,7 @@ struct gf100_gr { struct gf100_gr_pack *sw_ctx; struct gf100_gr_pack *bundle; struct gf100_gr_pack *bundle_veid; + struct gf100_gr_pack *bundle64; struct gf100_gr_pack *method; struct gf100_gr_zbc_color zbc_color[NVKM_LTC_MAX_ZBC_COLOR_CNT]; @@ -286,7 +287,7 @@ struct gf100_gr_init { u32 addr; u8 count; u32 pitch; - u32 data; + u64 data; }; struct gf100_gr_pack { -- cgit v1.2.3 From 6a2b09e7bf3fe9bcdd38b84c12e34c7b4cbb263d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:21 +1000 Subject: drm/nouveau/gr/tu102: add gv100_gr_init_4188a4 Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index baf21aaf0021..88fccea248e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -254,6 +254,7 @@ u32 gv100_gr_nonpes_aware_tpc(struct gf100_gr *gr, u32 gpc, u32 tpc); void gv100_gr_init_419bd8(struct gf100_gr *); void gv100_gr_init_504430(struct gf100_gr *, int, int); void gv100_gr_init_shader_exceptions(struct gf100_gr *, int, int); +void gv100_gr_init_4188a4(struct gf100_gr *); void gv100_gr_trap_mp(struct gf100_gr *, int, int); int tu102_gr_av_to_init_veid(struct nvkm_blob *, struct gf100_gr_pack **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index ebf79ea985b3..7f7404a76140 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -52,10 +52,11 @@ gv100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc) gv100_gr_trap_sm(gr, gpc, tpc, 1); } -static void +void gv100_gr_init_4188a4(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; + nvkm_mask(device, 0x4188a4, 0x03000000, 0x03000000); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 96ba82a26385..255d50c4c65f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -112,6 +112,7 @@ tu102_gr = { .init_shader_exceptions = gv100_gr_init_shader_exceptions, .init_rop_exceptions = gf100_gr_init_rop_exceptions, .init_exception2 = gf100_gr_init_exception2, + .init_4188a4 = gv100_gr_init_4188a4, .trap_mp = gv100_gr_trap_mp, .fecs.reset = gf100_gr_fecs_reset, .rops = gm200_gr_rops, -- cgit v1.2.3 From 21876b0e4284169ddbc834d02f60940a3dd27471 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:22 +1000 Subject: drm/nouveau/gr/tu102: remove gv100_grctx_unkn88c Match RM. Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c index 36c38d004087..542ab0c78be6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c @@ -66,7 +66,6 @@ tu102_grctx_generate_unknown(struct gf100_gr_chan *chan, u64 addr, u32 size) const struct gf100_grctx_func tu102_grctx = { - .unkn88c = gv100_grctx_unkn88c, .main = gf100_grctx_generate_main, .unkn = gv100_grctx_generate_unkn, .sw_bundle64_init = tu102_grctx_pack_sw_bundle64_init, -- cgit v1.2.3 From a51c69ee74d195e6d84fe9d48ca55f51d39e1b5b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:32 +1000 Subject: drm/nouveau/fb/ga102: load and boot VPR scrubber FW v2. fixup for ga103 early merge Signed-off-by: Ben Skeggs Signed-off-by: Gourav Samaiya --- drivers/gpu/drm/nouveau/include/nvfw/hs.h | 28 +++++ drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 25 ++++ .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 6 + .../gpu/drm/nouveau/include/nvkm/engine/nvdec.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 5 + drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c | 61 ++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h | 2 +- drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild | 2 + drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 77 ++++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/fw.c | 58 +++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c | 62 ++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c | 134 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 9 +- drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c | 8 ++ drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c | 39 ++++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c | 32 +++++ 19 files changed, 551 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/hs.h b/drivers/gpu/drm/nouveau/include/nvfw/hs.h index b53bbc4cd130..8c4cd08a7b5f 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/hs.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/hs.h @@ -17,6 +17,20 @@ struct nvfw_hs_header { const struct nvfw_hs_header *nvfw_hs_header(struct nvkm_subdev *, const void *); +struct nvfw_hs_header_v2 { + u32 sig_prod_offset; + u32 sig_prod_size; + u32 patch_loc; + u32 patch_sig; + u32 meta_data_offset; + u32 meta_data_size; + u32 num_sig; + u32 header_offset; + u32 header_size; +}; + +const struct nvfw_hs_header_v2 *nvfw_hs_header_v2(struct nvkm_subdev *, const void *); + struct nvfw_hs_load_header { u32 non_sec_code_off; u32 non_sec_code_size; @@ -28,4 +42,18 @@ struct nvfw_hs_load_header { const struct nvfw_hs_load_header * nvfw_hs_load_header(struct nvkm_subdev *, const void *); + +struct nvfw_hs_load_header_v2 { + u32 os_code_offset; + u32 os_code_size; + u32 os_data_offset; + u32 os_data_size; + u32 num_apps; + struct { + u32 offset; + u32 size; + } app[0]; +}; + +const struct nvfw_hs_load_header_v2 *nvfw_hs_load_header_v2(struct nvkm_subdev *, const void *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 4868d2cb796f..45d70aa4fd6d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -31,6 +31,13 @@ struct nvkm_falcon_func_pio { void (*rd)(struct nvkm_falcon *, u8 port, const u8 *img, int len); }; +struct nvkm_falcon_func_dma { + int (*init)(struct nvkm_falcon *, u64 dma_addr, int xfer_len, + enum nvkm_falcon_mem, bool sec, u32 *cmd); + void (*xfer)(struct nvkm_falcon *, u32 mem_base, u32 dma_base, u32 cmd); + bool (*done)(struct nvkm_falcon *); +}; + int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner, const char *name, u32 addr, struct nvkm_falcon *); void nvkm_falcon_dtor(struct nvkm_falcon *); @@ -39,6 +46,8 @@ int nvkm_falcon_pio_wr(struct nvkm_falcon *, const u8 *img, u32 img_base, u8 por enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec); int nvkm_falcon_pio_rd(struct nvkm_falcon *, u8 port, enum nvkm_falcon_mem type, u32 mem_base, const u8 *img, u32 img_base, int len); +int nvkm_falcon_dma_wr(struct nvkm_falcon *, const u8 *img, u64 dma_addr, u32 dma_base, + enum nvkm_falcon_mem mem_type, u32 mem_base, int len, bool sec); int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *); int gm200_flcn_disable(struct nvkm_falcon *); @@ -52,6 +61,10 @@ void gm200_flcn_tracepc(struct nvkm_falcon *); int gp102_flcn_reset_eng(struct nvkm_falcon *); extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio; +int ga102_flcn_reset_prep(struct nvkm_falcon *); +int ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *); +extern const struct nvkm_falcon_func_dma ga102_flcn_dma; + void nvkm_falcon_v1_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); @@ -87,6 +100,9 @@ struct nvkm_falcon_fw { u32 sig_size; int sig_nr; u8 *sigs; + u32 fuse_ver; + u32 engine_id; + u32 ucode_id; u32 nmem_base_img; u32 nmem_base; @@ -117,6 +133,9 @@ int nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *, const char *name, st int nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *, const char *name, struct nvkm_subdev *, const char *bl, const char *img, int ver, struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw); +int nvkm_falcon_fw_ctor_hs_v2(const struct nvkm_falcon_fw_func *, const char *name, + struct nvkm_subdev *, const char *img, int ver, struct nvkm_falcon *, + struct nvkm_falcon_fw *); int nvkm_falcon_fw_sign(struct nvkm_falcon_fw *, u32 sig_base_img, u32 sig_size, const u8 *sigs, int sig_nr_prd, u32 sig_base_prd, int sig_nr_dbg, u32 sig_base_dbg); int nvkm_falcon_fw_patch(struct nvkm_falcon_fw *); @@ -132,6 +151,12 @@ int gm200_flcn_fw_reset(struct nvkm_falcon_fw *); int gm200_flcn_fw_load(struct nvkm_falcon_fw *); int gm200_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32); +int ga100_flcn_fw_signature(struct nvkm_falcon_fw *, u32 *); + +extern const struct nvkm_falcon_fw_func ga102_flcn_fw; +int ga102_flcn_fw_load(struct nvkm_falcon_fw *); +int ga102_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32); + #define FLCNFW_PRINTK(f,l,p,fmt,a...) FLCN_PRINTK((f)->falcon, l, p, "%s: "fmt, (f)->fw.name, ##a) #define FLCNFW_DBG(f,fmt,a...) FLCNFW_PRINTK((f), DEBUG, info, fmt"\n", ##a) #define FLCNFW_ERR(f,fmt,a...) FLCNFW_PRINTK((f), ERROR, err, fmt"\n", ##a) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index f576ca246d10..dacbd92edcd5 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -19,6 +19,7 @@ struct nvkm_falcon { struct nvkm_subdev *owner; const char *name; u32 addr; + u32 addr2; struct mutex mutex; struct mutex dmem_mutex; @@ -59,8 +60,10 @@ int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *, struct nvkm_falcon_func { int (*disable)(struct nvkm_falcon *); int (*enable)(struct nvkm_falcon *); + u32 addr2; bool reset_pmc; int (*reset_eng)(struct nvkm_falcon *); + int (*reset_prep)(struct nvkm_falcon *); int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *); u32 debug; @@ -69,7 +72,10 @@ struct nvkm_falcon_func { bool bind_intr; const struct nvkm_falcon_func_pio *imem_pio; + const struct nvkm_falcon_func_dma *imem_dma; + const struct nvkm_falcon_func_pio *dmem_pio; + const struct nvkm_falcon_func_dma *dmem_dma; u32 emem_addr; const struct nvkm_falcon_func_pio *emem_pio; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h index 97bd3092f68a..9baf197ac833 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h @@ -12,4 +12,5 @@ struct nvkm_nvdec { }; int gm107_nvdec_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_nvdec **); +int ga102_nvdec_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_nvdec **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 931a59581815..8162efcf2dd6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2615,6 +2615,7 @@ nv172_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .nvdec = { 0x00000001, ga102_nvdec_new }, }; static const struct nvkm_device_chip @@ -2639,6 +2640,7 @@ nv173_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .nvdec = { 0x00000001, ga102_nvdec_new }, }; static const struct nvkm_device_chip @@ -2663,6 +2665,7 @@ nv174_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .nvdec = { 0x00000001, ga102_nvdec_new }, }; static const struct nvkm_device_chip @@ -2687,6 +2690,7 @@ nv176_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .nvdec = { 0x00000001, ga102_nvdec_new }, }; static const struct nvkm_device_chip @@ -2711,6 +2715,7 @@ nv177_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .nvdec = { 0x00000001, ga102_nvdec_new }, }; struct nvkm_subdev * diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild index 9a0fd9812750..f05e79670d22 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild @@ -1,3 +1,4 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/engine/nvdec/base.o nvkm-y += nvkm/engine/nvdec/gm107.o +nvkm-y += nvkm/engine/nvdec/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c index b0181cc5953b..1f6e3b32ba16 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c @@ -37,7 +37,7 @@ nvkm_nvdec = { int nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_nvdec **pnvdec) + enum nvkm_subdev_type type, int inst, u32 addr, struct nvkm_nvdec **pnvdec) { struct nvkm_nvdec *nvdec; int ret; @@ -57,5 +57,5 @@ nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device, nvdec->func = fwif->func; return nvkm_falcon_ctor(nvdec->func->flcn, &nvdec->engine.subdev, - nvdec->engine.subdev.name, 0, &nvdec->falcon); + nvdec->engine.subdev.name, addr, &nvdec->falcon); }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c new file mode 100644 index 000000000000..37d8c3c0f3ab --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c @@ -0,0 +1,61 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +#include +#include + +static const struct nvkm_falcon_func +ga102_nvdec_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .addr2 = 0x1c00, + .reset_pmc = true, + .reset_prep = ga102_flcn_reset_prep, + .reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing, + .imem_dma = &ga102_flcn_dma, + .dmem_dma = &ga102_flcn_dma, +}; + +static const struct nvkm_nvdec_func +ga102_nvdec = { + .flcn = &ga102_nvdec_flcn, +}; + +static int +ga102_nvdec_nofw(struct nvkm_nvdec *nvdec, int ver, const struct nvkm_nvdec_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_nvdec_fwif +ga102_nvdec_fwif[] = { + { -1, ga102_nvdec_nofw, &ga102_nvdec }, + {} +}; + +int +ga102_nvdec_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_nvdec **pnvdec) +{ + return nvkm_nvdec_new_(ga102_nvdec_fwif, device, type, inst, 0x848000, pnvdec); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c index 5d04ded35cc3..564f7e8960a2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c @@ -54,5 +54,5 @@ int gm107_nvdec_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_nvdec **pnvdec) { - return nvkm_nvdec_new_(gm107_nvdec_fwif, device, type, inst, pnvdec); + return nvkm_nvdec_new_(gm107_nvdec_fwif, device, type, inst, 0, pnvdec); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h index 0920f6a887e2..61e1f7aaa509 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h @@ -15,5 +15,5 @@ struct nvkm_nvdec_fwif { }; int nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *, - enum nvkm_subdev_type, int, struct nvkm_nvdec **); + enum nvkm_subdev_type, int, u32 addr, struct nvkm_nvdec **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild index 6ffde5290b87..9ffe7b921ccb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild @@ -8,3 +8,5 @@ nvkm-y += nvkm/falcon/v1.o nvkm-y += nvkm/falcon/gm200.o nvkm-y += nvkm/falcon/gp102.o +nvkm-y += nvkm/falcon/ga100.o +nvkm-y += nvkm/falcon/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index e4075aa441f3..235149f73a69 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -25,6 +25,82 @@ #include #include +static const struct nvkm_falcon_func_dma * +nvkm_falcon_dma(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base) +{ + switch (*mem_type) { + case IMEM: return falcon->func->imem_dma; + case DMEM: return falcon->func->dmem_dma; + default: + return NULL; + } +} + +int +nvkm_falcon_dma_wr(struct nvkm_falcon *falcon, const u8 *img, u64 dma_addr, u32 dma_base, + enum nvkm_falcon_mem mem_type, u32 mem_base, int len, bool sec) +{ + const struct nvkm_falcon_func_dma *dma = nvkm_falcon_dma(falcon, &mem_type, &mem_base); + const char *type = nvkm_falcon_mem(mem_type); + const int dmalen = 256; + u32 dma_start = 0; + u32 dst, src, cmd; + int ret, i; + + if (WARN_ON(!dma->xfer)) + return -EINVAL; + + if (mem_type == DMEM) { + dma_start = dma_base; + dma_addr += dma_base; + } + + FLCN_DBG(falcon, "%s %08x <- %08x bytes at %08x (%010llx %08x)", + type, mem_base, len, dma_base, dma_addr - dma_base, dma_start); + if (WARN_ON(!len || (len & (dmalen - 1)))) + return -EINVAL; + + ret = dma->init(falcon, dma_addr, dmalen, mem_type, sec, &cmd); + if (ret) + return ret; + + dst = mem_base; + src = dma_base; + if (len) { + while (len >= dmalen) { + dma->xfer(falcon, dst, src - dma_start, cmd); + + if (img && nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) { + for (i = 0; i < dmalen; i += 4, mem_base += 4) { + const int w = 8, x = (i / 4) % w; + + if (x == 0) + printk(KERN_INFO "%s %08x <-", type, mem_base); + printk(KERN_CONT " %08x", *(u32 *)(img + src + i)); + if (x == (w - 1) || ((i + 4) == dmalen)) + printk(KERN_CONT " <- %08x+%08x", dma_base, + src + i - dma_base - (x * 4)); + if (i == (7 * 4)) + printk(KERN_CONT " *"); + } + } + + if (nvkm_msec(falcon->owner->device, 2000, + if (dma->done(falcon)) + break; + ) < 0) + return -ETIMEDOUT; + + src += dmalen; + dst += dmalen; + len -= dmalen; + } + WARN_ON(len); + } + + return 0; +} + static const struct nvkm_falcon_func_pio * nvkm_falcon_pio(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base) { @@ -239,6 +315,7 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func, falcon->owner = subdev; falcon->name = name; falcon->addr = addr; + falcon->addr2 = func->addr2; mutex_init(&falcon->mutex); mutex_init(&falcon->dmem_mutex); return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c index 13d52d7e4f60..80a480b12174 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c @@ -294,3 +294,61 @@ done: nvkm_firmware_put(blob); return ret; } + +int +nvkm_falcon_fw_ctor_hs_v2(const struct nvkm_falcon_fw_func *func, const char *name, + struct nvkm_subdev *subdev, const char *img, int ver, + struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw) +{ + const struct nvfw_bin_hdr *hdr; + const struct nvfw_hs_header_v2 *hshdr; + const struct nvfw_hs_load_header_v2 *lhdr; + const struct firmware *blob; + u32 loc, sig, cnt, *meta; + int ret; + + ret = nvkm_firmware_load_name(subdev, img, "", ver, &blob); + if (ret) + return ret; + + hdr = nvfw_bin_hdr(subdev, blob->data); + hshdr = nvfw_hs_header_v2(subdev, blob->data + hdr->header_offset); + meta = (u32 *)(blob->data + hshdr->meta_data_offset); + loc = *(u32 *)(blob->data + hshdr->patch_loc); + sig = *(u32 *)(blob->data + hshdr->patch_sig); + cnt = *(u32 *)(blob->data + hshdr->num_sig); + + ret = nvkm_falcon_fw_ctor(func, name, subdev->device, true, + blob->data + hdr->data_offset, hdr->data_size, falcon, fw); + if (ret) + goto done; + + ret = nvkm_falcon_fw_sign(fw, loc, hshdr->sig_prod_size / cnt, blob->data, + cnt, hshdr->sig_prod_offset + sig, 0, 0); + if (ret) + goto done; + + lhdr = nvfw_hs_load_header_v2(subdev, blob->data + hshdr->header_offset); + + fw->imem_base_img = lhdr->app[0].offset; + fw->imem_base = 0; + fw->imem_size = lhdr->app[0].size; + + fw->dmem_base_img = lhdr->os_data_offset; + fw->dmem_base = 0; + fw->dmem_size = lhdr->os_data_size; + fw->dmem_sign = loc - lhdr->os_data_offset; + + fw->boot_addr = lhdr->app[0].offset; + + fw->fuse_ver = meta[0]; + fw->engine_id = meta[1]; + fw->ucode_id = meta[2]; + +done: + if (ret) + nvkm_falcon_fw_dtor(fw); + + nvkm_firmware_put(blob); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c b/drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c new file mode 100644 index 000000000000..49fd32943916 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c @@ -0,0 +1,62 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +int +ga100_flcn_fw_signature(struct nvkm_falcon_fw *fw, u32 *src_base_src) +{ + struct nvkm_falcon *falcon = fw->falcon; + struct nvkm_device *device = falcon->owner->device; + u32 reg_fuse_version; + int idx; + + FLCN_DBG(falcon, "brom: %08x %08x", fw->engine_id, fw->ucode_id); + FLCN_DBG(falcon, "fuse_version: %d", fw->fuse_ver); + + if (fw->engine_id & 0x00000001) { + reg_fuse_version = nvkm_rd32(device, 0x824140 + (fw->ucode_id - 1) * 4); + } else + if (fw->engine_id & 0x00000004) { + reg_fuse_version = nvkm_rd32(device, 0x824100 + (fw->ucode_id - 1) * 4); + } else + if (fw->engine_id & 0x00000400) { + reg_fuse_version = nvkm_rd32(device, 0x8241c0 + (fw->ucode_id - 1) * 4); + } else { + WARN_ON(1); + return -ENOSYS; + } + + FLCN_DBG(falcon, "reg_fuse_version: %08x", reg_fuse_version); + if (reg_fuse_version) { + reg_fuse_version = fls(reg_fuse_version); + FLCN_DBG(falcon, "reg_fuse_version: %d", reg_fuse_version); + + if (WARN_ON(fw->fuse_ver < reg_fuse_version)) + return -EINVAL; + + idx = fw->fuse_ver - reg_fuse_version; + } else { + idx = fw->sig_nr - 1; + } + + return idx; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c b/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c new file mode 100644 index 000000000000..38306f9920b4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c @@ -0,0 +1,134 @@ +/* + * Copyright 2022 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +#include +#include + +static bool +ga102_flcn_dma_done(struct nvkm_falcon *falcon) +{ + return !!(nvkm_falcon_rd32(falcon, 0x118) & 0x00000002); +} + +static void +ga102_flcn_dma_xfer(struct nvkm_falcon *falcon, u32 mem_base, u32 dma_base, u32 cmd) +{ + nvkm_falcon_wr32(falcon, 0x114, mem_base); + nvkm_falcon_wr32(falcon, 0x11c, dma_base); + nvkm_falcon_wr32(falcon, 0x118, cmd); +} + +static int +ga102_flcn_dma_init(struct nvkm_falcon *falcon, u64 dma_addr, int xfer_len, + enum nvkm_falcon_mem mem_type, bool sec, u32 *cmd) +{ + *cmd = (ilog2(xfer_len) - 2) << 8; + if (mem_type == IMEM) + *cmd |= 0x00000010; + if (sec) + *cmd |= 0x00000004; + + nvkm_falcon_wr32(falcon, 0x110, dma_addr >> 8); + nvkm_falcon_wr32(falcon, 0x128, 0x00000000); + return 0; +} + +const struct nvkm_falcon_func_dma +ga102_flcn_dma = { + .init = ga102_flcn_dma_init, + .xfer = ga102_flcn_dma_xfer, + .done = ga102_flcn_dma_done, +}; + +int +ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon) +{ + nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000); + + if (nvkm_msec(falcon->owner->device, 20, + if (!(nvkm_falcon_rd32(falcon, 0x0f4) & 0x00001000)) + break; + ) < 0) + return -ETIMEDOUT; + + return 0; +} + +int +ga102_flcn_reset_prep(struct nvkm_falcon *falcon) +{ + const u32 addr2 = (falcon->owner->type != NVKM_ENGINE_NVDEC) ? 0x530 : 0x930; + + if (nvkm_msec(falcon->owner->device, 10, + if ((nvkm_falcon_rd32(falcon, falcon->addr2 + 0x1ec) & 0x00000003) == 0x00000001 && + (nvkm_falcon_rd32(falcon, addr2) & 0x00000008) == 0x00000008) + break; + ) < 0) + return -ETIMEDOUT; + + return 0; +} + +int +ga102_flcn_fw_boot(struct nvkm_falcon_fw *fw, u32 *mbox0, u32 *mbox1, u32 mbox0_ok, u32 irqsclr) +{ + struct nvkm_falcon *falcon = fw->falcon; + + nvkm_falcon_wr32(falcon, falcon->addr2 + 0x210, fw->dmem_sign); + nvkm_falcon_wr32(falcon, falcon->addr2 + 0x19c, fw->engine_id); + nvkm_falcon_wr32(falcon, falcon->addr2 + 0x198, fw->ucode_id); + nvkm_falcon_wr32(falcon, falcon->addr2 + 0x180, 0x00000001); + + return gm200_flcn_fw_boot(fw, mbox0, mbox1, mbox0_ok, irqsclr); +} + +int +ga102_flcn_fw_load(struct nvkm_falcon_fw *fw) +{ + struct nvkm_falcon *falcon = fw->falcon; + int ret = 0; + + nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080); + nvkm_falcon_wr32(falcon, 0x10c, 0x00000000); + nvkm_falcon_mask(falcon, 0x600, 0x00010007, (0 << 16) | (1 << 2) | 1); + + ret = nvkm_falcon_dma_wr(falcon, fw->fw.img, fw->fw.phys, fw->imem_base_img, + IMEM, fw->imem_base, fw->imem_size, true); + if (ret) + return ret; + + ret = nvkm_falcon_dma_wr(falcon, fw->fw.img, fw->fw.phys, fw->dmem_base_img, + DMEM, fw->dmem_base, fw->dmem_size, false); + if (ret) + return ret; + + return 0; +} + +const struct nvkm_falcon_fw_func +ga102_flcn_fw = { + .signature = ga100_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .load = ga102_flcn_fw_load, + .boot = ga102_flcn_fw_boot, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c index af53cbbc632c..6990890a760e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c @@ -171,8 +171,15 @@ gm200_flcn_disable(struct nvkm_falcon *falcon) nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000); nvkm_falcon_wr32(falcon, 0x014, 0xffffffff); - if (falcon->func->reset_pmc) + if (falcon->func->reset_pmc) { + if (falcon->func->reset_prep) { + ret = falcon->func->reset_prep(falcon); + if (ret) + return ret; + } + nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst); + } if (falcon->func->reset_eng) { ret = falcon->func->reset_eng(falcon); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c index c70beacb8d30..c774935f3077 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c @@ -66,6 +66,14 @@ gp102_flcn_emem_pio = { int gp102_flcn_reset_eng(struct nvkm_falcon *falcon) { + int ret; + + if (falcon->func->reset_prep) { + ret = falcon->func->reset_prep(falcon); + if (ret) + return ret; + } + nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001); udelay(10); nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c index 04ed77cb2eba..a7e0583401d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c @@ -38,6 +38,24 @@ nvfw_hs_header(struct nvkm_subdev *subdev, const void *data) return hdr; } +const struct nvfw_hs_header_v2 * +nvfw_hs_header_v2(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_hs_header_v2 *hdr = data; + + nvkm_debug(subdev, "hsHeader:\n"); + nvkm_debug(subdev, "\tsigProdOffset : 0x%x\n", hdr->sig_prod_offset); + nvkm_debug(subdev, "\tsigProdSize : 0x%x\n", hdr->sig_prod_size); + nvkm_debug(subdev, "\tpatchLoc : 0x%x\n", hdr->patch_loc); + nvkm_debug(subdev, "\tpatchSig : 0x%x\n", hdr->patch_sig); + nvkm_debug(subdev, "\tmetadataOffset : 0x%x\n", hdr->meta_data_offset); + nvkm_debug(subdev, "\tmetadataSize : 0x%x\n", hdr->meta_data_size); + nvkm_debug(subdev, "\tnumSig : 0x%x\n", hdr->num_sig); + nvkm_debug(subdev, "\theaderOffset : 0x%x\n", hdr->header_offset); + nvkm_debug(subdev, "\theaderSize : 0x%x\n", hdr->header_size); + return hdr; +} + const struct nvfw_hs_load_header * nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data) { @@ -60,3 +78,24 @@ nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data) return hdr; } + +const struct nvfw_hs_load_header_v2 * +nvfw_hs_load_header_v2(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_hs_load_header_v2 *hdr = data; + int i; + + nvkm_debug(subdev, "hsLoadHeader:\n"); + nvkm_debug(subdev, "\tosCodeOffset : 0x%x\n", hdr->os_code_offset); + nvkm_debug(subdev, "\tosCodeSize : 0x%x\n", hdr->os_code_size); + nvkm_debug(subdev, "\tosDataOffset : 0x%x\n", hdr->os_data_offset); + nvkm_debug(subdev, "\tosDataSize : 0x%x\n", hdr->os_data_size); + nvkm_debug(subdev, "\tnumApps : 0x%x\n", hdr->num_apps); + for (i = 0; i < hdr->num_apps; i++) { + nvkm_debug(subdev, + "\tApp[%d] : offset 0x%x size 0x%x\n", i, + hdr->app[i].offset, hdr->app[i].size); + } + + return hdr; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c index 52435c0a485c..8b7c8ea5e8a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c @@ -22,6 +22,30 @@ #include "gf100.h" #include "ram.h" +#include + +static int +ga102_fb_vpr_scrub(struct nvkm_fb *fb) +{ + struct nvkm_falcon_fw fw = {}; + int ret; + + ret = nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", &fb->subdev, "nvdec/scrubber", + 0, &fb->subdev.device->nvdec[0]->falcon, &fw); + if (ret) + return ret; + + ret = nvkm_falcon_fw_boot(&fw, &fb->subdev, true, NULL, NULL, 0, 0); + nvkm_falcon_fw_dtor(&fw); + return ret; +} + +static bool +ga102_fb_vpr_scrub_required(struct nvkm_fb *fb) +{ + return (nvkm_rd32(fb->subdev.device, 0x1fa80c) & 0x00000010) != 0; +} + static const struct nvkm_fb_func ga102_fb = { .dtor = gf100_fb_dtor, @@ -32,6 +56,8 @@ ga102_fb = { .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .ram_new = ga102_ram_new, .default_bigpage = 16, + .vpr.scrub_required = ga102_fb_vpr_scrub_required, + .vpr.scrub = ga102_fb_vpr_scrub, }; int @@ -39,3 +65,9 @@ ga102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, s { return gp102_fb_new_(&ga102_fb, device, type, inst, pfb); } + +MODULE_FIRMWARE("nvidia/ga102/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/ga103/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/ga104/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/ga106/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/ga107/nvdec/scrubber.bin"); -- cgit v1.2.3 From 4b569ded09fdadb0c14f797c8dae4e8bc4bbad9f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:33 +1000 Subject: drm/nouveau/acr/ga102: initial support v2. fixup for ga103 early merge Signed-off-by: Ben Skeggs Signed-off-by: Gourav Samaiya --- drivers/gpu/drm/nouveau/include/nvfw/acr.h | 85 ++++++ drivers/gpu/drm/nouveau/include/nvfw/ls.h | 51 ++++ drivers/gpu/drm/nouveau/include/nvfw/sec2.h | 40 +++ drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 1 + .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 17 ++ drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 15 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 6 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c | 197 +++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 4 + drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c | 26 +- drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c | 12 + drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c | 41 +++ drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c | 72 +++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild | 2 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c | 49 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c | 326 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c | 4 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c | 4 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c | 70 +++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h | 13 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c | 59 ++++ 28 files changed, 1091 insertions(+), 14 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/acr.h b/drivers/gpu/drm/nouveau/include/nvfw/acr.h index e65d6a8db104..6f19560bc54b 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/acr.h @@ -39,6 +39,23 @@ struct wpr_header_v1 { void wpr_header_v1_dump(struct nvkm_subdev *, const struct wpr_header_v1 *); +struct wpr_generic_header { +#define WPR_GENERIC_HEADER_ID_LSF_UCODE_DESC 1 +#define WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER 2 +#define WPR_GENERIC_HEADER_ID_LSF_SHARED_SUB_WPR 3 +#define WPR_GENERIC_HEADER_ID_LSF_LSB_HEADER 4 + u16 identifier; + u16 version; + u32 size; +}; + +struct wpr_header_v2 { + struct wpr_generic_header hdr; + struct wpr_header_v1 wpr; +}; + +void wpr_header_v2_dump(struct nvkm_subdev *, const struct wpr_header_v2 *); + struct lsf_signature { u8 prd_keys[2][16]; u8 dbg_keys[2][16]; @@ -89,6 +106,74 @@ struct lsb_header_v1 { void lsb_header_v1_dump(struct nvkm_subdev *, struct lsb_header_v1 *); +struct lsb_header_v2 { + struct wpr_generic_header hdr; + struct lsf_signature_v2 { + struct wpr_generic_header hdr; + u32 falcon_id; + u8 prd_present; + u8 dbg_present; + u16 reserved; + u32 sig_size; + u8 prod_sig[2][384 + 128]; + u8 debug_sig[2][384 + 128]; + u16 sig_algo_ver; + u16 sig_algo; + u16 hash_algo_ver; + u16 hash_algo; + u32 sig_algo_padding_type; + u8 depmap[11 * 2 * 4]; + u32 depmap_count; + u8 supports_versioning; + u8 pad[3]; + u32 ls_ucode_version; + u32 ls_ucode_id; + u32 ucode_ls_encrypted; + u32 ls_eng_algo_type; + u32 ls_eng_algo_ver; + u8 ls_enc_iv[16]; + u8 rsvd[36]; + } signature; + u32 ucode_off; + u32 ucode_size; + u32 data_size; + u32 bl_code_size; + u32 bl_imem_off; + u32 bl_data_off; + u32 bl_data_size; + u32 rsvd0; + u32 app_code_off; + u32 app_code_size; + u32 app_data_off; + u32 app_data_size; + u32 app_imem_offset; + u32 app_dmem_offset; + u32 flags; + u32 monitor_code_offset; + u32 monitor_data_offset; + u32 manifest_offset; + struct hs_fmc_params { + u8 hs_fmc; + u8 padding[3]; + u16 pkc_algo; + u16 pkc_algo_version; + u32 engid_mask; + u32 ucode_id; + u32 fuse_ver; + u8 pkc_signature[384 + 128]; + u8 pkc_key[2048]; + u8 rsvd[4]; + } hs_fmc_params; + struct hs_ovl_sig_blob_params { + u8 hs_ovl_sig_blob_present; + u32 hs_ovl_sig_blob_offset; + u32 hs_ovl_sig_blob_size; + } hs_ovl_sig_blob_params; + u8 rsvd[20]; +}; + +void lsb_header_v2_dump(struct nvkm_subdev *, struct lsb_header_v2 *); + struct flcn_acr_desc { union { u8 reserved_dmem[0x200]; diff --git a/drivers/gpu/drm/nouveau/include/nvfw/ls.h b/drivers/gpu/drm/nouveau/include/nvfw/ls.h index f63692a2a16c..d531121bfa35 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/ls.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/ls.h @@ -50,4 +50,55 @@ struct nvfw_ls_desc_v1 { const struct nvfw_ls_desc_v1 * nvfw_ls_desc_v1(struct nvkm_subdev *, const void *); + +struct nvfw_ls_desc_v2 { + u32 descriptor_size; + u32 image_size; + u32 tools_version; + u32 app_version; + char date[64]; + u32 secure_bootloader; + u32 bootloader_start_offset; + u32 bootloader_size; + u32 bootloader_imem_offset; + u32 bootloader_entry_point; + u32 app_start_offset; + u32 app_size; + u32 app_imem_offset; + u32 app_imem_entry; + u32 app_dmem_offset; + u32 app_resident_code_offset; + u32 app_resident_code_size; + u32 app_resident_data_offset; + u32 app_resident_data_size; + u32 nb_imem_overlays; + u32 nb_dmem_overlays; + struct { + u32 start; + u32 size; + } load_ovl[64]; +}; + +const struct nvfw_ls_desc_v2 *nvfw_ls_desc_v2(struct nvkm_subdev *, const void *); + +struct nvfw_ls_hsbl_bin_hdr { + u32 bin_magic; + u32 bin_ver; + u32 bin_size; + u32 header_offset; +}; + +const struct nvfw_ls_hsbl_bin_hdr *nvfw_ls_hsbl_bin_hdr(struct nvkm_subdev *, const void *); + +struct nvfw_ls_hsbl_hdr { + u32 sig_prod_offset; + u32 sig_prod_size; + u32 patch_loc; + u32 patch_sig; + u32 meta_data_offset; + u32 meta_data_size; + u32 num_sig; +}; + +const struct nvfw_ls_hsbl_hdr *nvfw_ls_hsbl_hdr(struct nvkm_subdev *, const void *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h index 07d7094d8ed8..b3331d679c4e 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h @@ -34,6 +34,29 @@ struct nv_sec2_init_msg { u16 sw_managed_area_size; }; +struct nv_sec2_init_msg_v1 { + struct nvfw_falcon_msg hdr; +#define NV_SEC2_INIT_MSG_INIT 0x00 + u8 msg_type; + + u8 num_queues; + u16 os_debug_entry_point; + + struct { + u32 offset; + u16 size; + u8 index; +#define NV_SEC2_INIT_MSG_QUEUE_ID_CMDQ 0x00 +#define NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ 0x01 + u8 id; + } queue_info[2]; + + u32 sw_managed_area_offset; + u16 sw_managed_area_size; + + u32 unkn[8]; +}; + struct nv_sec2_acr_cmd { struct nvfw_falcon_cmd hdr; #define NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON 0x00 @@ -62,4 +85,21 @@ struct nv_sec2_acr_bootstrap_falcon_msg { #define NV_SEC2_UNIT_V2_INIT 0x01 #define NV_SEC2_UNIT_V2_UNLOAD 0x05 #define NV_SEC2_UNIT_V2_ACR 0x07 + +struct nv_sec2_acr_bootstrap_falcon_cmd_v1 { + struct nv_sec2_acr_cmd cmd; +#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000 +#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO 0x00000001 + u32 flags; + u32 falcon_id; + u32 unkn08; + u32 unkn0c; +}; + +struct nv_sec2_acr_bootstrap_falcon_msg_v1 { + struct nv_sec2_acr_msg msg; + u32 error_code; + u32 falcon_id; + u32 unkn08; +}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 45d70aa4fd6d..b857cf142c4a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -61,6 +61,7 @@ void gm200_flcn_tracepc(struct nvkm_falcon *); int gp102_flcn_reset_eng(struct nvkm_falcon *); extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio; +int ga102_flcn_select(struct nvkm_falcon *); int ga102_flcn_reset_prep(struct nvkm_falcon *); int ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *); extern const struct nvkm_falcon_func_dma ga102_flcn_dma; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index dacbd92edcd5..cd86d9198e4a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -60,6 +60,7 @@ int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *, struct nvkm_falcon_func { int (*disable)(struct nvkm_falcon *); int (*enable)(struct nvkm_falcon *); + int (*select)(struct nvkm_falcon *); u32 addr2; bool reset_pmc; int (*reset_eng)(struct nvkm_falcon *); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index a41b86426f80..8d48fb20fa54 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -23,4 +23,5 @@ struct nvkm_sec2 { int gp102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **); int gp108_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **); int tu102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **); +int ga102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 12c0b8395262..4c1f81ee1cef 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -67,6 +67,7 @@ int gp108_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct int gp10b_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); int gv100_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); int tu102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); +int ga102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); struct nvkm_acr_lsfw { const struct nvkm_acr_lsf_func *func; @@ -79,6 +80,7 @@ struct nvkm_acr_lsfw { const struct firmware *sig; + bool secure_bootloader; u32 bootloader_size; u32 bootloader_imem_offset; @@ -89,10 +91,19 @@ struct nvkm_acr_lsfw { u32 app_resident_code_size; u32 app_resident_data_offset; u32 app_resident_data_size; + u32 app_imem_offset; + u32 app_dmem_offset; u32 ucode_size; u32 data_size; + u32 fuse_ver; + u32 engine_id; + u32 ucode_id; + u32 sig_size; + u32 sig_nr; + u8 *sigs; + struct { u32 lsb; u32 img; @@ -123,6 +134,12 @@ int nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *, struct nvkm_falcon *, enum nvkm_acr_lsf_id, const char *path, int ver, const struct nvkm_acr_lsf_func *); + +int +nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *, struct nvkm_falcon *, + enum nvkm_acr_lsf_id, const char *path, + int ver, const struct nvkm_acr_lsf_func *); + int nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *, struct nvkm_falcon *, enum nvkm_acr_lsf_id, const char *path, diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h index ccf886ec1f84..72619d7df73e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h @@ -12,4 +12,5 @@ struct nvkm_gsp { }; int gv100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **); +int ga102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 8162efcf2dd6..666300dc0bf0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2596,12 +2596,14 @@ nv170_chipset = { static const struct nvkm_device_chip nv172_chipset = { .name = "GA102", + .acr = { 0x00000001, ga102_acr_new }, .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, + .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .mc = { 0x00000001, ga100_mc_new }, @@ -2616,17 +2618,20 @@ nv172_chipset = { .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, + .sec2 = { 0x00000001, ga102_sec2_new }, }; static const struct nvkm_device_chip nv173_chipset = { .name = "GA103", + .acr = { 0x00000001, ga102_acr_new }, .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, + .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .mc = { 0x00000001, ga100_mc_new }, @@ -2641,17 +2646,20 @@ nv173_chipset = { .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, + .sec2 = { 0x00000001, ga102_sec2_new }, }; static const struct nvkm_device_chip nv174_chipset = { .name = "GA104", + .acr = { 0x00000001, ga102_acr_new }, .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, + .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .mc = { 0x00000001, ga100_mc_new }, @@ -2666,17 +2674,20 @@ nv174_chipset = { .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, + .sec2 = { 0x00000001, ga102_sec2_new }, }; static const struct nvkm_device_chip nv176_chipset = { .name = "GA106", + .acr = { 0x00000001, ga102_acr_new }, .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, + .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .mc = { 0x00000001, ga100_mc_new }, @@ -2691,17 +2702,20 @@ nv176_chipset = { .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, + .sec2 = { 0x00000001, ga102_sec2_new }, }; static const struct nvkm_device_chip nv177_chipset = { .name = "GA107", + .acr = { 0x00000001, ga102_acr_new }, .bar = { 0x00000001, tu102_bar_new }, .bios = { 0x00000001, nvkm_bios_new }, .devinit = { 0x00000001, ga100_devinit_new }, .fault = { 0x00000001, tu102_fault_new }, .fb = { 0x00000001, ga102_fb_new }, .gpio = { 0x00000001, ga102_gpio_new }, + .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, .mc = { 0x00000001, ga100_mc_new }, @@ -2716,6 +2730,7 @@ nv177_chipset = { .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, + .sec2 = { 0x00000001, ga102_sec2_new }, }; struct nvkm_subdev * diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild index 63cd2be3de08..19feadb1f67b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild @@ -3,3 +3,4 @@ nvkm-y += nvkm/engine/sec2/base.o nvkm-y += nvkm/engine/sec2/gp102.o nvkm-y += nvkm/engine/sec2/gp108.o nvkm-y += nvkm/engine/sec2/tu102.o +nvkm-y += nvkm/engine/sec2/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index b1e5f543c99d..f2c60da5d1e8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -100,6 +100,12 @@ nvkm_sec2_oneinit(struct nvkm_engine *engine) struct nvkm_intr *intr = &sec2->engine.subdev.device->mc->intr; enum nvkm_intr_type type = NVKM_INTR_SUBDEV; + if (sec2->func->intr_vector) { + intr = sec2->func->intr_vector(sec2, &type); + if (IS_ERR(intr)) + return PTR_ERR(intr); + } + return nvkm_inth_add(intr, type, NVKM_INTR_PRIO_NORMAL, subdev, sec2->func->intr, &subdev->inth); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c new file mode 100644 index 000000000000..945abb8156d7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c @@ -0,0 +1,197 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" +#include +#include + +#include +#include + +static int +ga102_sec2_initmsg(struct nvkm_sec2 *sec2) +{ + struct nv_sec2_init_msg_v1 msg; + int ret, i; + + ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg)); + if (ret) + return ret; + + if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT || + msg.msg_type != NV_SEC2_INIT_MSG_INIT) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) { + if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) { + nvkm_falcon_msgq_init(sec2->msgq, msg.queue_info[i].index, + msg.queue_info[i].offset, + msg.queue_info[i].size); + } else { + nvkm_falcon_cmdq_init(sec2->cmdq, msg.queue_info[i].index, + msg.queue_info[i].offset, + msg.queue_info[i].size); + } + } + + return 0; +} + +static struct nvkm_intr * +ga102_sec2_intr_vector(struct nvkm_sec2 *sec2, enum nvkm_intr_type *pvector) +{ + struct nvkm_device *device = sec2->engine.subdev.device; + struct nvkm_falcon *falcon = &sec2->falcon; + int ret; + + ret = ga102_flcn_select(falcon); + if (ret) + return ERR_PTR(ret); + + *pvector = nvkm_rd32(device, 0x8403e0) & 0x000000ff; + return &device->vfn->intr; +} + +static int +ga102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nvfw_falcon_msg *hdr) +{ + struct nv_sec2_acr_bootstrap_falcon_msg_v1 *msg = + container_of(hdr, typeof(*msg), msg.hdr); + struct nvkm_subdev *subdev = priv; + const char *name = nvkm_acr_lsf_id(msg->falcon_id); + + if (msg->error_code) { + nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for falcon %d [%s]: %08x %08x\n", + msg->falcon_id, name, msg->error_code, msg->unkn08); + return -EINVAL; + } + + nvkm_debug(subdev, "%s booted\n", name); + return 0; +} + +static int +ga102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, enum nvkm_acr_lsf_id id) +{ + struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon); + struct nv_sec2_acr_bootstrap_falcon_cmd_v1 cmd = { + .cmd.hdr.unit_id = sec2->func->unit_acr, + .cmd.hdr.size = sizeof(cmd), + .cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON, + .flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES, + .falcon_id = id, + }; + + return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr, + ga102_sec2_acr_bootstrap_falcon_callback, + &sec2->engine.subdev, + msecs_to_jiffies(1000)); +} + +static const struct nvkm_acr_lsf_func +ga102_sec2_acr_0 = { + .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), + .bld_write = gp102_sec2_acr_bld_write_1, + .bld_patch = gp102_sec2_acr_bld_patch_1, + .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | + BIT_ULL(NVKM_ACR_LSF_GPCCS) | + BIT_ULL(NVKM_ACR_LSF_SEC2), + .bootstrap_falcon = ga102_sec2_acr_bootstrap_falcon, +}; + +static const struct nvkm_falcon_func +ga102_sec2_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .select = ga102_flcn_select, + .addr2 = 0x1000, + .reset_pmc = true, + .reset_eng = gp102_flcn_reset_eng, + .reset_prep = ga102_flcn_reset_prep, + .reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing, + .imem_dma = &ga102_flcn_dma, + .dmem_pio = &gm200_flcn_dmem_pio, + .dmem_dma = &ga102_flcn_dma, + .emem_addr = 0x01000000, + .emem_pio = &gp102_flcn_emem_pio, + .start = nvkm_falcon_v1_start, + .cmdq = { 0xc00, 0xc04, 8 }, + .msgq = { 0xc80, 0xc84, 8 }, +}; + +static const struct nvkm_sec2_func +ga102_sec2 = { + .flcn = &ga102_sec2_flcn, + .intr_vector = ga102_sec2_intr_vector, + .intr = gp102_sec2_intr, + .initmsg = ga102_sec2_initmsg, + .unit_acr = NV_SEC2_UNIT_V2_ACR, + .unit_unload = NV_SEC2_UNIT_V2_UNLOAD, +}; + +MODULE_FIRMWARE("nvidia/ga102/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga102/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga102/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga102/sec2/hs_bl_sig.bin"); + +MODULE_FIRMWARE("nvidia/ga103/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga103/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga103/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga103/sec2/hs_bl_sig.bin"); + +MODULE_FIRMWARE("nvidia/ga104/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga104/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga104/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga104/sec2/hs_bl_sig.bin"); + +MODULE_FIRMWARE("nvidia/ga106/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga106/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga106/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga106/sec2/hs_bl_sig.bin"); + +MODULE_FIRMWARE("nvidia/ga107/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga107/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga107/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga107/sec2/hs_bl_sig.bin"); + +static int +ga102_sec2_load(struct nvkm_sec2 *sec2, int ver, + const struct nvkm_sec2_fwif *fwif) +{ + return nvkm_acr_lsfw_load_sig_image_desc_v2(&sec2->engine.subdev, &sec2->falcon, + NVKM_ACR_LSF_SEC2, "sec2/", ver, fwif->acr); +} + +static const struct nvkm_sec2_fwif +ga102_sec2_fwif[] = { + { 0, ga102_sec2_load, &ga102_sec2, &ga102_sec2_acr_0 }, + { -1, gp102_sec2_nofw, &ga102_sec2 } +}; + +int +ga102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_sec2 **psec2) +{ + /* TOP info wasn't updated on Turing to reflect the PRI + * address change for some reason. We override it here. + */ + return nvkm_sec2_new_(ga102_sec2_fwif, device, type, inst, 0x840000, psec2); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index b1e74bc49d72..c64013d10500 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -237,7 +237,7 @@ MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin"); MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin"); -static void +void gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust) { struct flcn_bl_dmem_desc_v2 hdr; @@ -248,7 +248,7 @@ gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust) flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr); } -static void +void gp102_sec2_acr_bld_write_1(struct nvkm_acr *acr, u32 bld, struct nvkm_acr_lsfw *lsfw) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index 4997b8903a78..172d2705c199 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -2,11 +2,13 @@ #ifndef __NVKM_SEC2_PRIV_H__ #define __NVKM_SEC2_PRIV_H__ #include +struct nvkm_acr_lsfw; struct nvkm_sec2_func { const struct nvkm_falcon_func *flcn; u8 unit_unload; u8 unit_acr; + struct nvkm_intr *(*intr_vector)(struct nvkm_sec2 *, enum nvkm_intr_type *); irqreturn_t (*intr)(struct nvkm_inth *); int (*initmsg)(struct nvkm_sec2 *); }; @@ -25,6 +27,8 @@ int gp102_sec2_nofw(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *); int gp102_sec2_load(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *); extern const struct nvkm_sec2_func gp102_sec2; extern const struct nvkm_acr_lsf_func gp102_sec2_acr_1; +void gp102_sec2_acr_bld_write_1(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); +void gp102_sec2_acr_bld_patch_1(struct nvkm_acr *, u32, s64); int nvkm_sec2_new_(const struct nvkm_sec2_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int, u32 addr, struct nvkm_sec2 **); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c b/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c index 38306f9920b4..0ff450fe3590 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c @@ -77,14 +77,28 @@ ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon) int ga102_flcn_reset_prep(struct nvkm_falcon *falcon) { - const u32 addr2 = (falcon->owner->type != NVKM_ENGINE_NVDEC) ? 0x530 : 0x930; + nvkm_falcon_rd32(falcon, 0x0f4); - if (nvkm_msec(falcon->owner->device, 10, - if ((nvkm_falcon_rd32(falcon, falcon->addr2 + 0x1ec) & 0x00000003) == 0x00000001 && - (nvkm_falcon_rd32(falcon, addr2) & 0x00000008) == 0x00000008) + nvkm_usec(falcon->owner->device, 150, + if (nvkm_falcon_rd32(falcon, 0x0f4) & 0x80000000) break; - ) < 0) - return -ETIMEDOUT; + _warn = false; + ); + + return 0; +} + +int +ga102_flcn_select(struct nvkm_falcon *falcon) +{ + if ((nvkm_falcon_rd32(falcon, falcon->addr2 + 0x668) & 0x00000010) != 0x00000000) { + nvkm_falcon_wr32(falcon, falcon->addr2 + 0x668, 0x00000000); + if (nvkm_msec(falcon->owner->device, 10, + if (nvkm_falcon_rd32(falcon, falcon->addr2 + 0x668) & 0x00000001) + break; + ) < 0) + return -ETIMEDOUT; + } return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c index 6990890a760e..393ade9f7e6c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c @@ -151,6 +151,12 @@ gm200_flcn_enable(struct nvkm_falcon *falcon) return ret; } + if (falcon->func->select) { + ret = falcon->func->select(falcon); + if (ret) + return ret; + } + if (falcon->func->reset_pmc) nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst); @@ -168,6 +174,12 @@ gm200_flcn_disable(struct nvkm_falcon *falcon) struct nvkm_device *device = falcon->owner->device; int ret; + if (falcon->func->select) { + ret = falcon->func->select(falcon); + if (ret) + return ret; + } + nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000); nvkm_falcon_wr32(falcon, 0x014, 0xffffffff); diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c index bef790ad8f2f..83a9c48bc58c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c @@ -45,6 +45,47 @@ wpr_header_v1_dump(struct nvkm_subdev *subdev, const struct wpr_header_v1 *hdr) nvkm_debug(subdev, "\tstatus : %d\n", hdr->status); } +void +wpr_generic_header_dump(struct nvkm_subdev *subdev, const struct wpr_generic_header *hdr) +{ + nvkm_debug(subdev, "wprGenericHeader\n"); + nvkm_debug(subdev, "\tidentifier : %04x\n", hdr->identifier); + nvkm_debug(subdev, "\tversion : %04x\n", hdr->version); + nvkm_debug(subdev, "\tsize : %08x\n", hdr->size); +} + +void +wpr_header_v2_dump(struct nvkm_subdev *subdev, const struct wpr_header_v2 *hdr) +{ + wpr_generic_header_dump(subdev, &hdr->hdr); + wpr_header_v1_dump(subdev, &hdr->wpr); +} + +void +lsb_header_v2_dump(struct nvkm_subdev *subdev, struct lsb_header_v2 *hdr) +{ + wpr_generic_header_dump(subdev, &hdr->hdr); + nvkm_debug(subdev, "lsbHeader\n"); + nvkm_debug(subdev, "\tucodeOff : 0x%x\n", hdr->ucode_off); + nvkm_debug(subdev, "\tucodeSize : 0x%x\n", hdr->ucode_size); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); + nvkm_debug(subdev, "\tblCodeSize : 0x%x\n", hdr->bl_code_size); + nvkm_debug(subdev, "\tblImemOff : 0x%x\n", hdr->bl_imem_off); + nvkm_debug(subdev, "\tblDataOff : 0x%x\n", hdr->bl_data_off); + nvkm_debug(subdev, "\tblDataSize : 0x%x\n", hdr->bl_data_size); + nvkm_debug(subdev, "\treserved0 : %08x\n", hdr->rsvd0); + nvkm_debug(subdev, "\tappCodeOff : 0x%x\n", hdr->app_code_off); + nvkm_debug(subdev, "\tappCodeSize : 0x%x\n", hdr->app_code_size); + nvkm_debug(subdev, "\tappDataOff : 0x%x\n", hdr->app_data_off); + nvkm_debug(subdev, "\tappDataSize : 0x%x\n", hdr->app_data_size); + nvkm_debug(subdev, "\tappImemOffset : 0x%x\n", hdr->app_imem_offset); + nvkm_debug(subdev, "\tappDmemOffset : 0x%x\n", hdr->app_dmem_offset); + nvkm_debug(subdev, "\tflags : 0x%x\n", hdr->flags); + nvkm_debug(subdev, "\tmonitorCodeOff: 0x%x\n", hdr->monitor_code_offset); + nvkm_debug(subdev, "\tmonitorDataOff: 0x%x\n", hdr->monitor_data_offset); + nvkm_debug(subdev, "\tmanifestOffset: 0x%x\n", hdr->manifest_offset); +} + static void lsb_header_tail_dump(struct nvkm_subdev *subdev, struct lsb_header_tail *hdr) { diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c index b847f281ce97..45c3a6c5e088 100644 --- a/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c @@ -106,3 +106,75 @@ nvfw_ls_desc_v1(struct nvkm_subdev *subdev, const void *data) return hdr; } + +const struct nvfw_ls_desc_v2 * +nvfw_ls_desc_v2(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_ls_desc_v2 *hdr = data; + char *date; + int i; + + nvkm_debug(subdev, "lsUcodeImgDesc:\n"); + nvkm_debug(subdev, "\tdescriptorSize : %d\n", hdr->descriptor_size); + nvkm_debug(subdev, "\timageSize : %d\n", hdr->image_size); + nvkm_debug(subdev, "\ttoolsVersion : 0x%x\n", hdr->tools_version); + nvkm_debug(subdev, "\tappVersion : 0x%x\n", hdr->app_version); + + date = kstrndup(hdr->date, sizeof(hdr->date), GFP_KERNEL); + nvkm_debug(subdev, "\tdate : %s\n", date); + kfree(date); + + nvkm_debug(subdev, "\tsecureBootloader : 0x%x\n", hdr->secure_bootloader); + nvkm_debug(subdev, "\tbootloaderStartOffset: 0x%x\n", hdr->bootloader_start_offset); + nvkm_debug(subdev, "\tbootloaderSize : 0x%x\n", hdr->bootloader_size); + nvkm_debug(subdev, "\tbootloaderImemOffset : 0x%x\n", hdr->bootloader_imem_offset); + nvkm_debug(subdev, "\tbootloaderEntryPoint : 0x%x\n", hdr->bootloader_entry_point); + + nvkm_debug(subdev, "\tappStartOffset : 0x%x\n", hdr->app_start_offset); + nvkm_debug(subdev, "\tappSize : 0x%x\n", hdr->app_size); + nvkm_debug(subdev, "\tappImemOffset : 0x%x\n", hdr->app_imem_offset); + nvkm_debug(subdev, "\tappImemEntry : 0x%x\n", hdr->app_imem_entry); + nvkm_debug(subdev, "\tappDmemOffset : 0x%x\n", hdr->app_dmem_offset); + nvkm_debug(subdev, "\tappResidentCodeOffset: 0x%x\n", hdr->app_resident_code_offset); + nvkm_debug(subdev, "\tappResidentCodeSize : 0x%x\n", hdr->app_resident_code_size); + nvkm_debug(subdev, "\tappResidentDataOffset: 0x%x\n", hdr->app_resident_data_offset); + nvkm_debug(subdev, "\tappResidentDataSize : 0x%x\n", hdr->app_resident_data_size); + + nvkm_debug(subdev, "\tnbImemOverlays : %d\n", hdr->nb_imem_overlays); + nvkm_debug(subdev, "\tnbDmemOverlays : %d\n", hdr->nb_dmem_overlays); + for (i = 0; i < ARRAY_SIZE(hdr->load_ovl); i++) { + nvkm_debug(subdev, "\tloadOvl[%d] : 0x%x %d\n", i, + hdr->load_ovl[i].start, hdr->load_ovl[i].size); + } + + return hdr; +} + +const struct nvfw_ls_hsbl_bin_hdr * +nvfw_ls_hsbl_bin_hdr(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_ls_hsbl_bin_hdr *hdr = data; + + nvkm_debug(subdev, "lsHsblBinHdr:\n"); + nvkm_debug(subdev, "\tbinMagic : 0x%08x\n", hdr->bin_magic); + nvkm_debug(subdev, "\tbinVer : %d\n", hdr->bin_ver); + nvkm_debug(subdev, "\tbinSize : %d\n", hdr->bin_size); + nvkm_debug(subdev, "\theaderOffset : 0x%x\n", hdr->header_offset); + return hdr; +} + +const struct nvfw_ls_hsbl_hdr * +nvfw_ls_hsbl_hdr(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_ls_hsbl_hdr *hdr = data; + + nvkm_debug(subdev, "lsHsblHdr:\n"); + nvkm_debug(subdev, "\tsigProdOffset : 0x%x\n", hdr->sig_prod_offset); + nvkm_debug(subdev, "\tsigProdSize : 0x%x\n", hdr->sig_prod_size); + nvkm_debug(subdev, "\tpatchLoc : 0x%x\n", hdr->patch_loc); + nvkm_debug(subdev, "\tpatchSig : 0x%x\n", hdr->patch_sig); + nvkm_debug(subdev, "\tmetadataOffset : 0x%x\n", hdr->meta_data_offset); + nvkm_debug(subdev, "\tmetadataSize : 0x%x\n", hdr->meta_data_size); + nvkm_debug(subdev, "\tnumSig : 0x%x\n", hdr->num_sig); + return hdr; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild index ce6ece75f07e..5731f35b11e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild @@ -8,3 +8,5 @@ nvkm-y += nvkm/subdev/acr/gp108.o nvkm-y += nvkm/subdev/acr/gv100.o nvkm-y += nvkm/subdev/acr/gp10b.o nvkm-y += nvkm/subdev/acr/tu102.o +nvkm-y += nvkm/subdev/acr/ga100.o +nvkm-y += nvkm/subdev/acr/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c new file mode 100644 index 000000000000..e3370c1551c0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c @@ -0,0 +1,49 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +void +ga100_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit) +{ + struct nvkm_device *device = acr->subdev.device; + + *start = (u64)(nvkm_rd32(device, 0x1fa81c) & 0xffffff00) << 8; + *limit = (u64)(nvkm_rd32(device, 0x1fa820) & 0xffffff00) << 8; + *limit = *limit + 0x20000; +} + +int +ga100_acr_hsfw_ctor(struct nvkm_acr *acr, const char *bl, const char *fw, + const char *name, int ver, const struct nvkm_acr_hsf_fwif *fwif) +{ + struct nvkm_acr_hsfw *hsfw; + + if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL))) + return -ENOMEM; + + hsfw->falcon_id = fwif->falcon_id; + hsfw->boot_mbox0 = fwif->boot_mbox0; + hsfw->intr_clear = fwif->intr_clear; + list_add_tail(&hsfw->head, &acr->hsfw); + + return nvkm_falcon_fw_ctor_hs_v2(fwif->func, name, &acr->subdev, fw, ver, NULL, &hsfw->fw); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c new file mode 100644 index 000000000000..45dcf493e972 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c @@ -0,0 +1,326 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +#include + +static int +ga102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust) +{ + struct wpr_header_v2 hdr; + struct lsb_header_v2 *lsb; + struct nvkm_acr_lsfw *lsfw; + u32 offset = 0; + + lsb = kvmalloc(sizeof(*lsb), GFP_KERNEL); + if (!lsb) + return -ENOMEM; + + do { + nvkm_robj(acr->wpr, offset, &hdr, sizeof(hdr)); + wpr_header_v2_dump(&acr->subdev, &hdr); + + list_for_each_entry(lsfw, &acr->lsfw, head) { + if (lsfw->id != hdr.wpr.falcon_id) + continue; + + nvkm_robj(acr->wpr, hdr.wpr.lsb_offset, lsb, sizeof(*lsb)); + lsb_header_v2_dump(&acr->subdev, lsb); + + lsfw->func->bld_patch(acr, lsb->bl_data_off, adjust); + break; + } + + offset += sizeof(hdr); + } while (hdr.wpr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID); + + kvfree(lsb); + return 0; +} + +static int +ga102_acr_wpr_build_lsb(struct nvkm_acr *acr, struct nvkm_acr_lsfw *lsfw) +{ + struct lsb_header_v2 *hdr; + int ret = 0; + + if (WARN_ON(lsfw->sig->size != sizeof(hdr->signature))) + return -EINVAL; + + hdr = kvzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + hdr->hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_LSB_HEADER; + hdr->hdr.version = 2; + hdr->hdr.size = sizeof(*hdr); + + memcpy(&hdr->signature, lsfw->sig->data, lsfw->sig->size); + hdr->ucode_off = lsfw->offset.img; + hdr->ucode_size = lsfw->ucode_size; + hdr->data_size = lsfw->data_size; + hdr->bl_code_size = lsfw->bootloader_size; + hdr->bl_imem_off = lsfw->bootloader_imem_offset; + hdr->bl_data_off = lsfw->offset.bld; + hdr->bl_data_size = lsfw->bl_data_size; + hdr->app_code_off = lsfw->app_start_offset + lsfw->app_resident_code_offset; + hdr->app_code_size = ALIGN(lsfw->app_resident_code_size, 0x100); + hdr->app_data_off = lsfw->app_start_offset + lsfw->app_resident_data_offset; + hdr->app_data_size = ALIGN(lsfw->app_resident_data_size, 0x100); + hdr->app_imem_offset = lsfw->app_imem_offset; + hdr->app_dmem_offset = lsfw->app_dmem_offset; + hdr->flags = lsfw->func->flags; + hdr->monitor_code_offset = 0; + hdr->monitor_data_offset = 0; + hdr->manifest_offset = 0; + + if (lsfw->secure_bootloader) { + struct nvkm_falcon_fw fw = { + .fw.img = hdr->hs_fmc_params.pkc_signature, + .fw.name = "LSFW", + .func = &(const struct nvkm_falcon_fw_func) { + .signature = ga100_flcn_fw_signature, + }, + .sig_size = lsfw->sig_size, + .sig_nr = lsfw->sig_nr, + .sigs = lsfw->sigs, + .fuse_ver = lsfw->fuse_ver, + .engine_id = lsfw->engine_id, + .ucode_id = lsfw->ucode_id, + .falcon = lsfw->falcon, + + }; + + ret = nvkm_falcon_get(fw.falcon, &acr->subdev); + if (ret == 0) { + hdr->hs_fmc_params.hs_fmc = 1; + hdr->hs_fmc_params.pkc_algo = 0; + hdr->hs_fmc_params.pkc_algo_version = 1; + hdr->hs_fmc_params.engid_mask = lsfw->engine_id; + hdr->hs_fmc_params.ucode_id = lsfw->ucode_id; + hdr->hs_fmc_params.fuse_ver = lsfw->fuse_ver; + ret = nvkm_falcon_fw_patch(&fw); + nvkm_falcon_put(fw.falcon, &acr->subdev); + } + } + + nvkm_wobj(acr->wpr, lsfw->offset.lsb, hdr, sizeof(*hdr)); + kvfree(hdr); + return ret; +} + +static int +ga102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos) +{ + struct nvkm_acr_lsfw *lsfw; + struct wpr_header_v2 hdr; + u32 offset = 0; + int ret; + + /*XXX: shared sub-WPR headers, fill terminator for now. */ + nvkm_wo32(acr->wpr, 0x300, (2 << 16) | WPR_GENERIC_HEADER_ID_LSF_SHARED_SUB_WPR); + nvkm_wo32(acr->wpr, 0x304, 0x14); + nvkm_wo32(acr->wpr, 0x308, 0xffffffff); + nvkm_wo32(acr->wpr, 0x30c, 0); + nvkm_wo32(acr->wpr, 0x310, 0); + + /* Fill per-LSF structures. */ + list_for_each_entry(lsfw, &acr->lsfw, head) { + struct lsf_signature_v2 *sig = (void *)lsfw->sig->data; + + hdr.hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER; + hdr.hdr.version = 2; + hdr.hdr.size = sizeof(hdr); + hdr.wpr.falcon_id = lsfw->id; + hdr.wpr.lsb_offset = lsfw->offset.lsb; + hdr.wpr.bootstrap_owner = NVKM_ACR_LSF_GSPLITE; + hdr.wpr.lazy_bootstrap = 1; + hdr.wpr.bin_version = sig->ls_ucode_version; + hdr.wpr.status = WPR_HEADER_V1_STATUS_COPY; + + /* Write WPR header. */ + nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr)); + offset += sizeof(hdr); + + /* Write LSB header. */ + ret = ga102_acr_wpr_build_lsb(acr, lsfw); + if (ret) + return ret; + + /* Write ucode image. */ + nvkm_wobj(acr->wpr, lsfw->offset.img, + lsfw->img.data, + lsfw->img.size); + + /* Write bootloader data. */ + lsfw->func->bld_write(acr, lsfw->offset.bld, lsfw); + } + + /* Finalise WPR. */ + hdr.hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER; + hdr.hdr.version = 2; + hdr.hdr.size = sizeof(hdr); + hdr.wpr.falcon_id = WPR_HEADER_V1_FALCON_ID_INVALID; + nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr)); + return 0; +} + +static u32 +ga102_acr_wpr_layout(struct nvkm_acr *acr) +{ + struct nvkm_acr_lsfw *lsfw; + u32 wpr = 0; + + wpr += 21 /* MAX_LSF */ * sizeof(struct wpr_header_v2); + wpr = ALIGN(wpr, 256); + + wpr += 0x100; /* Shared sub-WPR headers. */ + + list_for_each_entry(lsfw, &acr->lsfw, head) { + wpr = ALIGN(wpr, 256); + lsfw->offset.lsb = wpr; + wpr += sizeof(struct lsb_header_v2); + + wpr = ALIGN(wpr, 4096); + lsfw->offset.img = wpr; + wpr += lsfw->img.size; + + wpr = ALIGN(wpr, 256); + lsfw->offset.bld = wpr; + lsfw->bl_data_size = ALIGN(lsfw->func->bld_size, 256); + wpr += lsfw->bl_data_size; + } + + return wpr; +} + +static int +ga102_acr_wpr_parse(struct nvkm_acr *acr) +{ + const struct wpr_header_v2 *hdr = (void *)acr->wpr_fw->data; + + while (hdr->wpr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID) { + wpr_header_v2_dump(&acr->subdev, hdr); + if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->wpr.falcon_id)) + return -ENOMEM; + } + + return 0; +} + +MODULE_FIRMWARE("nvidia/ga102/acr/ucode_unload.bin"); +MODULE_FIRMWARE("nvidia/ga103/acr/ucode_unload.bin"); +MODULE_FIRMWARE("nvidia/ga104/acr/ucode_unload.bin"); +MODULE_FIRMWARE("nvidia/ga106/acr/ucode_unload.bin"); +MODULE_FIRMWARE("nvidia/ga107/acr/ucode_unload.bin"); + +static const struct nvkm_acr_hsf_fwif +ga102_acr_unload_fwif[] = { + { 0, ga100_acr_hsfw_ctor, &ga102_flcn_fw, NVKM_ACR_HSF_SEC2 }, + {} +}; + +MODULE_FIRMWARE("nvidia/ga102/acr/ucode_asb.bin"); +MODULE_FIRMWARE("nvidia/ga103/acr/ucode_asb.bin"); +MODULE_FIRMWARE("nvidia/ga104/acr/ucode_asb.bin"); +MODULE_FIRMWARE("nvidia/ga106/acr/ucode_asb.bin"); +MODULE_FIRMWARE("nvidia/ga107/acr/ucode_asb.bin"); + +static const struct nvkm_acr_hsf_fwif +ga102_acr_asb_fwif[] = { + { 0, ga100_acr_hsfw_ctor, &ga102_flcn_fw, NVKM_ACR_HSF_GSP }, + {} +}; + +static const struct nvkm_falcon_fw_func +ga102_acr_ahesasc_0 = { + .signature = ga100_flcn_fw_signature, + .reset = gm200_flcn_fw_reset, + .setup = gp102_acr_load_setup, + .load = ga102_flcn_fw_load, + .boot = ga102_flcn_fw_boot, +}; + +MODULE_FIRMWARE("nvidia/ga102/acr/ucode_ahesasc.bin"); +MODULE_FIRMWARE("nvidia/ga103/acr/ucode_ahesasc.bin"); +MODULE_FIRMWARE("nvidia/ga104/acr/ucode_ahesasc.bin"); +MODULE_FIRMWARE("nvidia/ga106/acr/ucode_ahesasc.bin"); +MODULE_FIRMWARE("nvidia/ga107/acr/ucode_ahesasc.bin"); + +static const struct nvkm_acr_hsf_fwif +ga102_acr_ahesasc_fwif[] = { + { 0, ga100_acr_hsfw_ctor, &ga102_acr_ahesasc_0, NVKM_ACR_HSF_SEC2 }, + {} +}; + +static const struct nvkm_acr_func +ga102_acr = { + .ahesasc = ga102_acr_ahesasc_fwif, + .asb = ga102_acr_asb_fwif, + .unload = ga102_acr_unload_fwif, + .wpr_parse = ga102_acr_wpr_parse, + .wpr_layout = ga102_acr_wpr_layout, + .wpr_alloc = gp102_acr_wpr_alloc, + .wpr_patch = ga102_acr_wpr_patch, + .wpr_build = ga102_acr_wpr_build, + .wpr_check = ga100_acr_wpr_check, + .init = tu102_acr_init, +}; + +static int +ga102_acr_load(struct nvkm_acr *acr, int version, + const struct nvkm_acr_fwif *fwif) +{ + struct nvkm_subdev *subdev = &acr->subdev; + const struct nvkm_acr_hsf_fwif *hsfwif; + + hsfwif = nvkm_firmware_load(subdev, fwif->func->ahesasc, "AcrAHESASC", + acr, NULL, "acr/ucode_ahesasc", "AHESASC"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + + hsfwif = nvkm_firmware_load(subdev, fwif->func->asb, "AcrASB", + acr, NULL, "acr/ucode_asb", "ASB"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + + hsfwif = nvkm_firmware_load(subdev, fwif->func->unload, "AcrUnload", + acr, NULL, "acr/ucode_unload", "unload"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + + return 0; +} + +static const struct nvkm_acr_fwif +ga102_acr_fwif[] = { + { 0, ga102_acr_load, &ga102_acr }, + { -1, gm200_acr_nofw, &gm200_acr }, + {} +}; + +int +ga102_acr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_acr **pacr) +{ + return nvkm_acr_new_(ga102_acr_fwif, device, type, inst, pacr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c index 7a11151af3bd..31079c947758 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c @@ -61,7 +61,7 @@ gm200_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit) *limit = *limit + 0x20000; } -void +int gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust) { struct nvkm_subdev *subdev = &acr->subdev; @@ -86,6 +86,8 @@ gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust) } offset += sizeof(hdr); } while (hdr.falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID); + + return 0; } void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c index f4c2d3729feb..084f28449e52 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c @@ -29,7 +29,7 @@ #include #include -void +int gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust) { struct wpr_header_v1 hdr; @@ -54,6 +54,8 @@ gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust) offset += sizeof(hdr); } while (hdr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID); + + return 0; } int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c index 9b1cf6711ae9..69a059c648c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c @@ -29,6 +29,7 @@ void nvkm_acr_lsfw_del(struct nvkm_acr_lsfw *lsfw) { nvkm_blob_dtor(&lsfw->img); + kfree(lsfw->sigs); nvkm_firmware_put(lsfw->sig); list_del(&lsfw->head); kfree(lsfw); @@ -176,6 +177,75 @@ nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *subdev, return 0; } +int +nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *subdev, + struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id, + const char *path, int ver, + const struct nvkm_acr_lsf_func *func) +{ + const struct firmware *fw; + struct nvkm_acr_lsfw *lsfw; + const struct nvfw_ls_desc_v2 *desc; + int ret = 0; + + lsfw = nvkm_acr_lsfw_load_sig_image_desc_(subdev, falcon, id, path, ver, func, &fw); + if (IS_ERR(lsfw)) + return PTR_ERR(lsfw); + + desc = nvfw_ls_desc_v2(subdev, fw->data); + + lsfw->secure_bootloader = desc->secure_bootloader; + lsfw->bootloader_size = ALIGN(desc->bootloader_size, 256); + lsfw->bootloader_imem_offset = desc->bootloader_imem_offset; + + lsfw->app_size = ALIGN(desc->app_size, 256); + lsfw->app_start_offset = desc->app_start_offset; + lsfw->app_imem_entry = desc->app_imem_entry; + lsfw->app_resident_code_offset = desc->app_resident_code_offset; + lsfw->app_resident_code_size = desc->app_resident_code_size; + lsfw->app_resident_data_offset = desc->app_resident_data_offset; + lsfw->app_resident_data_size = desc->app_resident_data_size; + lsfw->app_imem_offset = desc->app_imem_offset; + lsfw->app_dmem_offset = desc->app_dmem_offset; + + lsfw->ucode_size = ALIGN(lsfw->app_resident_data_offset, 256) + lsfw->bootloader_size; + lsfw->data_size = lsfw->app_size + lsfw->bootloader_size - lsfw->ucode_size; + + nvkm_firmware_put(fw); + + if (lsfw->secure_bootloader) { + const struct firmware *hsbl; + const struct nvfw_ls_hsbl_bin_hdr *hdr; + const struct nvfw_ls_hsbl_hdr *hshdr; + u32 loc, sig, cnt, *meta; + + ret = nvkm_firmware_load_name(subdev, path, "hs_bl_sig", ver, &hsbl); + if (ret) + return ret; + + hdr = nvfw_ls_hsbl_bin_hdr(subdev, hsbl->data); + hshdr = nvfw_ls_hsbl_hdr(subdev, hsbl->data + hdr->header_offset); + meta = (u32 *)(hsbl->data + hshdr->meta_data_offset); + loc = *(u32 *)(hsbl->data + hshdr->patch_loc); + sig = *(u32 *)(hsbl->data + hshdr->patch_sig); + cnt = *(u32 *)(hsbl->data + hshdr->num_sig); + + lsfw->fuse_ver = meta[0]; + lsfw->engine_id = meta[1]; + lsfw->ucode_id = meta[2]; + lsfw->sig_size = hshdr->sig_prod_size / cnt; + lsfw->sig_nr = cnt; + lsfw->sigs = kmemdup(hsbl->data + hshdr->sig_prod_offset + sig, + lsfw->sig_nr * lsfw->sig_size, GFP_KERNEL); + nvkm_firmware_put(hsbl); + if (!lsfw->sigs) + ret = -ENOMEM; + } + + return ret; +} + int nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *subdev, struct nvkm_falcon *falcon, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h index 66a764e24bc6..4881c8ba3880 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h @@ -24,7 +24,7 @@ struct nvkm_acr_func { u32 (*wpr_layout)(struct nvkm_acr *); int (*wpr_alloc)(struct nvkm_acr *, u32 wpr_size); int (*wpr_build)(struct nvkm_acr *, struct nvkm_acr_lsf *rtos); - void (*wpr_patch)(struct nvkm_acr *, s64 adjust); + int (*wpr_patch)(struct nvkm_acr *, s64 adjust); void (*wpr_check)(struct nvkm_acr *, u64 *start, u64 *limit); int (*init)(struct nvkm_acr *); void (*fini)(struct nvkm_acr *); @@ -35,7 +35,7 @@ extern const struct nvkm_acr_func gm200_acr; int gm200_acr_wpr_parse(struct nvkm_acr *); u32 gm200_acr_wpr_layout(struct nvkm_acr *); int gm200_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *); -void gm200_acr_wpr_patch(struct nvkm_acr *, s64); +int gm200_acr_wpr_patch(struct nvkm_acr *, s64); void gm200_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *); void gm200_acr_wpr_build_lsb_tail(struct nvkm_acr_lsfw *, struct lsb_header_tail *); @@ -48,7 +48,11 @@ u32 gp102_acr_wpr_layout(struct nvkm_acr *); int gp102_acr_wpr_alloc(struct nvkm_acr *, u32 wpr_size); int gp102_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *); int gp102_acr_wpr_build_lsb(struct nvkm_acr *, struct nvkm_acr_lsfw *); -void gp102_acr_wpr_patch(struct nvkm_acr *, s64); +int gp102_acr_wpr_patch(struct nvkm_acr *, s64); + +int tu102_acr_init(struct nvkm_acr *); + +void ga100_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *); struct nvkm_acr_hsfw { struct nvkm_falcon_fw fw; @@ -93,6 +97,9 @@ extern const struct nvkm_falcon_fw_func gp108_acr_load_0; extern const struct nvkm_falcon_fw_func gp108_acr_hsfw_0; int gp108_acr_hsfw_load_bld(struct nvkm_falcon_fw *); +int ga100_acr_hsfw_ctor(struct nvkm_acr *, const char *, const char *, const char *, int, + const struct nvkm_acr_hsf_fwif *); + int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c index ad45f5cb452b..c22d551c0078 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c @@ -29,7 +29,7 @@ #include -static int +int tu102_acr_init(struct nvkm_acr *acr) { int ret = nvkm_acr_hsfw_boot(acr, "AHESASC"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild index 67cc3b320169..7f61a1ed158b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild @@ -1,3 +1,4 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/subdev/gsp/base.o nvkm-y += nvkm/subdev/gsp/gv100.o +nvkm-y += nvkm/subdev/gsp/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c new file mode 100644 index 000000000000..525267412c3e --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c @@ -0,0 +1,59 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +static const struct nvkm_falcon_func +ga102_gsp_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .select = ga102_flcn_select, + .addr2 = 0x1000, + .reset_eng = gp102_flcn_reset_eng, + .reset_prep = ga102_flcn_reset_prep, + .reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing, + .imem_dma = &ga102_flcn_dma, + .dmem_dma = &ga102_flcn_dma, +}; + +static const struct nvkm_gsp_func +ga102_gsp = { + .flcn = &ga102_gsp_flcn, +}; + +static int +ga102_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif) +{ + return 0; +} + +struct nvkm_gsp_fwif +ga102_gsps[] = { + { -1, ga102_gsp_nofw, &ga102_gsp }, + {} +}; + +int +ga102_gsp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_gsp **pgsp) +{ + return nvkm_gsp_new_(ga102_gsps, device, type, inst, pgsp); +} -- cgit v1.2.3 From 21e938d0017d3523ef5114a8feebc32e95007983 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:34 +1000 Subject: drm/nouveau/ltc/ga102: initial support v2. fixup for ga103 early merge Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 5 ++ drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c | 57 +++++++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h index 213d5ff33cae..64294042ec07 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h @@ -4,7 +4,7 @@ #include #include -#define NVKM_LTC_MAX_ZBC_COLOR_CNT 16 +#define NVKM_LTC_MAX_ZBC_COLOR_CNT 32 #define NVKM_LTC_MAX_ZBC_DEPTH_CNT 16 struct nvkm_ltc { @@ -44,4 +44,5 @@ int gm200_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct int gp100_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_ltc **); int gp102_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_ltc **); int gp10b_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_ltc **); +int ga102_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_ltc **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 666300dc0bf0..9e4b194f24bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2606,6 +2606,7 @@ nv172_chipset = { .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, + .ltc = { 0x00000001, ga102_ltc_new }, .mc = { 0x00000001, ga100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, @@ -2634,6 +2635,7 @@ nv173_chipset = { .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, + .ltc = { 0x00000001, ga102_ltc_new }, .mc = { 0x00000001, ga100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, @@ -2662,6 +2664,7 @@ nv174_chipset = { .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, + .ltc = { 0x00000001, ga102_ltc_new }, .mc = { 0x00000001, ga100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, @@ -2690,6 +2693,7 @@ nv176_chipset = { .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, + .ltc = { 0x00000001, ga102_ltc_new }, .mc = { 0x00000001, ga100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, @@ -2718,6 +2722,7 @@ nv177_chipset = { .gsp = { 0x00000001, ga102_gsp_new }, .i2c = { 0x00000001, gm200_i2c_new }, .imem = { 0x00000001, nv50_instmem_new }, + .ltc = { 0x00000001, ga102_ltc_new }, .mc = { 0x00000001, ga100_mc_new }, .mmu = { 0x00000001, tu102_mmu_new }, .pci = { 0x00000001, gp100_pci_new }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild index 728d75010847..0d8a915d727e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild @@ -7,3 +7,4 @@ nvkm-y += nvkm/subdev/ltc/gm200.o nvkm-y += nvkm/subdev/ltc/gp100.o nvkm-y += nvkm/subdev/ltc/gp102.o nvkm-y += nvkm/subdev/ltc/gp10b.o +nvkm-y += nvkm/subdev/ltc/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c new file mode 100644 index 000000000000..159d9f8c95f3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c @@ -0,0 +1,57 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" + +static void +ga102_ltc_zbc_clear_color(struct nvkm_ltc *ltc, int i, const u32 color[4]) +{ + struct nvkm_device *device = ltc->subdev.device; + + nvkm_mask(device, 0x17e338, 0x0000001f, i); + nvkm_wr32(device, 0x17e33c, color[0]); + nvkm_wr32(device, 0x17e340, color[1]); + nvkm_wr32(device, 0x17e344, color[2]); + nvkm_wr32(device, 0x17e348, color[3]); +} + +static const struct nvkm_ltc_func +ga102_ltc = { + .oneinit = gp100_ltc_oneinit, + .init = gp100_ltc_init, + .intr = gp100_ltc_intr, + .cbc_clear = gm107_ltc_cbc_clear, + .cbc_wait = gm107_ltc_cbc_wait, + .zbc_color = 31, + .zbc_depth = 16, + .zbc_clear_color = ga102_ltc_zbc_clear_color, + .zbc_clear_depth = gm107_ltc_zbc_clear_depth, + .zbc_clear_stencil = gp102_ltc_zbc_clear_stencil, + .invalidate = gf100_ltc_invalidate, + .flush = gf100_ltc_flush, +}; + +int +ga102_ltc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_ltc **pltc) +{ + return nvkm_ltc_new_(&ga102_ltc, device, type, inst, pltc); +} -- cgit v1.2.3 From c4bdac754ca0bb21bad598b47dd8c2c86eee1cc1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:48:35 +1000 Subject: drm/nouveau/gr/ga102: initial support v2: - whitespace Signed-off-by: Ben Skeggs Signed-off-by: Gourav Samaiya --- drivers/gpu/drm/nouveau/include/nvif/class.h | 3 + drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 7 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 5 + drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c | 77 +++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 3 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c | 347 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 24 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 14 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 6 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c | 75 +++++ 15 files changed, 565 insertions(+), 9 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index 15529d2c85f9..ad1e5de84e80 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -190,6 +190,8 @@ #define TURING_A /* cl9097.h */ 0x0000c597 +#define AMPERE_B /* cl9097.h */ 0x0000c797 + #define NV74_BSP 0x000074b0 #define GT212_MSVLD 0x000085b1 @@ -234,6 +236,7 @@ #define PASCAL_COMPUTE_B 0x0000c1c0 #define VOLTA_COMPUTE_A 0x0000c3c0 #define TURING_COMPUTE_A 0x0000c5c0 +#define AMPERE_COMPUTE_B 0x0000c7c0 #define NV74_CIPHER 0x000074c1 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h index b28b752ffaa2..a2333cfe6955 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h @@ -54,4 +54,5 @@ int gp108_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n int gp10b_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_gr **); int gv100_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_gr **); int tu102_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_gr **); +int ga102_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_gr **); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 4c1f81ee1cef..73d2a6ae9ab2 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -118,6 +118,7 @@ struct nvkm_acr_lsf_func { #define NVKM_ACR_LSF_DMACTL_REQ_CTX 0x00000004 #define NVKM_ACR_LSF_FORCE_PRIV_LOAD 0x00000008 u32 flags; + u32 bl_entry; u32 bld_size; void (*bld_write)(struct nvkm_acr *, u32 bld, struct nvkm_acr_lsfw *); void (*bld_patch)(struct nvkm_acr *, u32 bld, s64 adjust); @@ -144,4 +145,10 @@ int nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *, struct nvkm_falcon *, enum nvkm_acr_lsf_id, const char *path, int ver, const struct nvkm_acr_lsf_func *); + +int +nvkm_acr_lsfw_load_bl_sig_net(struct nvkm_subdev *, struct nvkm_falcon *, + enum nvkm_acr_lsf_id, const char *path, + int ver, const struct nvkm_acr_lsf_func *, + const void *, u32, const void *, u32); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 9e4b194f24bf..364fea320cb3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2618,6 +2618,7 @@ nv172_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .gr = { 0x00000001, ga102_gr_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, .sec2 = { 0x00000001, ga102_sec2_new }, }; @@ -2647,6 +2648,7 @@ nv173_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .gr = { 0x00000001, ga102_gr_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, .sec2 = { 0x00000001, ga102_sec2_new }, }; @@ -2676,6 +2678,7 @@ nv174_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .gr = { 0x00000001, ga102_gr_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, .sec2 = { 0x00000001, ga102_sec2_new }, }; @@ -2705,6 +2708,7 @@ nv176_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .gr = { 0x00000001, ga102_gr_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, .sec2 = { 0x00000001, ga102_sec2_new }, }; @@ -2734,6 +2738,7 @@ nv177_chipset = { .disp = { 0x00000001, ga102_disp_new }, .dma = { 0x00000001, gv100_dma_new }, .fifo = { 0x00000001, ga102_fifo_new }, + .gr = { 0x00000001, ga102_gr_new }, .nvdec = { 0x00000001, ga102_nvdec_new }, .sec2 = { 0x00000001, ga102_sec2_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild index 558c86fd8e82..b5418f05ccd8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild @@ -40,6 +40,7 @@ nvkm-y += nvkm/engine/gr/gp108.o nvkm-y += nvkm/engine/gr/gp10b.o nvkm-y += nvkm/engine/gr/gv100.o nvkm-y += nvkm/engine/gr/tu102.o +nvkm-y += nvkm/engine/gr/ga102.o nvkm-y += nvkm/engine/gr/ctxnv40.o nvkm-y += nvkm/engine/gr/ctxnv50.o @@ -63,3 +64,4 @@ nvkm-y += nvkm/engine/gr/ctxgp104.o nvkm-y += nvkm/engine/gr/ctxgp107.o nvkm-y += nvkm/engine/gr/ctxgv100.o nvkm-y += nvkm/engine/gr/ctxtu102.o +nvkm-y += nvkm/engine/gr/ctxga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c new file mode 100644 index 000000000000..11461adf5036 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c @@ -0,0 +1,77 @@ +/* + * Copyright 2019 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ctxgf100.h" + +static void +ga102_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + tpc = gv100_gr_nonpes_aware_tpc(gr, gpc, tpc); + + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x608), sm); +} + +static void +ga102_grctx_generate_unkn(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_mask(device, 0x41980c, 0x00000010, 0x00000010); + nvkm_mask(device, 0x41be08, 0x00000004, 0x00000004); +} + +static void +ga102_grctx_generate_r419ea8(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, 0x419ea8, nvkm_rd32(device, 0x504728) | 0x08000000); +} + +const struct gf100_grctx_func +ga102_grctx = { + .main = gf100_grctx_generate_main, + .unkn = ga102_grctx_generate_unkn, + .bundle = gm107_grctx_generate_bundle, + .bundle_size = 0x3000, + .bundle_min_gpm_fifo_depth = 0x180, + .bundle_token_limit = 0x1140, + .pagepool = gp100_grctx_generate_pagepool, + .pagepool_size = 0x20000, + .attrib_cb_size = gp102_grctx_generate_attrib_cb_size, + .attrib_cb = gv100_grctx_generate_attrib_cb, + .attrib = gv100_grctx_generate_attrib, + .attrib_nr_max = 0x800, + .attrib_nr = 0x4a1, + .alpha_nr_max = 0xc00, + .alpha_nr = 0x800, + .unknown_size = 0x80000, + .unknown = tu102_grctx_generate_unknown, + .gfxp_nr = 0xd28, + .sm_id = ga102_grctx_generate_sm_id, + .skip_pd_num_tpc_per_gpc = true, + .rop_mapping = gv100_grctx_generate_rop_mapping, + .r406500 = gm200_grctx_generate_r406500, + .r400088 = gv100_grctx_generate_r400088, + .r419ea8 = ga102_grctx_generate_r419ea8, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 2a31d4464a32..cb390e0134a2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1361,6 +1361,8 @@ gf100_grctx_generate_main(struct gf100_gr_chan *chan) if (gr->func->init_419bd8) gr->func->init_419bd8(gr); + if (grctx->r419ea8) + grctx->r419ea8(gr); gf100_gr_wait_idle(gr); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 46f94c143936..00dbeda7e346 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -69,6 +69,7 @@ struct gf100_grctx_func { void (*r419a3c)(struct gf100_gr *); void (*r408840)(struct gf100_gr *); void (*r419c0c)(struct gf100_gr *); + void (*r419ea8)(struct gf100_gr *); }; extern const struct gf100_grctx_func gf100_grctx; @@ -161,6 +162,8 @@ void gv100_grctx_generate_r400088(struct gf100_gr *, bool); void tu102_grctx_generate_unknown(struct gf100_gr_chan *, u64, u32); +extern const struct gf100_grctx_func ga102_grctx; + /* context init value lists */ extern const struct gf100_gr_pack gf100_grctx_pack_icmd[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c new file mode 100644 index 000000000000..a5b5ac2755a2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c @@ -0,0 +1,347 @@ +/* + * Copyright 2019 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "gf100.h" +#include "ctxgf100.h" + +#include +#include +#include +#include + +#include + +#include + +static void +ga102_gr_zbc_clear_color(struct gf100_gr *gr, int zbc) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + u32 invalid[] = { 0, 0, 0, 0 }, *color; + + if (gr->zbc_color[zbc].format) + color = gr->zbc_color[zbc].l2; + else + color = invalid; + + nvkm_mask(device, 0x41bcb4, 0x0000001f, zbc); + nvkm_wr32(device, 0x41bcec, color[0]); + nvkm_wr32(device, 0x41bcf0, color[1]); + nvkm_wr32(device, 0x41bcf4, color[2]); + nvkm_wr32(device, 0x41bcf8, color[3]); +} + +static const struct gf100_gr_func_zbc +ga102_gr_zbc = { + .clear_color = ga102_gr_zbc_clear_color, + .clear_depth = gp100_gr_zbc_clear_depth, + .stencil_get = gp102_gr_zbc_stencil_get, + .clear_stencil = gp102_gr_zbc_clear_stencil, +}; + +static void +ga102_gr_gpccs_reset(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, 0x41a610, 0x00000000); + nvkm_msec(device, 1, NVKM_DELAY); + nvkm_wr32(device, 0x41a610, 0x00000001); +} + +static const struct nvkm_acr_lsf_func +ga102_gr_gpccs_acr = { + .flags = NVKM_ACR_LSF_FORCE_PRIV_LOAD, + .bl_entry = 0x3400, + .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), + .bld_write = gp108_gr_acr_bld_write, + .bld_patch = gp108_gr_acr_bld_patch, +}; + +static void +ga102_gr_fecs_reset(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, 0x409614, 0x00000010); + nvkm_wr32(device, 0x41a614, 0x00000020); + nvkm_usec(device, 10, NVKM_DELAY); + nvkm_wr32(device, 0x409614, 0x00000110); + nvkm_wr32(device, 0x41a614, 0x00000a20); + nvkm_usec(device, 10, NVKM_DELAY); + nvkm_rd32(device, 0x409614); + nvkm_rd32(device, 0x41a614); +} + +static const struct nvkm_acr_lsf_func +ga102_gr_fecs_acr = { + .bl_entry = 0x7e00, + .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), + .bld_write = gp108_gr_acr_bld_write, + .bld_patch = gp108_gr_acr_bld_patch, +}; + +static void +ga102_gr_init_rop_exceptions(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, 0x41bcbc, 0x40000000); + nvkm_wr32(device, 0x41bc38, 0x40000000); + nvkm_wr32(device, 0x41ac94, nvkm_rd32(device, 0x502c94)); +} + +static void +ga102_gr_init_40a790(struct gf100_gr *gr) +{ + nvkm_wr32(gr->base.engine.subdev.device, 0x40a790, 0xc0000000); +} + +static void +ga102_gr_init_gpc_mmu(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, 0x418880, nvkm_rd32(device, 0x100c80) & 0xf8001fff); + nvkm_wr32(device, 0x418894, 0x00000000); + + nvkm_wr32(device, 0x4188b4, nvkm_rd32(device, 0x100cc8)); + nvkm_wr32(device, 0x4188b8, nvkm_rd32(device, 0x100ccc)); + nvkm_wr32(device, 0x4188b0, nvkm_rd32(device, 0x100cc4)); +} + +static struct nvkm_intr * +ga102_gr_oneinit_intr(struct gf100_gr *gr, enum nvkm_intr_type *pvector) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + *pvector = nvkm_rd32(device, 0x400154) & 0x00000fff; + return &device->vfn->intr; +} + +static const struct gf100_gr_func +ga102_gr = { + .oneinit_intr = ga102_gr_oneinit_intr, + .oneinit_tiles = gm200_gr_oneinit_tiles, + .oneinit_sm_id = gv100_gr_oneinit_sm_id, + .init = gf100_gr_init, + .init_419bd8 = gv100_gr_init_419bd8, + .init_gpc_mmu = ga102_gr_init_gpc_mmu, + .init_vsc_stream_master = gk104_gr_init_vsc_stream_master, + .init_zcull = tu102_gr_init_zcull, + .init_num_active_ltcs = gf100_gr_init_num_active_ltcs, + .init_swdx_pes_mask = gp102_gr_init_swdx_pes_mask, + .init_fs = tu102_gr_init_fs, + .init_fecs_exceptions = tu102_gr_init_fecs_exceptions, + .init_40a790 = ga102_gr_init_40a790, + .init_ds_hww_esr_2 = gm200_gr_init_ds_hww_esr_2, + .init_sked_hww_esr = gk104_gr_init_sked_hww_esr, + .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, + .init_504430 = gv100_gr_init_504430, + .init_shader_exceptions = gv100_gr_init_shader_exceptions, + .init_rop_exceptions = ga102_gr_init_rop_exceptions, + .init_4188a4 = gv100_gr_init_4188a4, + .trap_mp = gv100_gr_trap_mp, + .fecs.reset = ga102_gr_fecs_reset, + .gpccs.reset = ga102_gr_gpccs_reset, + .rops = gm200_gr_rops, + .gpc_nr = 7, + .tpc_nr = 6, + .ppc_nr = 3, + .grctx = &ga102_grctx, + .zbc = &ga102_gr_zbc, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, AMPERE_B, &gf100_fermi }, + { -1, -1, AMPERE_COMPUTE_B }, + {} + } +}; + +MODULE_FIRMWARE("nvidia/ga102/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga102/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga102/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga102/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga102/gr/NET_img.bin"); + +MODULE_FIRMWARE("nvidia/ga103/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga103/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga103/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga103/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga103/gr/NET_img.bin"); + +MODULE_FIRMWARE("nvidia/ga104/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga104/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga104/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga104/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga104/gr/NET_img.bin"); + +MODULE_FIRMWARE("nvidia/ga106/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga106/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga106/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga106/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga106/gr/NET_img.bin"); + +MODULE_FIRMWARE("nvidia/ga107/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga107/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga107/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/ga107/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/ga107/gr/NET_img.bin"); + +struct netlist_region { + u32 region_id; + u32 data_size; + u32 data_offset; +}; + +struct netlist_image_header { + u32 version; + u32 regions; +}; + +struct netlist_image { + struct netlist_image_header header; + struct netlist_region regions[]; +}; + +struct netlist_av64 { + u32 addr; + u32 data_hi; + u32 data_lo; +}; + +static int +ga102_gr_av64_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) +{ + struct gf100_gr_init *init; + struct gf100_gr_pack *pack; + int nent; + int i; + + nent = (blob->size / sizeof(struct netlist_av64)); + pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1))); + if (!pack) + return -ENOMEM; + + init = (void *)(pack + 2); + pack[0].init = init; + pack[0].type = 64; + + for (i = 0; i < nent; i++) { + struct gf100_gr_init *ent = &init[i]; + struct netlist_av64 *av = &((struct netlist_av64 *)blob->data)[i]; + + ent->addr = av->addr; + ent->data = ((u64)av->data_hi << 32) | av->data_lo; + ent->count = 1; + ent->pitch = 1; + } + + *ppack = pack; + return 0; +} + +static int +ga102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) +{ + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + const struct firmware *fw; + const struct netlist_image *net; + const struct netlist_region *fecs_inst = NULL; + const struct netlist_region *fecs_data = NULL; + const struct netlist_region *gpccs_inst = NULL; + const struct netlist_region *gpccs_data = NULL; + int ret, i; + + ret = nvkm_firmware_get(subdev, "gr/NET_img", 0, &fw); + if (ret) + return ret; + + net = (const void *)fw->data; + nvkm_debug(subdev, "netlist version %d, %d regions\n", + net->header.version, net->header.regions); + + for (i = 0; i < net->header.regions; i++) { + const struct netlist_region *reg = &net->regions[i]; + struct nvkm_blob blob = { + .data = (void *)fw->data + reg->data_offset, + .size = reg->data_size, + }; + + nvkm_debug(subdev, "\t%2d: %08x %08x\n", + reg->region_id, reg->data_offset, reg->data_size); + + switch (reg->region_id) { + case 0: fecs_data = reg; break; + case 1: fecs_inst = reg; break; + case 2: gpccs_data = reg; break; + case 3: gpccs_inst = reg; break; + case 4: gk20a_gr_av_to_init(&blob, &gr->bundle); break; + case 5: gk20a_gr_aiv_to_init(&blob, &gr->sw_ctx); break; + case 7: gk20a_gr_av_to_method(&blob, &gr->method); break; + case 28: tu102_gr_av_to_init_veid(&blob, &gr->bundle_veid); break; + case 34: ga102_gr_av64_to_init(&blob, &gr->bundle64); break; + case 48: gk20a_gr_av_to_init(&blob, &gr->sw_nonctx1); break; + case 49: gk20a_gr_av_to_init(&blob, &gr->sw_nonctx2); break; + case 50: gk20a_gr_av_to_init(&blob, &gr->sw_nonctx3); break; + case 51: gk20a_gr_av_to_init(&blob, &gr->sw_nonctx4); break; + default: + break; + } + } + + ret = nvkm_acr_lsfw_load_bl_sig_net(subdev, &gr->fecs.falcon, NVKM_ACR_LSF_FECS, + "gr/fecs_", ver, fwif->fecs, + fw->data + fecs_inst->data_offset, + fecs_inst->data_size, + fw->data + fecs_data->data_offset, + fecs_data->data_size); + if (ret) + return ret; + + ret = nvkm_acr_lsfw_load_bl_sig_net(subdev, &gr->gpccs.falcon, NVKM_ACR_LSF_GPCCS, + "gr/gpccs_", ver, fwif->gpccs, + fw->data + gpccs_inst->data_offset, + gpccs_inst->data_size, + fw->data + gpccs_data->data_offset, + gpccs_data->data_size); + if (ret) + return ret; + + gr->firmware = true; + + nvkm_firmware_put(fw); + return 0; +} + +static const struct gf100_gr_fwif +ga102_gr_fwif[] = { + { 0, ga102_gr_load, &ga102_gr, &ga102_gr_fecs_acr, &ga102_gr_gpccs_acr }, + { -1, gm200_gr_nofw }, + {} +}; + +int +ga102_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(ga102_gr_fwif, device, type, inst, pgr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index b82989ef7f3b..5f20079c3660 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1995,6 +1995,9 @@ gf100_gr_oneinit(struct nvkm_gr *base) enum nvkm_intr_type intr_type = NVKM_INTR_SUBDEV; int ret, i, j; + if (gr->func->oneinit_intr) + intr = gr->func->oneinit_intr(gr, &intr_type); + ret = nvkm_inth_add(intr, intr_type, NVKM_INTR_PRIO_NORMAL, &gr->base.engine.subdev, gf100_gr_intr, &gr->base.engine.subdev.inth); if (ret) @@ -2147,6 +2150,10 @@ gf100_gr_dtor(struct nvkm_gr *base) vfree(gr->method); vfree(gr->sw_ctx); vfree(gr->sw_nonctx); + vfree(gr->sw_nonctx1); + vfree(gr->sw_nonctx2); + vfree(gr->sw_nonctx3); + vfree(gr->sw_nonctx4); return gr; } @@ -2324,6 +2331,8 @@ gf100_gr_reset(struct nvkm_gr *base) subdev->func->fini(subdev, false); nvkm_mc_disable(device, subdev->type, subdev->inst); + if (gr->func->gpccs.reset) + gr->func->gpccs.reset(gr); nvkm_mc_enable(device, subdev->type, subdev->inst); return subdev->func->init(subdev); @@ -2339,10 +2348,17 @@ gf100_gr_init(struct gf100_gr *gr) gr->func->init_gpc_mmu(gr); - if (gr->sw_nonctx) + if (gr->sw_nonctx1) { + gf100_gr_mmio(gr, gr->sw_nonctx1); + gf100_gr_mmio(gr, gr->sw_nonctx2); + gf100_gr_mmio(gr, gr->sw_nonctx3); + gf100_gr_mmio(gr, gr->sw_nonctx4); + } else + if (gr->sw_nonctx) { gf100_gr_mmio(gr, gr->sw_nonctx); - else + } else { gf100_gr_mmio(gr, gr->func->mmio); + } gf100_gr_wait_idle(gr); @@ -2374,6 +2390,10 @@ gf100_gr_init(struct gf100_gr *gr) nvkm_wr32(device, 0x400124, 0x00000002); gr->func->init_fecs_exceptions(gr); + + if (gr->func->init_40a790) + gr->func->init_40a790(gr); + if (gr->func->init_ds_hww_esr_2) gr->func->init_ds_hww_esr_2(gr); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 88fccea248e5..94ca7ac16acf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -88,6 +88,10 @@ struct gf100_gr { * using hardcoded arrays. To be allocated with vzalloc(). */ struct gf100_gr_pack *sw_nonctx; + struct gf100_gr_pack *sw_nonctx1; + struct gf100_gr_pack *sw_nonctx2; + struct gf100_gr_pack *sw_nonctx3; + struct gf100_gr_pack *sw_nonctx4; struct gf100_gr_pack *sw_ctx; struct gf100_gr_pack *bundle; struct gf100_gr_pack *bundle_veid; @@ -143,6 +147,7 @@ struct gf100_gr_func_zbc { }; struct gf100_gr_func { + struct nvkm_intr *(*oneinit_intr)(struct gf100_gr *, enum nvkm_intr_type *); void (*oneinit_tiles)(struct gf100_gr *); int (*oneinit_sm_id)(struct gf100_gr *); int (*init)(struct gf100_gr *); @@ -158,6 +163,7 @@ struct gf100_gr_func { void (*init_swdx_pes_mask)(struct gf100_gr *); void (*init_fs)(struct gf100_gr *); void (*init_fecs_exceptions)(struct gf100_gr *); + void (*init_40a790)(struct gf100_gr *); void (*init_ds_hww_esr_2)(struct gf100_gr *); void (*init_40601c)(struct gf100_gr *); void (*init_sked_hww_esr)(struct gf100_gr *); @@ -181,6 +187,7 @@ struct gf100_gr_func { } fecs; struct { struct gf100_gr_ucode *ucode; + void (*reset)(struct gf100_gr *); } gpccs; int (*rops)(struct gf100_gr *); int gpc_nr; @@ -246,6 +253,8 @@ extern const struct gf100_gr_func_zbc gp100_gr_zbc; void gp102_gr_init_swdx_pes_mask(struct gf100_gr *); extern const struct gf100_gr_func_zbc gp102_gr_zbc; +int gp102_gr_zbc_stencil_get(struct gf100_gr *, int, const u32, const u32); +void gp102_gr_zbc_clear_stencil(struct gf100_gr *, int); extern const struct gf100_gr_func gp107_gr; @@ -258,6 +267,9 @@ void gv100_gr_init_4188a4(struct gf100_gr *); void gv100_gr_trap_mp(struct gf100_gr *, int, int); int tu102_gr_av_to_init_veid(struct nvkm_blob *, struct gf100_gr_pack **); +void tu102_gr_init_zcull(struct gf100_gr *); +void tu102_gr_init_fs(struct gf100_gr *); +void tu102_gr_init_fecs_exceptions(struct gf100_gr *); #define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) #include @@ -427,6 +439,8 @@ void gm20b_gr_acr_bld_patch(struct nvkm_acr *, u32, s64); extern const struct nvkm_acr_lsf_func gp108_gr_gpccs_acr; extern const struct nvkm_acr_lsf_func gp108_gr_fecs_acr; +void gp108_gr_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); +void gp108_gr_acr_bld_patch(struct nvkm_acr *, u32, s64); int gf100_gr_new_(const struct gf100_gr_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gr **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c index f265ba08c5ef..0e223b7b5f0e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c @@ -26,7 +26,7 @@ #include -static void +void gp102_gr_zbc_clear_stencil(struct gf100_gr *gr, int zbc) { struct nvkm_device *device = gr->base.engine.subdev.device; @@ -40,7 +40,7 @@ gp102_gr_zbc_clear_stencil(struct gf100_gr *gr, int zbc) gr->zbc_stencil[zbc].format << ((znum % 4) * 7)); } -static int +int gp102_gr_zbc_stencil_get(struct gf100_gr *gr, int format, const u32 ds, const u32 l2) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c index 7310f0466bb7..311f703439e4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c @@ -25,7 +25,7 @@ #include -static void +void gp108_gr_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) { struct flcn_bl_dmem_desc_v2 hdr; @@ -36,7 +36,7 @@ gp108_gr_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr); } -static void +void gp108_gr_acr_bld_write(struct nvkm_acr *acr, u32 bld, struct nvkm_acr_lsfw *lsfw) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 255d50c4c65f..3b6c8100a242 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -24,13 +24,13 @@ #include -static void +void tu102_gr_init_fecs_exceptions(struct gf100_gr *gr) { nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x006e0003); } -static void +void tu102_gr_init_fs(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; @@ -49,7 +49,7 @@ tu102_gr_init_fs(struct gf100_gr *gr) gf100_gr_init_num_tpc_per_gpc(gr, true, true); } -static void +void tu102_gr_init_zcull(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c index 69a059c648c6..f36a359d4531 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c @@ -321,3 +321,78 @@ done: nvkm_firmware_put(bl); return ret; } + +int +nvkm_acr_lsfw_load_bl_sig_net(struct nvkm_subdev *subdev, + struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id, + const char *path, int ver, + const struct nvkm_acr_lsf_func *func, + const void *inst_data, u32 inst_size, + const void *data_data, u32 data_size) +{ + struct nvkm_acr *acr = subdev->device->acr; + struct nvkm_acr_lsfw *lsfw; + const struct firmware _inst = { .data = inst_data, .size = inst_size }; + const struct firmware _data = { .data = data_data, .size = data_size }; + const struct firmware *bl = NULL, *inst = &_inst, *data = &_data; + const struct { + int bin_magic; + int bin_version; + int bin_size; + int header_offset; + int header_size; + } *hdr; + u32 *bldata; + int ret; + + if (IS_ERR((lsfw = nvkm_acr_lsfw_add(func, acr, falcon, id)))) + return PTR_ERR(lsfw); + + ret = nvkm_firmware_load_name(subdev, path, "bl", ver, &bl); + if (ret) + goto done; + + hdr = (const void *)bl->data; + bldata = (void *)(bl->data + hdr->header_offset); + + ret = nvkm_firmware_load_name(subdev, path, "sig", ver, &lsfw->sig); + if (ret) + goto done; + + lsfw->bootloader_size = ALIGN(hdr->header_size, 256); + lsfw->bootloader_imem_offset = func->bl_entry; + + lsfw->app_start_offset = lsfw->bootloader_size; + lsfw->app_imem_entry = 0; + lsfw->app_resident_code_offset = 0; + lsfw->app_resident_code_size = ALIGN(inst->size, 256); + lsfw->app_resident_data_offset = lsfw->app_resident_code_size; + lsfw->app_resident_data_size = ALIGN(data->size, 256); + lsfw->app_imem_offset = 0; + lsfw->app_dmem_offset = 0; + lsfw->app_size = lsfw->app_resident_code_size + lsfw->app_resident_data_size; + + lsfw->img.size = lsfw->bootloader_size + lsfw->app_size; + if (!(lsfw->img.data = kzalloc(lsfw->img.size, GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + + memcpy(lsfw->img.data, bldata, lsfw->bootloader_size); + memcpy(lsfw->img.data + lsfw->app_start_offset + + lsfw->app_resident_code_offset, inst->data, inst->size); + memcpy(lsfw->img.data + lsfw->app_start_offset + + lsfw->app_resident_data_offset, data->data, data->size); + + lsfw->ucode_size = ALIGN(lsfw->app_resident_data_offset, 256) + + lsfw->bootloader_size; + lsfw->data_size = lsfw->app_size + lsfw->bootloader_size - + lsfw->ucode_size; + +done: + if (ret) + nvkm_acr_lsfw_del(lsfw); + nvkm_firmware_put(bl); + return ret; +} -- cgit v1.2.3 From 519b58bbfa825f042fcf80261cc18e1e35f85ffd Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Tue, 8 Nov 2022 10:56:07 +0800 Subject: net: marvell: prestera: fix memory leak in prestera_rxtx_switch_init() When prestera_sdma_switch_init() failed, the memory pointed to by sw->rxtx isn't released. Fix it. Only be compiled, not be tested. Fixes: 501ef3066c89 ("net: marvell: prestera: Add driver for Prestera family ASIC devices") Signed-off-by: Zhengchao Shao Reviewed-by: Vadym Kochan Link: https://lore.kernel.org/r/20221108025607.338450-1-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/prestera/prestera_rxtx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c index 42ee963e9f75..9277a8fd1339 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c @@ -776,6 +776,7 @@ tx_done: int prestera_rxtx_switch_init(struct prestera_switch *sw) { struct prestera_rxtx *rxtx; + int err; rxtx = kzalloc(sizeof(*rxtx), GFP_KERNEL); if (!rxtx) @@ -783,7 +784,11 @@ int prestera_rxtx_switch_init(struct prestera_switch *sw) sw->rxtx = rxtx; - return prestera_sdma_switch_init(sw); + err = prestera_sdma_switch_init(sw); + if (err) + kfree(rxtx); + + return err; } void prestera_rxtx_switch_fini(struct prestera_switch *sw) -- cgit v1.2.3 From 07d120aa33cc9d9115753d159f64d20c94458781 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 7 Nov 2022 18:00:11 +0000 Subject: net: tun: call napi_schedule_prep() to ensure we own a napi A recent patch exposed another issue in napi_get_frags() caught by syzbot [1] Before feeding packets to GRO, and calling napi_complete() we must first grab NAPI_STATE_SCHED. [1] WARNING: CPU: 0 PID: 3612 at net/core/dev.c:6076 napi_complete_done+0x45b/0x880 net/core/dev.c:6076 Modules linked in: CPU: 0 PID: 3612 Comm: syz-executor408 Not tainted 6.1.0-rc3-syzkaller-00175-g1118b2049d77 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 RIP: 0010:napi_complete_done+0x45b/0x880 net/core/dev.c:6076 Code: c1 ea 03 0f b6 14 02 4c 89 f0 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 24 04 00 00 41 89 5d 1c e9 73 fc ff ff e8 b5 53 22 fa <0f> 0b e9 82 fe ff ff e8 a9 53 22 fa 48 8b 5c 24 08 31 ff 48 89 de RSP: 0018:ffffc90003c4f920 EFLAGS: 00010293 RAX: 0000000000000000 RBX: 0000000000000030 RCX: 0000000000000000 RDX: ffff8880251c0000 RSI: ffffffff875a58db RDI: 0000000000000007 RBP: 0000000000000001 R08: 0000000000000007 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000001 R12: ffff888072d02628 R13: ffff888072d02618 R14: ffff888072d02634 R15: 0000000000000000 FS: 0000555555f13300(0000) GS:ffff8880b9a00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055c44d3892b8 CR3: 00000000172d2000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: napi_complete include/linux/netdevice.h:510 [inline] tun_get_user+0x206d/0x3a60 drivers/net/tun.c:1980 tun_chr_write_iter+0xdb/0x200 drivers/net/tun.c:2027 call_write_iter include/linux/fs.h:2191 [inline] do_iter_readv_writev+0x20b/0x3b0 fs/read_write.c:735 do_iter_write+0x182/0x700 fs/read_write.c:861 vfs_writev+0x1aa/0x630 fs/read_write.c:934 do_writev+0x133/0x2f0 fs/read_write.c:977 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7f37021a3c19 Fixes: 1118b2049d77 ("net: tun: Fix memory leaks of napi_get_frags") Reported-by: syzbot Signed-off-by: Eric Dumazet Cc: Wang Yufen Link: https://lore.kernel.org/r/20221107180011.188437-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- drivers/net/tun.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index eb12f3136a54..7a3ab3427369 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1967,18 +1967,25 @@ drop: skb_headlen(skb)); if (unlikely(headlen > skb_headlen(skb))) { + WARN_ON_ONCE(1); + err = -ENOMEM; dev_core_stats_rx_dropped_inc(tun->dev); +napi_busy: napi_free_frags(&tfile->napi); rcu_read_unlock(); mutex_unlock(&tfile->napi_mutex); - WARN_ON(1); - return -ENOMEM; + return err; } - local_bh_disable(); - napi_gro_frags(&tfile->napi); - napi_complete(&tfile->napi); - local_bh_enable(); + if (likely(napi_schedule_prep(&tfile->napi))) { + local_bh_disable(); + napi_gro_frags(&tfile->napi); + napi_complete(&tfile->napi); + local_bh_enable(); + } else { + err = -EBUSY; + goto napi_busy; + } mutex_unlock(&tfile->napi_mutex); } else if (tfile->napi_enabled) { struct sk_buff_head *queue = &tfile->sk.sk_write_queue; -- cgit v1.2.3 From b06334919c7a068d54ba5b219c05e919d89943f7 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Nov 2022 18:14:43 +0800 Subject: net: nixge: disable napi when enable interrupts failed in nixge_open() When failed to enable interrupts in nixge_open() for opening device, napi isn't disabled. When open nixge device next time, it will reports a invalid opcode issue. Fix it. Only be compiled, not be tested. Fixes: 492caffa8a1a ("net: ethernet: nixge: Add support for National Instruments XGE netdev") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221107101443.120205-1-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ni/nixge.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index 3db4a2431741..19d043b593cc 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -900,6 +900,7 @@ static int nixge_open(struct net_device *ndev) err_rx_irq: free_irq(priv->tx_irq, ndev); err_tx_irq: + napi_disable(&priv->napi); phy_stop(phy); phy_disconnect(phy); tasklet_kill(&priv->dma_err_tasklet); -- cgit v1.2.3 From 742c60e1285ca40642e988f7e3db92232171b27d Mon Sep 17 00:00:00 2001 From: Nick Child Date: Mon, 7 Nov 2022 14:32:15 -0600 Subject: ibmveth: Reduce default tx queues to 8 Previously, the default number of transmit queues was 16. Due to resource concerns, set to 8 queues instead. Still allow the user to set more queues (max 16) if they like. Since the driver is virtualized away from the physical NIC, the purpose of multiple queues is purely to allow for parallel calls to the hypervisor. Therefore, there is no noticeable effect on performance by reducing queue count to 8. Fixes: d926793c1de9 ("ibmveth: Implement multi queue on xmit") Reported-by: Dave Taht Signed-off-by: Nick Child Link: https://lore.kernel.org/r/20221107203215.58206-1-nnac123@linux.ibm.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ibm/ibmveth.c | 3 ++- drivers/net/ethernet/ibm/ibmveth.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 3b14dc93f59d..5b96cd94dcd2 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1757,7 +1757,8 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) kobject_uevent(kobj, KOBJ_ADD); } - rc = netif_set_real_num_tx_queues(netdev, ibmveth_real_max_tx_queues()); + rc = netif_set_real_num_tx_queues(netdev, min(num_online_cpus(), + IBMVETH_DEFAULT_QUEUES)); if (rc) { netdev_dbg(netdev, "failed to set number of tx queues rc=%d\n", rc); diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h index daf6f615c03f..115d4c45aa77 100644 --- a/drivers/net/ethernet/ibm/ibmveth.h +++ b/drivers/net/ethernet/ibm/ibmveth.h @@ -100,6 +100,7 @@ static inline long h_illan_attributes(unsigned long unit_address, #define IBMVETH_MAX_BUF_SIZE (1024 * 128) #define IBMVETH_MAX_TX_BUF_SIZE (1024 * 64) #define IBMVETH_MAX_QUEUES 16U +#define IBMVETH_DEFAULT_QUEUES 8U static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 }; static int pool_count[] = { 256, 512, 256, 256, 256 }; -- cgit v1.2.3 From fed74d75277da865da9ba334d3f5d5e3e327971d Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Fri, 4 Nov 2022 11:56:05 +0100 Subject: pinctrl: mediatek: common-v2: Fix bias-disable for PULL_PU_PD_RSEL_TYPE In pinctrl-paris we're calling the .bias_set_combo() callback when we are asked to set the pin bias to either pull up/down or pull disable. On newer platforms, this callback is mtk_pinconf_bias_set_combo(), located in pinctrl-mtk-common-v2.c: this will check the "pull type" assigned to the requested pin and in case said pin's pull type is MTK_PULL_PU_PD_RSEL_TYPE, this function will set RSEL first, PUPD last, which is fine. The issue comes when we're requesting PIN_CONFIG_BIAS_DISABLE, as this does *not* require setting RSEL but only PU_PD: in this case, the arg is MTK_DISABLE (zero), which is not a supported RSEL, due to which function mtk_pinconf_bias_set_rsel() returns a failure; because of that, mtk_pinconf_bias_set_pu_pd() is never called, hence the pin bias is never set to DISABLE. To fix this issue, add a check to mtk_pinconf_bias_set_rsel(): if we are entering that function with no pullup requested and at the same time the arg is MTK_DISABLE, this means that we're trying to disable pin bias, hence it's safe to return cleanly without ever setting any RSEL register. This makes mtk_pinconf_bias_set_combo() happy, going on with setting the PU_PD registers, which is the only action to actually take to disable bias on a pin/pingroup. Fixes: fb34a9ae383a ("pinctrl: mediatek: support rsel feature") Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20221104105605.33720-1-angelogioacchino.delregno@collabora.com Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index e1ae3beb9f72..b7921b59eb7b 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c @@ -709,6 +709,9 @@ static int mtk_pinconf_bias_set_rsel(struct mtk_pinctrl *hw, { int err, rsel_val; + if (!pullup && arg == MTK_DISABLE) + return 0; + if (hw->rsel_si_unit) { /* find pin rsel_index from pin_rsel array*/ err = mtk_hw_pin_rsel_lookup(hw, desc, pullup, arg, &rsel_val); -- cgit v1.2.3 From 8c94951560ef29c455043bf2dfa2275b011edc66 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 8 Nov 2022 10:32:38 +0000 Subject: drm/i915: use i915_sg_dma_sizes() for all backends We rely on page_sizes.sg in setup_scratch_page() reporting the correct value if the underlying sgl is not contiguous, however in get_pages_internal() we are only looking at the layout of the created pages when calculating the sg_page_sizes, and not the final sgl, which could in theory be completely different. In such a situation we might incorrectly think we have a 64K scratch page, when it is actually only 4K or similar split over multiple non-contiguous entries, which could lead to broken behaviour when touching the scratch space within the padding of a 64K GTT page-table. For most of the other backends we already just call i915_sg_dma_sizes() on the final mapping, so rather just move that into __i915_gem_object_set_pages() to avoid such issues coming back to bite us later. v2: Update missing conversion in gvt Suggested-by: Tvrtko Ursulin Signed-off-by: Matthew Auld Cc: Stuart Summers Cc: Andrzej Hajda Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20221108103238.165447-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 4 +--- drivers/gpu/drm/i915/gem/i915_gem_internal.c | 5 +---- drivers/gpu/drm/i915/gem/i915_gem_object.h | 3 +-- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 7 +++---- drivers/gpu/drm/i915/gem/i915_gem_phys.c | 9 +++------ drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 3 +-- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 4 +--- drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c | 2 +- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 10 +++------- drivers/gpu/drm/i915/gvt/dmabuf.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 5 +---- drivers/gpu/drm/i915/selftests/mock_region.c | 2 +- 14 files changed, 20 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index ec6f7ae47783..1df74f7aa3dc 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -238,7 +238,6 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = to_i915(obj->base.dev); struct sg_table *sgt; - unsigned int sg_page_sizes; assert_object_held(obj); @@ -262,8 +261,7 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) (!HAS_LLC(i915) && !IS_DG1(i915))) wbinvd_on_all_cpus(); - sg_page_sizes = i915_sg_dma_sizes(sgt->sgl); - __i915_gem_object_set_pages(obj, sgt, sg_page_sizes); + __i915_gem_object_set_pages(obj, sgt); return 0; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c index 629acb403a2c..f66bcefc09ec 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c @@ -35,7 +35,6 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) struct drm_i915_private *i915 = to_i915(obj->base.dev); struct sg_table *st; struct scatterlist *sg; - unsigned int sg_page_sizes; unsigned int npages; int max_order = MAX_ORDER; unsigned int max_segment; @@ -64,7 +63,6 @@ create_st: sg = st->sgl; st->nents = 0; - sg_page_sizes = 0; do { int order = min(fls(npages) - 1, max_order); @@ -83,7 +81,6 @@ create_st: } while (1); sg_set_page(sg, page, PAGE_SIZE << order, 0); - sg_page_sizes |= PAGE_SIZE << order; st->nents++; npages -= 1 << order; @@ -105,7 +102,7 @@ create_st: goto err; } - __i915_gem_object_set_pages(obj, st, sg_page_sizes); + __i915_gem_object_set_pages(obj, st); return 0; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 6b9ecff42bb5..3db53769864c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -403,8 +403,7 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, unsigned long n); void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, - struct sg_table *pages, - unsigned int sg_page_sizes); + struct sg_table *pages); int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj); int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 16f845663ff2..05a27723ebb8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -16,8 +16,7 @@ #include "i915_gem_mman.h" void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, - struct sg_table *pages, - unsigned int sg_page_sizes) + struct sg_table *pages) { struct drm_i915_private *i915 = to_i915(obj->base.dev); unsigned long supported = RUNTIME_INFO(i915)->page_sizes; @@ -45,8 +44,8 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, obj->mm.pages = pages; - GEM_BUG_ON(!sg_page_sizes); - obj->mm.page_sizes.phys = sg_page_sizes; + obj->mm.page_sizes.phys = i915_sg_dma_sizes(pages->sgl); + GEM_BUG_ON(!obj->mm.page_sizes.phys); /* * Calculate the supported page-sizes which fit into the given diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c index 0d0e46dae559..68453572275b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c @@ -79,7 +79,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) /* We're no longer struct page backed */ obj->mem_flags &= ~I915_BO_FLAG_STRUCT_PAGE; - __i915_gem_object_set_pages(obj, st, sg->length); + __i915_gem_object_set_pages(obj, st); return 0; @@ -209,11 +209,8 @@ static int i915_gem_object_shmem_to_phys(struct drm_i915_gem_object *obj) return 0; err_xfer: - if (!IS_ERR_OR_NULL(pages)) { - unsigned int sg_page_sizes = i915_sg_dma_sizes(pages->sgl); - - __i915_gem_object_set_pages(obj, pages, sg_page_sizes); - } + if (!IS_ERR_OR_NULL(pages)) + __i915_gem_object_set_pages(obj, pages); return err; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 2f7804492cd5..9c759df700ca 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -247,7 +247,7 @@ rebuild_st: if (i915_gem_object_can_bypass_llc(obj)) obj->cache_dirty = true; - __i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl)); + __i915_gem_object_set_pages(obj, st); return 0; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index 0c70711818ed..bc9521078807 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -628,7 +628,7 @@ static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj) sg_dma_len(pages->sgl), POISON_INUSE); - __i915_gem_object_set_pages(obj, pages, obj->stolen->size); + __i915_gem_object_set_pages(obj, pages); return 0; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 2c8b2d5ae903..e4e55e3f4e41 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -815,8 +815,7 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj, GEM_BUG_ON(obj->mm.rsgt); obj->mm.rsgt = rsgt; - __i915_gem_object_set_pages(obj, &rsgt->table, - i915_sg_dma_sizes(rsgt->table.sgl)); + __i915_gem_object_set_pages(obj, &rsgt->table); } GEM_BUG_ON(bo->ttm && ((obj->base.size >> PAGE_SHIFT) < bo->ttm->num_pages)); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index ca7a388ba2bf..9348b1804d53 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -131,7 +131,6 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) const unsigned long num_pages = obj->base.size >> PAGE_SHIFT; unsigned int max_segment = i915_sg_segment_size(obj->base.dev->dev); struct sg_table *st; - unsigned int sg_page_sizes; struct page **pvec; int ret; @@ -170,8 +169,7 @@ alloc_table: if (i915_gem_object_can_bypass_llc(obj)) obj->cache_dirty = true; - sg_page_sizes = i915_sg_dma_sizes(st->sgl); - __i915_gem_object_set_pages(obj, st, sg_page_sizes); + __i915_gem_object_set_pages(obj, st); return 0; diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c index f963b8e1e37b..cbd9b624a788 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c @@ -68,7 +68,7 @@ static int huge_get_pages(struct drm_i915_gem_object *obj) if (i915_gem_gtt_prepare_pages(obj, pages)) goto err; - __i915_gem_object_set_pages(obj, pages, PAGE_SIZE); + __i915_gem_object_set_pages(obj, pages); return 0; diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 0cb99e75b0bc..beaf27e09e8a 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -136,7 +136,7 @@ static int get_huge_pages(struct drm_i915_gem_object *obj) goto err; GEM_BUG_ON(sg_page_sizes != obj->mm.page_mask); - __i915_gem_object_set_pages(obj, st, sg_page_sizes); + __i915_gem_object_set_pages(obj, st); return 0; @@ -210,7 +210,6 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj) const u64 max_len = rounddown_pow_of_two(UINT_MAX); struct sg_table *st; struct scatterlist *sg; - unsigned int sg_page_sizes; u64 rem; st = kmalloc(sizeof(*st), GFP); @@ -226,7 +225,6 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj) rem = obj->base.size; sg = st->sgl; st->nents = 0; - sg_page_sizes = 0; do { unsigned int page_size = get_largest_page_size(i915, rem); unsigned int len = min(page_size * div_u64(rem, page_size), @@ -239,8 +237,6 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj) sg_dma_len(sg) = len; sg_dma_address(sg) = page_size; - sg_page_sizes |= len; - st->nents++; rem -= len; @@ -254,7 +250,7 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj) i915_sg_trim(st); - __i915_gem_object_set_pages(obj, st, sg_page_sizes); + __i915_gem_object_set_pages(obj, st); return 0; } @@ -286,7 +282,7 @@ static int fake_get_huge_pages_single(struct drm_i915_gem_object *obj) sg_dma_len(sg) = obj->base.size; sg_dma_address(sg) = page_size; - __i915_gem_object_set_pages(obj, st, sg->length); + __i915_gem_object_set_pages(obj, st); return 0; #undef GFP diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 01e54b45c5c1..355f1c0e8664 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -88,7 +88,7 @@ static int vgpu_gem_get_pages( sg_dma_address(sg) = dma_addr; } - __i915_gem_object_set_pages(obj, st, PAGE_SIZE); + __i915_gem_object_set_pages(obj, st); out: if (ret) { dma_addr_t dma_addr; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 27c733b00976..eae7d947d7de 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -61,7 +61,6 @@ static int fake_get_pages(struct drm_i915_gem_object *obj) #define PFN_BIAS 0x1000 struct sg_table *pages; struct scatterlist *sg; - unsigned int sg_page_sizes; typeof(obj->base.size) rem; pages = kmalloc(sizeof(*pages), GFP); @@ -74,7 +73,6 @@ static int fake_get_pages(struct drm_i915_gem_object *obj) return -ENOMEM; } - sg_page_sizes = 0; rem = obj->base.size; for (sg = pages->sgl; sg; sg = sg_next(sg)) { unsigned long len = min_t(typeof(rem), rem, BIT(31)); @@ -83,13 +81,12 @@ static int fake_get_pages(struct drm_i915_gem_object *obj) sg_set_page(sg, pfn_to_page(PFN_BIAS), len, 0); sg_dma_address(sg) = page_to_phys(sg_page(sg)); sg_dma_len(sg) = len; - sg_page_sizes |= len; rem -= len; } GEM_BUG_ON(rem); - __i915_gem_object_set_pages(obj, pages, sg_page_sizes); + __i915_gem_object_set_pages(obj, pages); return 0; #undef GFP diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c index bac21fe84ca5..6324eb32d4dd 100644 --- a/drivers/gpu/drm/i915/selftests/mock_region.c +++ b/drivers/gpu/drm/i915/selftests/mock_region.c @@ -41,7 +41,7 @@ static int mock_region_get_pages(struct drm_i915_gem_object *obj) } pages = &obj->mm.rsgt->table; - __i915_gem_object_set_pages(obj, pages, i915_sg_dma_sizes(pages->sgl)); + __i915_gem_object_set_pages(obj, pages); return 0; -- cgit v1.2.3 From 7a58b8d6021426b796eebfae80983374d9a80a75 Mon Sep 17 00:00:00 2001 From: Duoming Zhou Date: Sun, 18 Sep 2022 11:33:12 +0800 Subject: usb: chipidea: fix deadlock in ci_otg_del_timer There is a deadlock in ci_otg_del_timer(), the process is shown below: (thread 1) | (thread 2) ci_otg_del_timer() | ci_otg_hrtimer_func() ... | spin_lock_irqsave() //(1) | ... ... | hrtimer_cancel() | spin_lock_irqsave() //(2) (block forever) We hold ci->lock in position (1) and use hrtimer_cancel() to wait ci_otg_hrtimer_func() to stop, but ci_otg_hrtimer_func() also need ci->lock in position (2). As a result, the hrtimer_cancel() in ci_otg_del_timer() will be blocked forever. This patch extracts hrtimer_cancel() from the protection of spin_lock_irqsave() in order that the ci_otg_hrtimer_func() could obtain the ci->lock. What`s more, there will be no race happen. Because the "next_timer" is always under the protection of spin_lock_irqsave() and we only check whether "next_timer" equals to NUM_OTG_FSM_TIMERS in the following code. Fixes: 3a316ec4c91c ("usb: chipidea: use hrtimer for otg fsm timers") Cc: stable Signed-off-by: Duoming Zhou Link: https://lore.kernel.org/r/20220918033312.94348-1-duoming@zju.edu.cn Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/otg_fsm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index ada78daba6df..c17516c29b63 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -256,8 +256,10 @@ static void ci_otg_del_timer(struct ci_hdrc *ci, enum otg_fsm_timer t) ci->enabled_otg_timer_bits &= ~(1 << t); if (ci->next_otg_timer == t) { if (ci->enabled_otg_timer_bits == 0) { + spin_unlock_irqrestore(&ci->lock, flags); /* No enabled timers after delete it */ hrtimer_cancel(&ci->otg_fsm_hrtimer); + spin_lock_irqsave(&ci->lock, flags); ci->next_otg_timer = NUM_OTG_FSM_TIMERS; } else { /* Find the next timer */ -- cgit v1.2.3 From 9d5333c931347005352d5b8beaa43528c94cfc9c Mon Sep 17 00:00:00 2001 From: Li Jun Date: Wed, 26 Oct 2022 15:07:49 -0400 Subject: usb: cdns3: host: fix endless superspeed hub port reset When usb 3.0 hub connect with one USB 2.0 device and NO USB 3.0 device, some usb hub reports endless port reset message. [ 190.324169] usb 2-1: new SuperSpeed USB device number 88 using xhci-hcd [ 190.352834] hub 2-1:1.0: USB hub found [ 190.356995] hub 2-1:1.0: 4 ports detected [ 190.700056] usb 2-1: USB disconnect, device number 88 [ 192.472139] usb 2-1: new SuperSpeed USB device number 89 using xhci-hcd [ 192.500820] hub 2-1:1.0: USB hub found [ 192.504977] hub 2-1:1.0: 4 ports detected [ 192.852066] usb 2-1: USB disconnect, device number 89 The reason is the runtime pm state of USB2.0 port is active and USB 3.0 port is suspend, so parent device is active state. cat /sys/bus/platform/devices/5b110000.usb/5b130000.usb/xhci-hcd.1.auto/usb2/power/runtime_status suspended cat /sys/bus/platform/devices/5b110000.usb/5b130000.usb/xhci-hcd.1.auto/usb1/power/runtime_status active cat /sys/bus/platform/devices/5b110000.usb/5b130000.usb/xhci-hcd.1.auto/power/runtime_status active cat /sys/bus/platform/devices/5b110000.usb/5b130000.usb/power/runtime_status active So xhci_cdns3_suspend_quirk() have not called. U3 configure is not applied. move U3 configure into host start. Reinit again in resume function in case controller power lost during suspend. Cc: stable@vger.kernel.org 5.10 Signed-off-by: Li Jun Signed-off-by: Frank Li Reviewed-by: Peter Chen Acked-by: Alexander Stein Link: https://lore.kernel.org/r/20221026190749.2280367-1-Frank.Li@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/cdns3/host.c | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c index 9643b905e2d8..6164fc4c96a4 100644 --- a/drivers/usb/cdns3/host.c +++ b/drivers/usb/cdns3/host.c @@ -24,11 +24,37 @@ #define CFG_RXDET_P3_EN BIT(15) #define LPM_2_STB_SWITCH_EN BIT(25) -static int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd); +static void xhci_cdns3_plat_start(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + u32 value; + + /* set usbcmd.EU3S */ + value = readl(&xhci->op_regs->command); + value |= CMD_PM_INDEX; + writel(value, &xhci->op_regs->command); + + if (hcd->regs) { + value = readl(hcd->regs + XECP_AUX_CTRL_REG1); + value |= CFG_RXDET_P3_EN; + writel(value, hcd->regs + XECP_AUX_CTRL_REG1); + + value = readl(hcd->regs + XECP_PORT_CAP_REG); + value |= LPM_2_STB_SWITCH_EN; + writel(value, hcd->regs + XECP_PORT_CAP_REG); + } +} + +static int xhci_cdns3_resume_quirk(struct usb_hcd *hcd) +{ + xhci_cdns3_plat_start(hcd); + return 0; +} static const struct xhci_plat_priv xhci_plat_cdns3_xhci = { .quirks = XHCI_SKIP_PHY_INIT | XHCI_AVOID_BEI, - .suspend_quirk = xhci_cdns3_suspend_quirk, + .plat_start = xhci_cdns3_plat_start, + .resume_quirk = xhci_cdns3_resume_quirk, }; static int __cdns_host_init(struct cdns *cdns) @@ -90,32 +116,6 @@ err1: return ret; } -static int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd) -{ - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - u32 value; - - if (pm_runtime_status_suspended(hcd->self.controller)) - return 0; - - /* set usbcmd.EU3S */ - value = readl(&xhci->op_regs->command); - value |= CMD_PM_INDEX; - writel(value, &xhci->op_regs->command); - - if (hcd->regs) { - value = readl(hcd->regs + XECP_AUX_CTRL_REG1); - value |= CFG_RXDET_P3_EN; - writel(value, hcd->regs + XECP_AUX_CTRL_REG1); - - value = readl(hcd->regs + XECP_PORT_CAP_REG); - value |= LPM_2_STB_SWITCH_EN; - writel(value, hcd->regs + XECP_PORT_CAP_REG); - } - - return 0; -} - static void cdns_host_exit(struct cdns *cdns) { kfree(cdns->xhci_plat_data); -- cgit v1.2.3 From f002f45a00ee14214d96b18b9a555fe2c56afb20 Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Tue, 8 Nov 2022 15:45:03 +0800 Subject: mmc: sdhci-esdhc-imx: use the correct host caps for MMC_CAP_8_BIT_DATA MMC_CAP_8_BIT_DATA belongs to struct mmc_host, not struct sdhci_host. So correct it here. Fixes: 1ed5c3b22fc7 ("mmc: sdhci-esdhc-imx: Propagate ESDHC_FLAG_HS400* only on 8bit bus") Signed-off-by: Haibo Chen Cc: stable@vger.kernel.org Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1667893503-20583-1-git-send-email-haibo.chen@nxp.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 89225faa242a..31ea0a2fce35 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1672,14 +1672,14 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; - if (host->caps & MMC_CAP_8_BIT_DATA && + if (host->mmc->caps & MMC_CAP_8_BIT_DATA && imx_data->socdata->flags & ESDHC_FLAG_HS400) host->mmc->caps2 |= MMC_CAP2_HS400; if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; - if (host->caps & MMC_CAP_8_BIT_DATA && + if (host->mmc->caps & MMC_CAP_8_BIT_DATA && imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { host->mmc->caps2 |= MMC_CAP2_HS400_ES; host->mmc_host_ops.hs400_enhanced_strobe = -- cgit v1.2.3 From a931237cbea256aff13bb403da13a97b2d1605d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 8 Nov 2022 14:19:49 +0200 Subject: serial: 8250: Fall back to non-DMA Rx if IIR_RDI occurs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DW UART sometimes triggers IIR_RDI during DMA Rx when IIR_RX_TIMEOUT should have been triggered instead. Since IIR_RDI has higher priority than IIR_RX_TIMEOUT, this causes the Rx to hang into interrupt loop. The problem seems to occur at least with some combinations of small-sized transfers (I've reproduced the problem on Elkhart Lake PSE UARTs). If there's already an on-going Rx DMA and IIR_RDI triggers, fall graciously back to non-DMA Rx. That is, behave as if IIR_RX_TIMEOUT had occurred. 8250_omap already considers IIR_RDI similar to this change so its nothing unheard of. Fixes: 75df022b5f89 ("serial: 8250_dma: Fix RX handling") Cc: Co-developed-by: Srikanth Thokala Signed-off-by: Srikanth Thokala Co-developed-by: Aman Kumar Signed-off-by: Aman Kumar Signed-off-by: Ilpo Järvinen Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221108121952.5497-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index fe8662cd9402..92dd18716169 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1897,6 +1897,10 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status); static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) { switch (iir & 0x3f) { + case UART_IIR_RDI: + if (!up->dma->rx_running) + break; + fallthrough; case UART_IIR_RX_TIMEOUT: serial8250_rx_dma_flush(up); fallthrough; -- cgit v1.2.3 From 1bfcbe5805d0cfc83c3544dcd01e0a282c1f6790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 8 Nov 2022 14:19:50 +0200 Subject: serial: 8250_lpss: Configure DMA also w/o DMA filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the platform doesn't use DMA device filter (as is the case with Elkhart Lake), whole lpss8250_dma_setup() setup is skipped. This results in skipping also *_maxburst setup which is undesirable. Refactor lpss8250_dma_setup() to configure DMA even if filter is not setup. Cc: stable Signed-off-by: Ilpo Järvinen Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221108121952.5497-3-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpss.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 44cc755b1a29..7d9cddbfef40 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -277,8 +277,13 @@ static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port struct dw_dma_slave *rx_param, *tx_param; struct device *dev = port->port.dev; - if (!lpss->dma_param.dma_dev) + if (!lpss->dma_param.dma_dev) { + dma = port->dma; + if (dma) + goto out_configuration_only; + return 0; + } rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL); if (!rx_param) @@ -289,16 +294,18 @@ static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port return -ENOMEM; *rx_param = lpss->dma_param; - dma->rxconf.src_maxburst = lpss->dma_maxburst; - *tx_param = lpss->dma_param; - dma->txconf.dst_maxburst = lpss->dma_maxburst; dma->fn = lpss8250_dma_filter; dma->rx_param = rx_param; dma->tx_param = tx_param; port->dma = dma; + +out_configuration_only: + dma->rxconf.src_maxburst = lpss->dma_maxburst; + dma->txconf.dst_maxburst = lpss->dma_maxburst; + return 0; } -- cgit v1.2.3 From 7090abd6ad0610a144523ce4ffcb8560909bf2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 8 Nov 2022 14:19:51 +0200 Subject: serial: 8250_lpss: Use 16B DMA burst with Elkhart Lake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configure DMA to use 16B burst size with Elkhart Lake. This makes the bus use more efficient and works around an issue which occurs with the previously used 1B. The fix was initially developed by Srikanth Thokala and Aman Kumar. This together with the previous config change is the cleaned up version of the original fix. Fixes: 0a9410b981e9 ("serial: 8250_lpss: Enable DMA on Intel Elkhart Lake") Cc: # serial: 8250_lpss: Configure DMA also w/o DMA filter Reported-by: Wentong Wu Signed-off-by: Ilpo Järvinen Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221108121952.5497-4-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpss.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 7d9cddbfef40..0e43bdfb7459 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -174,6 +174,8 @@ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port) */ up->dma = dma; + lpss->dma_maxburst = 16; + port->set_termios = dw8250_do_set_termios; return 0; -- cgit v1.2.3 From 1980860e0c8299316cddaf0992dd9e1258ec9d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 8 Nov 2022 14:19:52 +0200 Subject: serial: 8250: Flush DMA Rx on RLSI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returning true from handle_rx_dma() without flushing DMA first creates a data ordering hazard. If DMA Rx has handled any character at the point when RLSI occurs, the non-DMA path handles any pending characters jumping them ahead of those characters that are pending under DMA. Fixes: 75df022b5f89 ("serial: 8250_dma: Fix RX handling") Cc: Signed-off-by: Ilpo Järvinen Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221108121952.5497-5-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 92dd18716169..388172289627 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1901,10 +1901,9 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) if (!up->dma->rx_running) break; fallthrough; + case UART_IIR_RLSI: case UART_IIR_RX_TIMEOUT: serial8250_rx_dma_flush(up); - fallthrough; - case UART_IIR_RLSI: return true; } return up->dma->rx_dma(up); -- cgit v1.2.3 From 181135bb20dcb184edd89817831b888eb8132741 Mon Sep 17 00:00:00 2001 From: Nicolas Dumazet Date: Wed, 9 Nov 2022 13:29:46 +0100 Subject: usb: add NO_LPM quirk for Realforce 87U Keyboard Before adding this quirk, this (mechanical keyboard) device would not be recognized, logging: new full-speed USB device number 56 using xhci_hcd unable to read config index 0 descriptor/start: -32 chopping to 0 config(s) It would take dozens of plugging/unpuggling cycles for the keyboard to be recognized. Keyboard seems to simply work after applying this quirk. This issue had been reported by users in two places already ([1], [2]) but nobody tried upstreaming a patch yet. After testing I believe their suggested fix (DELAY_INIT + NO_LPM + DEVICE_QUALIFIER) was probably a little overkill. I assume this particular combination was tested because it had been previously suggested in [3], but only NO_LPM seems sufficient for this device. [1]: https://qiita.com/float168/items/fed43d540c8e2201b543 [2]: https://blog.kostic.dev/posts/making-the-realforce-87ub-work-with-usb30-on-Ubuntu/ [3]: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1678477 Cc: stable@vger.kernel.org Signed-off-by: Nicolas Dumazet Link: https://lore.kernel.org/r/20221109122946.706036-1-ndumazet@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 0722d2131305..079e183cf3bf 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -362,6 +362,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM }, { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, + /* Realforce 87U Keyboard */ + { USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, -- cgit v1.2.3 From d7ac8dca938cd60cf7bd9a89a229a173c6bcba87 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Fri, 28 Oct 2022 13:14:15 -0700 Subject: nvme: quiet user passthrough command errors The driver is spamming the kernel logs for entirely harmless errors from user space submitting unsupported commands. Just silence the errors. The application has direct access to command status, so there's no need to log these. And since every passthrough command now uses the quiet flag, move the setting to the common initializer. Signed-off-by: Keith Busch Reviewed-by: Alan Adamson Reviewed-by: Jens Axboe Reviewed-by: Kanchan Joshi Reviewed-by: Chaitanya Kulkarni Reviewed-by: Daniel Wagner Tested-by: Alan Adamson Signed-off-by: Christoph Hellwig --- drivers/nvme/host/core.c | 3 +-- drivers/nvme/host/pci.c | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index dc4220600585..da55ce45ac70 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -675,6 +675,7 @@ void nvme_init_request(struct request *req, struct nvme_command *cmd) if (req->mq_hctx->type == HCTX_TYPE_POLL) req->cmd_flags |= REQ_POLLED; nvme_clear_nvme_request(req); + req->rq_flags |= RQF_QUIET; memcpy(nvme_req(req)->cmd, cmd, sizeof(*cmd)); } EXPORT_SYMBOL_GPL(nvme_init_request); @@ -1037,7 +1038,6 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, goto out; } - req->rq_flags |= RQF_QUIET; ret = nvme_execute_rq(req, at_head); if (result && ret >= 0) *result = nvme_req(req)->result; @@ -1227,7 +1227,6 @@ static void nvme_keep_alive_work(struct work_struct *work) rq->timeout = ctrl->kato * HZ; rq->end_io = nvme_keep_alive_end_io; rq->end_io_data = ctrl; - rq->rq_flags |= RQF_QUIET; blk_execute_rq_nowait(rq, false); } diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 31e577b01257..02b5578773a1 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1436,7 +1436,6 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) abort_req->end_io = abort_endio; abort_req->end_io_data = NULL; - abort_req->rq_flags |= RQF_QUIET; blk_execute_rq_nowait(abort_req, false); /* @@ -2490,7 +2489,6 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode) req->end_io_data = nvmeq; init_completion(&nvmeq->delete_done); - req->rq_flags |= RQF_QUIET; blk_execute_rq_nowait(req, false); return 0; } -- cgit v1.2.3 From becc4cac309dc867571f0080fde4426a6c2222e0 Mon Sep 17 00:00:00 2001 From: Aleksandr Miloserdov Date: Wed, 26 Oct 2022 12:31:33 +0400 Subject: nvmet: fix memory leak in nvmet_subsys_attr_model_store_locked Since model_number is allocated before it needs to be freed before kmemdump_nul. Reviewed-by: Konstantin Shelekhin Reviewed-by: Dmitriy Bogdanov Signed-off-by: Aleksandr Miloserdov Reviewed-by: Sagi Grimberg Signed-off-by: Christoph Hellwig --- drivers/nvme/target/configfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c index 9443ee1d4ae3..d0b9eea15ff8 100644 --- a/drivers/nvme/target/configfs.c +++ b/drivers/nvme/target/configfs.c @@ -1215,6 +1215,7 @@ static ssize_t nvmet_subsys_attr_model_store_locked(struct nvmet_subsys *subsys, const char *page, size_t count) { int pos = 0, len; + char *val; if (subsys->subsys_discovered) { pr_err("Can't set model number. %s is already assigned\n", @@ -1237,9 +1238,11 @@ static ssize_t nvmet_subsys_attr_model_store_locked(struct nvmet_subsys *subsys, return -EINVAL; } - subsys->model_number = kmemdup_nul(page, len, GFP_KERNEL); - if (!subsys->model_number) + val = kmemdup_nul(page, len, GFP_KERNEL); + if (!val) return -ENOMEM; + kfree(subsys->model_number); + subsys->model_number = val; return count; } -- cgit v1.2.3 From e65fdf530f55c5e387db14470a59a399faa29613 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Wed, 9 Nov 2022 05:29:57 +0200 Subject: nvmet: fix a memory leak We need to also free the dhchap_ctrl_secret when releasing nvmet_host. kmemleak complaint: -- unreferenced object 0xffff99b1cbca5140 (size 64): comm "check", pid 4864, jiffies 4305092436 (age 2913.583s) hex dump (first 32 bytes): 44 48 48 43 2d 31 3a 30 30 3a 65 36 2b 41 63 44 DHHC-1:00:e6+AcD 39 76 47 4d 52 57 59 78 67 54 47 44 51 59 47 78 9vGMRWYxgTGDQYGx backtrace: [<00000000c07d369d>] kstrdup+0x2e/0x60 [<000000001372171c>] 0xffffffffc0cceec6 [<0000000010dbf50b>] 0xffffffffc0cc6783 [<000000007465e93c>] configfs_write_iter+0xb1/0x120 [<0000000039c23f62>] vfs_write+0x2be/0x3c0 [<000000002da4351c>] ksys_write+0x5f/0xe0 [<00000000d5011e32>] do_syscall_64+0x38/0x90 [<00000000503870cf>] entry_SYSCALL_64_after_hwframe+0x63/0xcd Fixes: db1312dd9548 ("nvmet: implement basic In-Band Authentication") Signed-off-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/target/configfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c index d0b9eea15ff8..6a2816f3b4e8 100644 --- a/drivers/nvme/target/configfs.c +++ b/drivers/nvme/target/configfs.c @@ -1839,6 +1839,7 @@ static void nvmet_host_release(struct config_item *item) #ifdef CONFIG_NVME_TARGET_AUTH kfree(host->dhchap_secret); + kfree(host->dhchap_ctrl_secret); #endif kfree(host); } -- cgit v1.2.3 From d38a648d2d6cc7bee11c6f533ff9426a00c2a74c Mon Sep 17 00:00:00 2001 From: M Chetan Kumar Date: Mon, 7 Nov 2022 13:04:49 +0530 Subject: net: wwan: iosm: fix memory leak in ipc_pcie_read_bios_cfg ipc_pcie_read_bios_cfg() is using the acpi_evaluate_dsm() to obtain the wwan power state configuration from BIOS but is not freeing the acpi_object. The acpi_evaluate_dsm() returned acpi_object to be freed. Free the acpi_object after use. Fixes: 7e98d785ae61 ("net: iosm: entry point") Signed-off-by: M Chetan Kumar Signed-off-by: David S. Miller --- drivers/net/wwan/iosm/iosm_ipc_pcie.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c index 31f57b986df2..97cb6846c6ae 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c +++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c @@ -232,6 +232,7 @@ static void ipc_pcie_config_init(struct iosm_pcie *ipc_pcie) */ static enum ipc_pcie_sleep_state ipc_pcie_read_bios_cfg(struct device *dev) { + enum ipc_pcie_sleep_state sleep_state = IPC_PCIE_D0L12; union acpi_object *object; acpi_handle handle_acpi; @@ -242,12 +243,16 @@ static enum ipc_pcie_sleep_state ipc_pcie_read_bios_cfg(struct device *dev) } object = acpi_evaluate_dsm(handle_acpi, &wwan_acpi_guid, 0, 3, NULL); + if (!object) + goto default_ret; + + if (object->integer.value == 3) + sleep_state = IPC_PCIE_D3L2; - if (object && object->integer.value == 3) - return IPC_PCIE_D3L2; + kfree(object); default_ret: - return IPC_PCIE_D0L12; + return sleep_state; } static int ipc_pcie_probe(struct pci_dev *pci, -- cgit v1.2.3 From 035e3befc191347331dd2530c3686e05a8acfbb2 Mon Sep 17 00:00:00 2001 From: M Chetan Kumar Date: Mon, 7 Nov 2022 13:05:02 +0530 Subject: net: wwan: iosm: fix driver not working with INTEL_IOMMU disabled With INTEL_IOMMU disable config or by forcing intel_iommu=off from grub some of the features of IOSM driver like browsing, flashing & coredump collection is not working. When driver calls DMA API - dma_map_single() for tx transfers. It is resulting in dma mapping error. Set the device DMA addressing capabilities using dma_set_mask() and remove the INTEL_IOMMU dependency in kconfig so that driver follows the platform config either INTEL_IOMMU enable or disable. Fixes: f7af616c632e ("net: iosm: infrastructure") Signed-off-by: M Chetan Kumar Signed-off-by: David S. Miller --- drivers/net/wwan/Kconfig | 2 +- drivers/net/wwan/iosm/iosm_ipc_pcie.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig index 3486ffe94ac4..ac4d73b5626f 100644 --- a/drivers/net/wwan/Kconfig +++ b/drivers/net/wwan/Kconfig @@ -94,7 +94,7 @@ config RPMSG_WWAN_CTRL config IOSM tristate "IOSM Driver for Intel M.2 WWAN Device" - depends on INTEL_IOMMU + depends on PCI select NET_DEVLINK select RELAY if WWAN_DEBUGFS help diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c index 97cb6846c6ae..d3d34d1c4704 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c +++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c @@ -259,6 +259,7 @@ static int ipc_pcie_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { struct iosm_pcie *ipc_pcie = kzalloc(sizeof(*ipc_pcie), GFP_KERNEL); + int ret; pr_debug("Probing device 0x%X from the vendor 0x%X", pci_id->device, pci_id->vendor); @@ -291,6 +292,12 @@ static int ipc_pcie_probe(struct pci_dev *pci, goto pci_enable_fail; } + ret = dma_set_mask(ipc_pcie->dev, DMA_BIT_MASK(64)); + if (ret) { + dev_err(ipc_pcie->dev, "Could not set PCI DMA mask: %d", ret); + return ret; + } + ipc_pcie_config_aspm(ipc_pcie); dev_dbg(ipc_pcie->dev, "PCIe device enabled."); -- cgit v1.2.3 From 02d2d2ea4a3bc2391f6ac31f6854da83e8a63829 Mon Sep 17 00:00:00 2001 From: M Chetan Kumar Date: Mon, 7 Nov 2022 13:05:13 +0530 Subject: net: wwan: iosm: fix invalid mux header type Data stall seen during peak DL throughput test & packets are dropped by mux layer due to invalid header type in datagram. During initlization Mux aggregration protocol is set to default UL/DL size and TD count of Mux lite protocol. This configuration mismatch between device and driver is resulting in data stall/packet drops. Override the UL/DL size and TD count for Mux aggregation protocol. Fixes: 1f52d7b62285 ("net: wwan: iosm: Enable M.2 7360 WWAN card support") Signed-off-by: M Chetan Kumar Signed-off-by: David S. Miller --- drivers/net/wwan/iosm/iosm_ipc_imem_ops.c | 8 ++++++++ drivers/net/wwan/iosm/iosm_ipc_mux.h | 1 + 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c index b7f9237dedf7..66b90cc4c346 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c @@ -91,6 +91,14 @@ void ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem, } ipc_chnl_cfg_get(&chnl_cfg, ipc_imem->nr_of_channels); + + if (ipc_imem->mmio->mux_protocol == MUX_AGGREGATION && + ipc_imem->nr_of_channels == IPC_MEM_IP_CHL_ID_0) { + chnl_cfg.ul_nr_of_entries = IPC_MEM_MAX_TDS_MUX_AGGR_UL; + chnl_cfg.dl_nr_of_entries = IPC_MEM_MAX_TDS_MUX_AGGR_DL; + chnl_cfg.dl_buf_size = IPC_MEM_MAX_ADB_BUF_SIZE; + } + ipc_imem_channel_init(ipc_imem, IPC_CTYPE_WWAN, chnl_cfg, IRQ_MOD_OFF); diff --git a/drivers/net/wwan/iosm/iosm_ipc_mux.h b/drivers/net/wwan/iosm/iosm_ipc_mux.h index cd9d74cc097f..9968bb885c1f 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_mux.h +++ b/drivers/net/wwan/iosm/iosm_ipc_mux.h @@ -10,6 +10,7 @@ #define IPC_MEM_MAX_UL_DG_ENTRIES 100 #define IPC_MEM_MAX_TDS_MUX_AGGR_UL 60 +#define IPC_MEM_MAX_TDS_MUX_AGGR_DL 60 #define IPC_MEM_MAX_ADB_BUF_SIZE (16 * 1024) #define IPC_MEM_MAX_UL_ADB_BUF_SIZE IPC_MEM_MAX_ADB_BUF_SIZE -- cgit v1.2.3 From 980ec04a88c9f0046c1da65833fb77b2ffa34b04 Mon Sep 17 00:00:00 2001 From: M Chetan Kumar Date: Mon, 7 Nov 2022 13:05:24 +0530 Subject: net: wwan: iosm: fix kernel test robot reported errors Include linux/vmalloc.h in iosm_ipc_coredump.c & iosm_ipc_devlink.c to resolve kernel test robot errors. Reported-by: kernel test robot Signed-off-by: M Chetan Kumar Signed-off-by: David S. Miller --- drivers/net/wwan/iosm/iosm_ipc_coredump.c | 1 + drivers/net/wwan/iosm/iosm_ipc_devlink.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wwan/iosm/iosm_ipc_coredump.c b/drivers/net/wwan/iosm/iosm_ipc_coredump.c index 9acd87724c9d..26ca30476f40 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_coredump.c +++ b/drivers/net/wwan/iosm/iosm_ipc_coredump.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2020-2021 Intel Corporation. */ +#include #include "iosm_ipc_coredump.h" diff --git a/drivers/net/wwan/iosm/iosm_ipc_devlink.c b/drivers/net/wwan/iosm/iosm_ipc_devlink.c index 17da85a8f337..2fe724d623c0 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_devlink.c +++ b/drivers/net/wwan/iosm/iosm_ipc_devlink.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2020-2021 Intel Corporation. */ +#include #include "iosm_ipc_chnl_cfg.h" #include "iosm_ipc_coredump.h" -- cgit v1.2.3 From f352262f727215553879705bacbcb208979f3eff Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 8 Nov 2022 17:06:19 +0000 Subject: drm/panfrost: Split io-pgtable requests properly Although we don't use 1GB block mappings, we still need to split map/unmap requests at 1GB boundaries to match what io-pgtable expects. Fix that, and add some explanation to make sense of it all. Fixes: 3740b081795a ("drm/panfrost: Update io-pgtable API") Reported-by: Dmitry Osipenko Signed-off-by: Robin Murphy Tested-by: Dmitry Osipenko Reviewed-by: Steven Price Signed-off-by: Steven Price Link: https://patchwork.freedesktop.org/patch/msgid/49e54bb4019cd06e01549b106d7ac37c3d182cd3.1667927179.git.robin.murphy@arm.com --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index e246d914e7f6..4e83a1891f3e 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -250,13 +250,22 @@ void panfrost_mmu_reset(struct panfrost_device *pfdev) static size_t get_pgsize(u64 addr, size_t size, size_t *count) { + /* + * io-pgtable only operates on multiple pages within a single table + * entry, so we need to split at boundaries of the table size, i.e. + * the next block size up. The distance from address A to the next + * boundary of block size B is logically B - A % B, but in unsigned + * two's complement where B is a power of two we get the equivalence + * B - A % B == (B - A) % B == (n * B - A) % B, and choose n = 0 :) + */ size_t blk_offset = -addr % SZ_2M; if (blk_offset || size < SZ_2M) { *count = min_not_zero(blk_offset, size) / SZ_4K; return SZ_4K; } - *count = size / SZ_2M; + blk_offset = -addr % SZ_1G ?: SZ_1G; + *count = min(blk_offset, size) / SZ_2M; return SZ_2M; } -- cgit v1.2.3 From 0fc801f8018000c8e64a275a20cb1da7c54e46df Mon Sep 17 00:00:00 2001 From: Mushahid Hussain Date: Mon, 10 Oct 2022 21:57:20 +0500 Subject: speakup: fix a segfault caused by switching consoles This patch fixes a segfault by adding a null check on synth in speakup_con_update(). The segfault can be reproduced as follows: - Login into a text console - Load speakup and speakup_soft modules - Remove speakup_soft - Switch to a graphics console This is caused by lack of a null check on `synth` in speakup_con_update(). Here's the sequence that causes the segfault: - When we remove the speakup_soft, synth_release() sets the synth to null. - After that, when we change the virtual console to graphics console, vt_notifier_call() is fired, which then calls speakup_con_update(). - Inside speakup_con_update() there's no null check on synth, so it calls synth_printf(). - Inside synth_printf(), synth_buffer_add() and synth_start(), both access synth, when it is null and causing a segfault. Therefore adding a null check on synth solves the issue. Fixes: 2610df41489f ("staging: speakup: Add pause command used on switching to graphical mode") Cc: stable Signed-off-by: Mushahid Hussain Signed-off-by: Samuel Thibault Link: https://lore.kernel.org/r/20221010165720.397042-1-mushi.shar@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/accessibility/speakup/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c index f52265293482..73db0cb44fc7 100644 --- a/drivers/accessibility/speakup/main.c +++ b/drivers/accessibility/speakup/main.c @@ -1778,7 +1778,7 @@ static void speakup_con_update(struct vc_data *vc) { unsigned long flags; - if (!speakup_console[vc->vc_num] || spk_parked) + if (!speakup_console[vc->vc_num] || spk_parked || !synth) return; if (!spin_trylock_irqsave(&speakup_info.spinlock, flags)) /* Speakup output, discard */ -- cgit v1.2.3 From 92ca969ff8815f3feef2645199bd39bf594e5eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= Date: Mon, 17 Oct 2022 15:09:36 +0700 Subject: speakup: replace utils' u_char with unsigned char MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/accessibility/speakup/utils.h will be used to compile host tool to generate metadata. "u_char" is a non-standard type, which is defined to "unsigned char" on glibc but not defined by some libc, e.g. musl. Let's replace "u_char" with "unsigned char" Signed-off-by: Đoàn Trần Công Danh Reviewed-by: Samuel Thibault Cc: stable Link: https://lore.kernel.org/r/b75743026aaee2d81efe3d7f2e8fa47f7d0b8ea7.1665736571.git.congdanhqx@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/accessibility/speakup/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accessibility/speakup/utils.h b/drivers/accessibility/speakup/utils.h index 4bf2ee8ac246..4ce9a12f7664 100644 --- a/drivers/accessibility/speakup/utils.h +++ b/drivers/accessibility/speakup/utils.h @@ -54,7 +54,7 @@ static inline int oops(const char *msg, const char *info) static inline struct st_key *hash_name(char *name) { - u_char *pn = (u_char *)name; + unsigned char *pn = (unsigned char *)name; int hash = 0; while (*pn) { -- cgit v1.2.3 From a830a15678593948f3271a5a398c9b67d8beedb9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Oct 2022 00:33:27 +0300 Subject: drm: rcar-du: Fix Kconfig dependency between RCAR_DU and RCAR_MIPI_DSI When the R-Car MIPI DSI driver was added, it was a standalone encoder driver without any dependency to or from the R-Car DU driver. Commit 957fe62d7d15 ("drm: rcar-du: Fix DSI enable & disable sequence") then added a direct call from the DU driver to the MIPI DSI driver, without updating Kconfig to take the new dependency into account. Fix it the same way that the LVDS encoder is handled. Fixes: 957fe62d7d15 ("drm: rcar-du: Fix DSI enable & disable sequence") Reported-by: kernel test robot Reviewed-by: Tomi Valkeinen Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/Kconfig | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index c959e8c6be7d..fd2c2eaee26b 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -44,13 +44,18 @@ config DRM_RCAR_LVDS select OF_FLATTREE select OF_OVERLAY -config DRM_RCAR_MIPI_DSI - tristate "R-Car DU MIPI DSI Encoder Support" - depends on DRM && DRM_BRIDGE && OF - select DRM_MIPI_DSI +config DRM_RCAR_USE_MIPI_DSI + bool "R-Car DU MIPI DSI Encoder Support" + depends on DRM_BRIDGE && OF + default DRM_RCAR_DU help Enable support for the R-Car Display Unit embedded MIPI DSI encoders. +config DRM_RCAR_MIPI_DSI + def_tristate DRM_RCAR_DU + depends on DRM_RCAR_USE_MIPI_DSI + select DRM_MIPI_DSI + config DRM_RCAR_VSP bool "R-Car DU VSP Compositor Support" if ARM default y if ARM64 -- cgit v1.2.3 From e5b0d06d9b10f5f43101bd6598b076c347f9295f Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Fri, 4 Nov 2022 18:58:49 +0100 Subject: misc/vmw_vmci: fix an infoleak in vmci_host_do_receive_datagram() `struct vmci_event_qp` allocated by qp_notify_peer() contains padding, which may carry uninitialized data to the userspace, as observed by KMSAN: BUG: KMSAN: kernel-infoleak in instrument_copy_to_user ./include/linux/instrumented.h:121 instrument_copy_to_user ./include/linux/instrumented.h:121 _copy_to_user+0x5f/0xb0 lib/usercopy.c:33 copy_to_user ./include/linux/uaccess.h:169 vmci_host_do_receive_datagram drivers/misc/vmw_vmci/vmci_host.c:431 vmci_host_unlocked_ioctl+0x33d/0x43d0 drivers/misc/vmw_vmci/vmci_host.c:925 vfs_ioctl fs/ioctl.c:51 ... Uninit was stored to memory at: kmemdup+0x74/0xb0 mm/util.c:131 dg_dispatch_as_host drivers/misc/vmw_vmci/vmci_datagram.c:271 vmci_datagram_dispatch+0x4f8/0xfc0 drivers/misc/vmw_vmci/vmci_datagram.c:339 qp_notify_peer+0x19a/0x290 drivers/misc/vmw_vmci/vmci_queue_pair.c:1479 qp_broker_attach drivers/misc/vmw_vmci/vmci_queue_pair.c:1662 qp_broker_alloc+0x2977/0x2f30 drivers/misc/vmw_vmci/vmci_queue_pair.c:1750 vmci_qp_broker_alloc+0x96/0xd0 drivers/misc/vmw_vmci/vmci_queue_pair.c:1940 vmci_host_do_alloc_queuepair drivers/misc/vmw_vmci/vmci_host.c:488 vmci_host_unlocked_ioctl+0x24fd/0x43d0 drivers/misc/vmw_vmci/vmci_host.c:927 ... Local variable ev created at: qp_notify_peer+0x54/0x290 drivers/misc/vmw_vmci/vmci_queue_pair.c:1456 qp_broker_attach drivers/misc/vmw_vmci/vmci_queue_pair.c:1662 qp_broker_alloc+0x2977/0x2f30 drivers/misc/vmw_vmci/vmci_queue_pair.c:1750 Bytes 28-31 of 48 are uninitialized Memory access of size 48 starts at ffff888035155e00 Data copied to user address 0000000020000100 Use memset() to prevent the infoleaks. Also speculatively fix qp_notify_peer_local(), which may suffer from the same problem. Reported-by: syzbot+39be4da489ed2493ba25@syzkaller.appspotmail.com Cc: stable Fixes: 06164d2b72aa ("VMCI: queue pairs implementation.") Signed-off-by: Alexander Potapenko Reviewed-by: Vishnu Dasa Link: https://lore.kernel.org/r/20221104175849.2782567-1-glider@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/vmw_vmci/vmci_queue_pair.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index e71068f7759b..844264e1b88c 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -854,6 +854,7 @@ static int qp_notify_peer_local(bool attach, struct vmci_handle handle) u32 context_id = vmci_get_context_id(); struct vmci_event_qp ev; + memset(&ev, 0, sizeof(ev)); ev.msg.hdr.dst = vmci_make_handle(context_id, VMCI_EVENT_HANDLER); ev.msg.hdr.src = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID, VMCI_CONTEXT_RESOURCE_ID); @@ -1467,6 +1468,7 @@ static int qp_notify_peer(bool attach, * kernel. */ + memset(&ev, 0, sizeof(ev)); ev.msg.hdr.dst = vmci_make_handle(peer_id, VMCI_EVENT_HANDLER); ev.msg.hdr.src = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID, VMCI_CONTEXT_RESOURCE_ID); -- cgit v1.2.3 From 6e63153db50059fb78b8a8447b132664887d24e3 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 4 Nov 2022 10:13:34 +0800 Subject: siox: fix possible memory leak in siox_device_add() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If device_register() returns error in siox_device_add(), the name allocated by dev_set_name() need be freed. As comment of device_register() says, it should use put_device() to give up the reference in the error path. So fix this by calling put_device(), then the name can be freed in kobject_cleanup(), and sdevice is freed in siox_device_release(), set it to null in error path. Fixes: bbecb07fa0af ("siox: new driver framework for eckelmann SIOX") Signed-off-by: Yang Yingliang Reviewed-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20221104021334.618189-1-yangyingliang@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/siox/siox-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/siox/siox-core.c b/drivers/siox/siox-core.c index 7c4f32d76966..561408583b2b 100644 --- a/drivers/siox/siox-core.c +++ b/drivers/siox/siox-core.c @@ -839,6 +839,8 @@ static struct siox_device *siox_device_add(struct siox_master *smaster, err_device_register: /* don't care to make the buffer smaller again */ + put_device(&sdevice->dev); + sdevice = NULL; err_buf_alloc: siox_master_unlock(smaster); -- cgit v1.2.3 From ab126f51c93a15093df604f661c9480854c005a3 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 23 Sep 2022 19:52:08 +0100 Subject: parport_pc: Avoid FIFO port location truncation Match the data type of a temporary holding a reference to the FIFO port with the type of the original reference coming from `struct parport', avoiding data truncation with LP64 ports such as SPARC64 that refer to PCI port I/O locations via their corresponding MMIO addresses and will therefore have non-zero bits in the high 32-bit part of the reference. And in any case it is cleaner to have the data types matching here. Signed-off-by: Maciej W. Rozycki Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Link: https://lore.kernel.org/linux-pci/20220419033752.GA1101844@bhelgaas/ Acked-by: Sudip Mukherjee Link: https://lore.kernel.org/r/alpine.DEB.2.21.2209231912550.29493@angie.orcam.me.uk Signed-off-by: Greg Kroah-Hartman --- drivers/parport/parport_pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 7c45927e2131..5784dc20fb38 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -468,7 +468,7 @@ static size_t parport_pc_fifo_write_block_pio(struct parport *port, const unsigned char *bufp = buf; size_t left = length; unsigned long expire = jiffies + port->physport->cad->timeout; - const int fifo = FIFO(port); + const unsigned long fifo = FIFO(port); int poll_for = 8; /* 80 usecs */ const struct parport_pc_private *priv = port->physport->private_data; const int fifo_depth = priv->fifo_depth; -- cgit v1.2.3 From 3ce00bb7e91cf57d723905371507af57182c37ef Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Fri, 4 Nov 2022 23:12:35 +0000 Subject: binder: validate alloc->mm in ->mmap() handler Since commit 1da52815d5f1 ("binder: fix alloc->vma_vm_mm null-ptr dereference") binder caches a pointer to the current->mm during open(). This fixes a null-ptr dereference reported by syzkaller. Unfortunately, it also opens the door for a process to update its mm after the open(), (e.g. via execve) making the cached alloc->mm pointer invalid. Things get worse when the process continues to mmap() a vma. From this point forward, binder will attempt to find this vma using an obsolete alloc->mm reference. Such as in binder_update_page_range(), where the wrong vma is obtained via vma_lookup(), yet binder proceeds to happily insert new pages into it. To avoid this issue fail the ->mmap() callback if we detect a mismatch between the vma->vm_mm and the original alloc->mm pointer. This prevents alloc->vm_addr from getting set, so that any subsequent vma_lookup() calls fail as expected. Fixes: 1da52815d5f1 ("binder: fix alloc->vma_vm_mm null-ptr dereference") Reported-by: Jann Horn Cc: # 5.15+ Signed-off-by: Carlos Llamas Acked-by: Todd Kjos Link: https://lore.kernel.org/r/20221104231235.348958-1-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder_alloc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 1c39cfce32fa..4ad42b0f75cd 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -739,6 +739,12 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, const char *failure_string; struct binder_buffer *buffer; + if (unlikely(vma->vm_mm != alloc->mm)) { + ret = -EINVAL; + failure_string = "invalid vma->vm_mm"; + goto err_invalid_mm; + } + mutex_lock(&binder_alloc_mmap_lock); if (alloc->buffer_size) { ret = -EBUSY; @@ -785,6 +791,7 @@ err_alloc_pages_failed: alloc->buffer_size = 0; err_already_mapped: mutex_unlock(&binder_alloc_mmap_lock); +err_invalid_mm: binder_alloc_debug(BINDER_DEBUG_USER_ERROR, "%s: %d %lx-%lx %s failed %d\n", __func__, alloc->pid, vma->vm_start, vma->vm_end, -- cgit v1.2.3 From 1760eb547276299ab0c6a6cd3d29469e54ade615 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Oct 2022 00:31:10 +0300 Subject: drm: rcar-du: Drop leftovers dependencies from Kconfig Commit 841281fe52a7 ("drm: rcar-du: Drop LVDS device tree backward compatibility") has removed device tree overlay sources used for backward compatibility with old bindings, but forgot to remove related dependencies from Kconfig. Fix it. Fixes: 841281fe52a7 ("drm: rcar-du: Drop LVDS device tree backward compatibility") Reviewed-by: Geert Uytterhoeven Reviewed-by: Kieran Bingham Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index c959e8c6be7d..13c4ad327771 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -41,8 +41,6 @@ config DRM_RCAR_LVDS depends on DRM_RCAR_USE_LVDS select DRM_KMS_HELPER select DRM_PANEL - select OF_FLATTREE - select OF_OVERLAY config DRM_RCAR_MIPI_DSI tristate "R-Car DU MIPI DSI Encoder Support" -- cgit v1.2.3 From 7a043f978ed1433bddb088a732e9bb91501ebd76 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 20 Sep 2022 11:55:00 +0100 Subject: drm: rcar-du: Add RZ/G2L DSI driver This driver supports the MIPI DSI encoder found in the RZ/G2L SoC. It currently supports DSI video mode only. Signed-off-by: Biju Das Acked-by: Sam Ravnborg Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/Kconfig | 8 + drivers/gpu/drm/rcar-du/Makefile | 2 + drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c | 762 ++++++++++++++++++++++++++ drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h | 151 +++++ 4 files changed, 923 insertions(+) create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index 13c4ad327771..f14686549cbe 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -49,6 +49,14 @@ config DRM_RCAR_MIPI_DSI help Enable support for the R-Car Display Unit embedded MIPI DSI encoders. +config DRM_RZG2L_MIPI_DSI + tristate "RZ/G2L MIPI DSI Encoder Support" + depends on DRM_BRIDGE && OF + depends on ARCH_RENESAS || COMPILE_TEST + select DRM_MIPI_DSI + help + Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders. + config DRM_RCAR_VSP bool "R-Car DU VSP Compositor Support" if ARM default y if ARM64 diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile index 6f132325c8b7..b8f2c82651d9 100644 --- a/drivers/gpu/drm/rcar-du/Makefile +++ b/drivers/gpu/drm/rcar-du/Makefile @@ -14,3 +14,5 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o obj-$(CONFIG_DRM_RCAR_MIPI_DSI) += rcar_mipi_dsi.o + +obj-$(CONFIG_DRM_RZG2L_MIPI_DSI) += rzg2l_mipi_dsi.o diff --git a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c new file mode 100644 index 000000000000..8579208db218 --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c @@ -0,0 +1,762 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2L MIPI DSI Encoder Driver + * + * Copyright (C) 2022 Renesas Electronics Corporation + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "rzg2l_mipi_dsi_regs.h" + +struct rzg2l_mipi_dsi { + struct device *dev; + void __iomem *mmio; + + struct reset_control *rstc; + struct reset_control *arstc; + struct reset_control *prstc; + + struct mipi_dsi_host host; + struct drm_bridge bridge; + struct drm_bridge *next_bridge; + + struct clk *vclk; + + enum mipi_dsi_pixel_format format; + unsigned int num_data_lanes; + unsigned int lanes; + unsigned long mode_flags; +}; + +static inline struct rzg2l_mipi_dsi * +bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge) +{ + return container_of(bridge, struct rzg2l_mipi_dsi, bridge); +} + +static inline struct rzg2l_mipi_dsi * +host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host) +{ + return container_of(host, struct rzg2l_mipi_dsi, host); +} + +struct rzg2l_mipi_dsi_timings { + unsigned long hsfreq_max; + u32 t_init; + u32 tclk_prepare; + u32 ths_prepare; + u32 tclk_zero; + u32 tclk_pre; + u32 tclk_post; + u32 tclk_trail; + u32 ths_zero; + u32 ths_trail; + u32 ths_exit; + u32 tlpx; +}; + +static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { + { + .hsfreq_max = 80000, + .t_init = 79801, + .tclk_prepare = 8, + .ths_prepare = 13, + .tclk_zero = 33, + .tclk_pre = 24, + .tclk_post = 94, + .tclk_trail = 10, + .ths_zero = 23, + .ths_trail = 17, + .ths_exit = 13, + .tlpx = 6, + }, + { + .hsfreq_max = 125000, + .t_init = 79801, + .tclk_prepare = 8, + .ths_prepare = 12, + .tclk_zero = 33, + .tclk_pre = 15, + .tclk_post = 94, + .tclk_trail = 10, + .ths_zero = 23, + .ths_trail = 17, + .ths_exit = 13, + .tlpx = 6, + }, + { + .hsfreq_max = 250000, + .t_init = 79801, + .tclk_prepare = 8, + .ths_prepare = 12, + .tclk_zero = 33, + .tclk_pre = 13, + .tclk_post = 94, + .tclk_trail = 10, + .ths_zero = 23, + .ths_trail = 16, + .ths_exit = 13, + .tlpx = 6, + }, + { + .hsfreq_max = 360000, + .t_init = 79801, + .tclk_prepare = 8, + .ths_prepare = 10, + .tclk_zero = 33, + .tclk_pre = 4, + .tclk_post = 35, + .tclk_trail = 7, + .ths_zero = 16, + .ths_trail = 9, + .ths_exit = 13, + .tlpx = 6, + }, + { + .hsfreq_max = 720000, + .t_init = 79801, + .tclk_prepare = 8, + .ths_prepare = 9, + .tclk_zero = 33, + .tclk_pre = 4, + .tclk_post = 35, + .tclk_trail = 7, + .ths_zero = 16, + .ths_trail = 9, + .ths_exit = 13, + .tlpx = 6, + }, + { + .hsfreq_max = 1500000, + .t_init = 79801, + .tclk_prepare = 8, + .ths_prepare = 9, + .tclk_zero = 33, + .tclk_pre = 4, + .tclk_post = 35, + .tclk_trail = 7, + .ths_zero = 16, + .ths_trail = 9, + .ths_exit = 13, + .tlpx = 6, + }, +}; + +static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) +{ + iowrite32(data, dsi->mmio + reg); +} + +static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) +{ + iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg); +} + +static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg) +{ + return ioread32(dsi->mmio + LINK_REG_OFFSET + reg); +} + +/* ----------------------------------------------------------------------------- + * Hardware Setup + */ + +static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, + const struct drm_display_mode *mode) +{ + const struct rzg2l_mipi_dsi_timings *dphy_timings; + unsigned long hsfreq; + unsigned int i, bpp; + u32 txsetr; + u32 clstptsetr; + u32 lptrnstsetr; + u32 clkkpt; + u32 clkbfht; + u32 clkstpt; + u32 golpbkt; + u32 dphyctrl0; + u32 dphytim0; + u32 dphytim1; + u32 dphytim2; + u32 dphytim3; + int ret; + + /* + * Relationship between hsclk and vclk must follow + * vclk * bpp = hsclk * 8 * lanes + * where vclk: video clock (Hz) + * bpp: video pixel bit depth + * hsclk: DSI HS Byte clock frequency (Hz) + * lanes: number of data lanes + * + * hsclk(bit) = hsclk(byte) * 8 + */ + bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); + hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes); + + /* All DSI global operation timings are set with recommended setting */ + for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) { + dphy_timings = &rzg2l_mipi_dsi_global_timings[i]; + if (hsfreq <= dphy_timings->hsfreq_max) + break; + } + + ret = pm_runtime_resume_and_get(dsi->dev); + if (ret < 0) + return ret; + + clk_set_rate(dsi->vclk, mode->clock * 1000); + + /* Initializing DPHY before accessing LINK */ + dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN | + DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR; + + rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); + usleep_range(20, 30); + + dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200; + rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); + usleep_range(10, 20); + + dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) | + DSIDPHYTIM0_T_INIT(dphy_timings->t_init); + dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) | + DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) | + DSIDPHYTIM1_THS_SETTLE(0) | + DSIDPHYTIM1_TCLK_SETTLE(0); + dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) | + DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) | + DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) | + DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero); + dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) | + DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) | + DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) | + DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero); + + rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0); + rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1); + rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2); + rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3); + + ret = reset_control_deassert(dsi->rstc); + if (ret < 0) + goto err_pm_put; + + udelay(1); + + /* Enable Data lanes and Clock lanes */ + txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN; + rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr); + + /* + * Global timings characteristic depends on high speed Clock Frequency + * Currently MIPI DSI-IF just supports maximum FHD@60 with: + * - videoclock = 148.5 (MHz) + * - bpp: maximum 24bpp + * - data lanes: maximum 4 lanes + * Therefore maximum hsclk will be 891 Mbps. + */ + if (hsfreq > 445500) { + clkkpt = 12; + clkbfht = 15; + clkstpt = 48; + golpbkt = 75; + } else if (hsfreq > 250000) { + clkkpt = 7; + clkbfht = 8; + clkstpt = 27; + golpbkt = 40; + } else { + clkkpt = 8; + clkbfht = 6; + clkstpt = 24; + golpbkt = 29; + } + + clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) | + CLSTPTSETR_CLKSTPT(clkstpt); + rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr); + + lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt); + rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr); + + return 0; + +err_pm_put: + pm_runtime_put(dsi->dev); + + return ret; +} + +static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi) +{ + reset_control_assert(dsi->rstc); + pm_runtime_put(dsi->dev); +} + +static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi, + const struct drm_display_mode *mode) +{ + u32 vich1ppsetr; + u32 vich1vssetr; + u32 vich1vpsetr; + u32 vich1hssetr; + u32 vich1hpsetr; + int dsi_format; + u32 delay[2]; + u8 index; + + /* Configuration for Pixel Packet */ + dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format); + switch (dsi_format) { + case 24: + vich1ppsetr = VICH1PPSETR_DT_RGB24; + break; + case 18: + vich1ppsetr = VICH1PPSETR_DT_RGB18; + break; + } + + if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) && + !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) + vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE; + + rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr); + + /* Configuration for Video Parameters */ + vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) | + VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start); + vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ? + VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW; + + vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) | + VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end); + + vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) | + VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start); + vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ? + VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW; + + vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) | + VICH1HPSETR_HBP(mode->htotal - mode->hsync_end); + + rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr); + rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr); + rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr); + rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr); + + /* + * Configuration for Delay Value + * Delay value based on 2 ranges of video clock. + * 74.25MHz is videoclock of HD@60p or FHD@30p + */ + if (mode->clock > 74250) { + delay[0] = 231; + delay[1] = 216; + } else { + delay[0] = 220; + delay[1] = 212; + } + + if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) + index = 0; + else + index = 1; + + rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R, + VICH1SET1R_DLY(delay[index])); +} + +static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi) +{ + bool is_clk_cont; + u32 hsclksetr; + u32 status; + int ret; + + is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS); + + /* Start HS clock */ + hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ? + HSCLKSETR_HSCLKMODE_CONT : + HSCLKSETR_HSCLKMODE_NON_CONT); + rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr); + + if (is_clk_cont) { + ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, + status & PLSR_CLLP2HS, + 2000, 20000, false, dsi, PLSR); + if (ret < 0) { + dev_err(dsi->dev, "failed to start HS clock\n"); + return ret; + } + } + + dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode", + is_clk_cont ? "continuous" : "non-continuous"); + + return 0; +} + +static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi) +{ + bool is_clk_cont; + u32 status; + int ret; + + is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS); + + /* Stop HS clock */ + rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, + is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT : + HSCLKSETR_HSCLKMODE_NON_CONT); + + if (is_clk_cont) { + ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, + status & PLSR_CLHS2LP, + 2000, 20000, false, dsi, PLSR); + if (ret < 0) { + dev_err(dsi->dev, "failed to stop HS clock\n"); + return ret; + } + } + + return 0; +} + +static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi) +{ + u32 vich1set0r; + u32 status; + int ret; + + /* Configuration for Blanking sequence and start video input*/ + vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP | + VICH1SET0R_HSANOLP | VICH1SET0R_VSTART; + rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r); + + ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, + status & VICH1SR_VIRDY, + 2000, 20000, false, dsi, VICH1SR); + if (ret < 0) + dev_err(dsi->dev, "Failed to start video signal input\n"); + + return ret; +} + +static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi) +{ + u32 status; + int ret; + + rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT); + ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, + (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)), + 2000, 20000, false, dsi, VICH1SR); + if (ret < 0) + goto err; + + ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, + !(status & LINKSR_HSBUSY), + 2000, 20000, false, dsi, LINKSR); + if (ret < 0) + goto err; + + return 0; + +err: + dev_err(dsi->dev, "Failed to stop video signal input\n"); + return ret; +} + +/* ----------------------------------------------------------------------------- + * Bridge + */ + +static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); + + return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge, + flags); +} + +static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct drm_atomic_state *state = old_bridge_state->base.state; + struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); + const struct drm_display_mode *mode; + struct drm_connector *connector; + struct drm_crtc *crtc; + int ret; + + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; + mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode; + + ret = rzg2l_mipi_dsi_startup(dsi, mode); + if (ret < 0) + return; + + rzg2l_mipi_dsi_set_display_timing(dsi, mode); + + ret = rzg2l_mipi_dsi_start_hs_clock(dsi); + if (ret < 0) + goto err_stop; + + ret = rzg2l_mipi_dsi_start_video(dsi); + if (ret < 0) + goto err_stop_clock; + + return; + +err_stop_clock: + rzg2l_mipi_dsi_stop_hs_clock(dsi); +err_stop: + rzg2l_mipi_dsi_stop(dsi); +} + +static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); + + rzg2l_mipi_dsi_stop_video(dsi); + rzg2l_mipi_dsi_stop_hs_clock(dsi); + rzg2l_mipi_dsi_stop(dsi); +} + +static enum drm_mode_status +rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + if (mode->clock > 148500) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = { + .attach = rzg2l_mipi_dsi_attach, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_enable = rzg2l_mipi_dsi_atomic_enable, + .atomic_disable = rzg2l_mipi_dsi_atomic_disable, + .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid, +}; + +/* ----------------------------------------------------------------------------- + * Host setting + */ + +static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) +{ + struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host); + int ret; + + if (device->lanes > dsi->num_data_lanes) { + dev_err(dsi->dev, + "Number of lines of device (%u) exceeds host (%u)\n", + device->lanes, dsi->num_data_lanes); + return -EINVAL; + } + + switch (mipi_dsi_pixel_format_to_bpp(device->format)) { + case 24: + case 18: + break; + default: + dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format); + return -EINVAL; + } + + dsi->lanes = device->lanes; + dsi->format = device->format; + dsi->mode_flags = device->mode_flags; + + dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node, + 1, 0); + if (IS_ERR(dsi->next_bridge)) { + ret = PTR_ERR(dsi->next_bridge); + dev_err(dsi->dev, "failed to get next bridge: %d\n", ret); + return ret; + } + + drm_bridge_add(&dsi->bridge); + + return 0; +} + +static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) +{ + struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host); + + drm_bridge_remove(&dsi->bridge); + + return 0; +} + +static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = { + .attach = rzg2l_mipi_dsi_host_attach, + .detach = rzg2l_mipi_dsi_host_detach, +}; + +/* ----------------------------------------------------------------------------- + * Power Management + */ + +static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev) +{ + struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev); + + reset_control_assert(dsi->prstc); + reset_control_assert(dsi->arstc); + + return 0; +} + +static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev) +{ + struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev); + int ret; + + ret = reset_control_deassert(dsi->arstc); + if (ret < 0) + return ret; + + ret = reset_control_deassert(dsi->prstc); + if (ret < 0) + reset_control_assert(dsi->arstc); + + return ret; +} + +static const struct dev_pm_ops rzg2l_mipi_pm_ops = { + SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL) +}; + +/* ----------------------------------------------------------------------------- + * Probe & Remove + */ + +static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) +{ + struct rzg2l_mipi_dsi *dsi; + int ret; + + dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); + if (!dsi) + return -ENOMEM; + + platform_set_drvdata(pdev, dsi); + dsi->dev = &pdev->dev; + + ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4); + if (ret < 0) + return dev_err_probe(dsi->dev, ret, + "missing or invalid data-lanes property\n"); + + dsi->num_data_lanes = ret; + + dsi->mmio = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(dsi->mmio)) + return PTR_ERR(dsi->mmio); + + dsi->vclk = devm_clk_get(dsi->dev, "vclk"); + if (IS_ERR(dsi->vclk)) + return PTR_ERR(dsi->vclk); + + dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst"); + if (IS_ERR(dsi->rstc)) + return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc), + "failed to get rst\n"); + + dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst"); + if (IS_ERR(dsi->arstc)) + return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc), + "failed to get arst\n"); + + dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst"); + if (IS_ERR(dsi->prstc)) + return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc), + "failed to get prst\n"); + + platform_set_drvdata(pdev, dsi); + + pm_runtime_enable(dsi->dev); + + /* Initialize the DRM bridge. */ + dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops; + dsi->bridge.of_node = dsi->dev->of_node; + + /* Init host device */ + dsi->host.dev = dsi->dev; + dsi->host.ops = &rzg2l_mipi_dsi_host_ops; + ret = mipi_dsi_host_register(&dsi->host); + if (ret < 0) + goto err_pm_disable; + + return 0; + +err_pm_disable: + pm_runtime_disable(dsi->dev); + return ret; +} + +static int rzg2l_mipi_dsi_remove(struct platform_device *pdev) +{ + struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev); + + mipi_dsi_host_unregister(&dsi->host); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct of_device_id rzg2l_mipi_dsi_of_table[] = { + { .compatible = "renesas,rzg2l-mipi-dsi" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table); + +static struct platform_driver rzg2l_mipi_dsi_platform_driver = { + .probe = rzg2l_mipi_dsi_probe, + .remove = rzg2l_mipi_dsi_remove, + .driver = { + .name = "rzg2l-mipi-dsi", + .pm = &rzg2l_mipi_pm_ops, + .of_match_table = rzg2l_mipi_dsi_of_table, + }, +}; + +module_platform_driver(rzg2l_mipi_dsi_platform_driver); + +MODULE_AUTHOR("Biju Das "); +MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h new file mode 100644 index 000000000000..1dbc16ec64a4 --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * RZ/G2L MIPI DSI Interface Registers Definitions + * + * Copyright (C) 2022 Renesas Electronics Corporation + */ + +#ifndef __RZG2L_MIPI_DSI_REGS_H__ +#define __RZG2L_MIPI_DSI_REGS_H__ + +#include + +/* DPHY Registers */ +#define DSIDPHYCTRL0 0x00 +#define DSIDPHYCTRL0_CAL_EN_HSRX_OFS BIT(16) +#define DSIDPHYCTRL0_CMN_MASTER_EN BIT(8) +#define DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 BIT(2) +#define DSIDPHYCTRL0_EN_LDO1200 BIT(1) +#define DSIDPHYCTRL0_EN_BGR BIT(0) + +#define DSIDPHYTIM0 0x04 +#define DSIDPHYTIM0_TCLK_MISS(x) ((x) << 24) +#define DSIDPHYTIM0_T_INIT(x) ((x) << 0) + +#define DSIDPHYTIM1 0x08 +#define DSIDPHYTIM1_THS_PREPARE(x) ((x) << 24) +#define DSIDPHYTIM1_TCLK_PREPARE(x) ((x) << 16) +#define DSIDPHYTIM1_THS_SETTLE(x) ((x) << 8) +#define DSIDPHYTIM1_TCLK_SETTLE(x) ((x) << 0) + +#define DSIDPHYTIM2 0x0c +#define DSIDPHYTIM2_TCLK_TRAIL(x) ((x) << 24) +#define DSIDPHYTIM2_TCLK_POST(x) ((x) << 16) +#define DSIDPHYTIM2_TCLK_PRE(x) ((x) << 8) +#define DSIDPHYTIM2_TCLK_ZERO(x) ((x) << 0) + +#define DSIDPHYTIM3 0x10 +#define DSIDPHYTIM3_TLPX(x) ((x) << 24) +#define DSIDPHYTIM3_THS_EXIT(x) ((x) << 16) +#define DSIDPHYTIM3_THS_TRAIL(x) ((x) << 8) +#define DSIDPHYTIM3_THS_ZERO(x) ((x) << 0) + +/* --------------------------------------------------------*/ +/* Link Registers */ +#define LINK_REG_OFFSET 0x10000 + +/* Link Status Register */ +#define LINKSR 0x10 +#define LINKSR_LPBUSY BIT(13) +#define LINKSR_HSBUSY BIT(12) +#define LINKSR_VICHRUN1 BIT(8) +#define LINKSR_SQCHRUN1 BIT(4) +#define LINKSR_SQCHRUN0 BIT(0) + +/* Tx Set Register */ +#define TXSETR 0x100 +#define TXSETR_NUMLANECAP (0x3 << 16) +#define TXSETR_DLEN (1 << 9) +#define TXSETR_CLEN (1 << 8) +#define TXSETR_NUMLANEUSE(x) (((x) & 0x3) << 0) + +/* HS Clock Set Register */ +#define HSCLKSETR 0x104 +#define HSCLKSETR_HSCLKMODE_CONT (1 << 1) +#define HSCLKSETR_HSCLKMODE_NON_CONT (0 << 1) +#define HSCLKSETR_HSCLKRUN_HS (1 << 0) +#define HSCLKSETR_HSCLKRUN_LP (0 << 0) + +/* Reset Control Register */ +#define RSTCR 0x110 +#define RSTCR_SWRST BIT(0) +#define RSTCR_FCETXSTP BIT(16) + +/* Reset Status Register */ +#define RSTSR 0x114 +#define RSTSR_DL0DIR (1 << 15) +#define RSTSR_DLSTPST (0xf << 8) +#define RSTSR_SWRSTV1 (1 << 4) +#define RSTSR_SWRSTIB (1 << 3) +#define RSTSR_SWRSTAPB (1 << 2) +#define RSTSR_SWRSTLP (1 << 1) +#define RSTSR_SWRSTHS (1 << 0) + +/* Clock Lane Stop Time Set Register */ +#define CLSTPTSETR 0x314 +#define CLSTPTSETR_CLKKPT(x) ((x) << 24) +#define CLSTPTSETR_CLKBFHT(x) ((x) << 16) +#define CLSTPTSETR_CLKSTPT(x) ((x) << 2) + +/* LP Transition Time Set Register */ +#define LPTRNSTSETR 0x318 +#define LPTRNSTSETR_GOLPBKT(x) ((x) << 0) + +/* Physical Lane Status Register */ +#define PLSR 0x320 +#define PLSR_CLHS2LP BIT(27) +#define PLSR_CLLP2HS BIT(26) + +/* Video-Input Channel 1 Set 0 Register */ +#define VICH1SET0R 0x400 +#define VICH1SET0R_VSEN BIT(12) +#define VICH1SET0R_HFPNOLP BIT(10) +#define VICH1SET0R_HBPNOLP BIT(9) +#define VICH1SET0R_HSANOLP BIT(8) +#define VICH1SET0R_VSTPAFT BIT(1) +#define VICH1SET0R_VSTART BIT(0) + +/* Video-Input Channel 1 Set 1 Register */ +#define VICH1SET1R 0x404 +#define VICH1SET1R_DLY(x) (((x) & 0xfff) << 2) + +/* Video-Input Channel 1 Status Register */ +#define VICH1SR 0x410 +#define VICH1SR_VIRDY BIT(3) +#define VICH1SR_RUNNING BIT(2) +#define VICH1SR_STOP BIT(1) +#define VICH1SR_START BIT(0) + +/* Video-Input Channel 1 Pixel Packet Set Register */ +#define VICH1PPSETR 0x420 +#define VICH1PPSETR_DT_RGB18 (0x1e << 16) +#define VICH1PPSETR_DT_RGB18_LS (0x2e << 16) +#define VICH1PPSETR_DT_RGB24 (0x3e << 16) +#define VICH1PPSETR_TXESYNC_PULSE (1 << 15) +#define VICH1PPSETR_VC(x) ((x) << 22) + +/* Video-Input Channel 1 Vertical Size Set Register */ +#define VICH1VSSETR 0x428 +#define VICH1VSSETR_VACTIVE(x) (((x) & 0x7fff) << 16) +#define VICH1VSSETR_VSPOL_LOW (1 << 15) +#define VICH1VSSETR_VSPOL_HIGH (0 << 15) +#define VICH1VSSETR_VSA(x) (((x) & 0xfff) << 0) + +/* Video-Input Channel 1 Vertical Porch Set Register */ +#define VICH1VPSETR 0x42c +#define VICH1VPSETR_VFP(x) (((x) & 0x1fff) << 16) +#define VICH1VPSETR_VBP(x) (((x) & 0x1fff) << 0) + +/* Video-Input Channel 1 Horizontal Size Set Register */ +#define VICH1HSSETR 0x430 +#define VICH1HSSETR_HACTIVE(x) (((x) & 0x7fff) << 16) +#define VICH1HSSETR_HSPOL_LOW (1 << 15) +#define VICH1HSSETR_HSPOL_HIGH (0 << 15) +#define VICH1HSSETR_HSA(x) (((x) & 0xfff) << 0) + +/* Video-Input Channel 1 Horizontal Porch Set Register */ +#define VICH1HPSETR 0x434 +#define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16) +#define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0) + +#endif /* __RZG2L_MIPI_DSI_REGS_H__ */ -- cgit v1.2.3 From 418bb3a69e1355c8977c528f8f3896a0aaaecb80 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 20 Sep 2022 11:55:01 +0100 Subject: drm: rcar-du: rzg2l_mipi_dsi: Enhance device lanes check Enhance device lanes check by reading TXSETR register at probe(), and enforced in rzg2l_mipi_dsi_host_attach(). As per HW manual, we can read TXSETR register only after DPHY initialization. Suggested-by: Laurent Pinchart Signed-off-by: Biju Das Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c | 122 ++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c index 8579208db218..aa95b85a2964 100644 --- a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c +++ b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c @@ -171,6 +171,11 @@ static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 d iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg); } +static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg) +{ + return ioread32(dsi->mmio + reg); +} + static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg) { return ioread32(dsi->mmio + LINK_REG_OFFSET + reg); @@ -180,19 +185,11 @@ static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg) * Hardware Setup */ -static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, - const struct drm_display_mode *mode) +static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi, + unsigned long hsfreq) { const struct rzg2l_mipi_dsi_timings *dphy_timings; - unsigned long hsfreq; - unsigned int i, bpp; - u32 txsetr; - u32 clstptsetr; - u32 lptrnstsetr; - u32 clkkpt; - u32 clkbfht; - u32 clkstpt; - u32 golpbkt; + unsigned int i; u32 dphyctrl0; u32 dphytim0; u32 dphytim1; @@ -200,19 +197,6 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, u32 dphytim3; int ret; - /* - * Relationship between hsclk and vclk must follow - * vclk * bpp = hsclk * 8 * lanes - * where vclk: video clock (Hz) - * bpp: video pixel bit depth - * hsclk: DSI HS Byte clock frequency (Hz) - * lanes: number of data lanes - * - * hsclk(bit) = hsclk(byte) * 8 - */ - bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); - hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes); - /* All DSI global operation timings are set with recommended setting */ for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) { dphy_timings = &rzg2l_mipi_dsi_global_timings[i]; @@ -220,12 +204,6 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, break; } - ret = pm_runtime_resume_and_get(dsi->dev); - if (ret < 0) - return ret; - - clk_set_rate(dsi->vclk, mode->clock * 1000); - /* Initializing DPHY before accessing LINK */ dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN | DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR; @@ -259,10 +237,62 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, ret = reset_control_deassert(dsi->rstc); if (ret < 0) - goto err_pm_put; + return ret; udelay(1); + return 0; +} + +static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi) +{ + u32 dphyctrl0; + + dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0); + + dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR); + rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); + + reset_control_assert(dsi->rstc); +} + +static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, + const struct drm_display_mode *mode) +{ + unsigned long hsfreq; + unsigned int bpp; + u32 txsetr; + u32 clstptsetr; + u32 lptrnstsetr; + u32 clkkpt; + u32 clkbfht; + u32 clkstpt; + u32 golpbkt; + int ret; + + /* + * Relationship between hsclk and vclk must follow + * vclk * bpp = hsclk * 8 * lanes + * where vclk: video clock (Hz) + * bpp: video pixel bit depth + * hsclk: DSI HS Byte clock frequency (Hz) + * lanes: number of data lanes + * + * hsclk(bit) = hsclk(byte) * 8 + */ + bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); + hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes); + + ret = pm_runtime_resume_and_get(dsi->dev); + if (ret < 0) + return ret; + + clk_set_rate(dsi->vclk, mode->clock * 1000); + + ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq); + if (ret < 0) + goto err_phy; + /* Enable Data lanes and Clock lanes */ txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN; rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr); @@ -301,7 +331,8 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, return 0; -err_pm_put: +err_phy: + rzg2l_mipi_dsi_dphy_exit(dsi); pm_runtime_put(dsi->dev); return ret; @@ -309,7 +340,7 @@ err_pm_put: static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi) { - reset_control_assert(dsi->rstc); + rzg2l_mipi_dsi_dphy_exit(dsi); pm_runtime_put(dsi->dev); } @@ -666,7 +697,9 @@ static const struct dev_pm_ops rzg2l_mipi_pm_ops = { static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) { + unsigned int num_data_lanes; struct rzg2l_mipi_dsi *dsi; + u32 txsetr; int ret; dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); @@ -681,7 +714,7 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) return dev_err_probe(dsi->dev, ret, "missing or invalid data-lanes property\n"); - dsi->num_data_lanes = ret; + num_data_lanes = ret; dsi->mmio = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dsi->mmio)) @@ -710,6 +743,24 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) pm_runtime_enable(dsi->dev); + ret = pm_runtime_resume_and_get(dsi->dev); + if (ret < 0) + goto err_pm_disable; + + /* + * TXSETR register can be read only after DPHY init. But during probe + * mode->clock and format are not available. So initialize DPHY with + * timing parameters for 80Mbps. + */ + ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000); + if (ret < 0) + goto err_phy; + + txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR); + dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes); + rzg2l_mipi_dsi_dphy_exit(dsi); + pm_runtime_put(dsi->dev); + /* Initialize the DRM bridge. */ dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops; dsi->bridge.of_node = dsi->dev->of_node; @@ -723,6 +774,9 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) return 0; +err_phy: + rzg2l_mipi_dsi_dphy_exit(dsi); + pm_runtime_put(dsi->dev); err_pm_disable: pm_runtime_disable(dsi->dev); return ret; -- cgit v1.2.3 From cec9e59cae6071e58140baf54e47c00aaa39851b Mon Sep 17 00:00:00 2001 From: Nathan Huckleberry Date: Tue, 8 Nov 2022 17:14:25 -0700 Subject: drm: xlnx: Fix return type of zynqmp_dp_bridge_mode_valid The mode_valid field in drm_bridge_helper_funcs is expected to be of type enum drm_mode_status (* mode_valid) (struct drm_bridge *bridge, struct drm_display_mode *mode); The mismatched return type breaks forward edge kCFI since the underlying function definition does not match the function hook definition. A new warning in clang will catch this at compile time: drivers/gpu/drm/xlnx/zynqmp_dp.c:1573:16: error: incompatible function pointer types initializing 'enum drm_mode_status (*)(struct drm_bridge *, const struct drm_display_info *, const struct drm_display_mode *)' with an expression of type 'int (struct drm_bridge *, const struct drm_display_info *, const struct drm_display_mode *)' [-Werror,-Wincompatible-function-pointer-types-strict] .mode_valid = zynqmp_dp_bridge_mode_valid, ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. The return type of zynqmp_dp_bridge_mode_valid should be changed from int to enum drm_mode_status. Reported-by: Dan Carpenter Link: https://github.com/ClangBuiltLinux/linux/issues/1703 Link: https://github.com/ClangBuiltLinux/linux/issues/1750 Signed-off-by: Nathan Huckleberry Reviewed-by: Laurent Pinchart [nathan: Rebase on drm-misc-next and fix conflicts Add note about new clang warning] Signed-off-by: Nathan Chancellor Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/xlnx/zynqmp_dp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c index 7c9ae167eac7..0a7b466446fb 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c @@ -1362,9 +1362,10 @@ static void zynqmp_dp_bridge_detach(struct drm_bridge *bridge) zynqmp_dp_aux_cleanup(dp); } -static int zynqmp_dp_bridge_mode_valid(struct drm_bridge *bridge, - const struct drm_display_info *info, - const struct drm_display_mode *mode) +static enum drm_mode_status +zynqmp_dp_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) { struct zynqmp_dp *dp = bridge_to_dp(bridge); int rate; -- cgit v1.2.3 From 6398acf34819da99e5110e7eae47e81ef5e4bb77 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 2 Nov 2022 12:08:24 +0200 Subject: drm/i915/display: move struct intel_link_m_n to intel_display_types.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct intel_crtc_state in intel_display_types.h actually needs the struct intel_link_m_n definition, while intel_display.h only needs the forward declaration. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/1ec10e4415cf84c51b7eb51092e81876da0bc902.1667383630.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.h | 10 +--------- drivers/gpu/drm/i915/display/intel_display_types.h | 9 +++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index d9c8b8447f9e..b78009a20e00 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -53,6 +53,7 @@ struct intel_digital_port; struct intel_dp; struct intel_encoder; struct intel_initial_plane_config; +struct intel_link_m_n; struct intel_load_detect_pipe; struct intel_plane; struct intel_plane_state; @@ -287,15 +288,6 @@ enum aux_ch { #define aux_ch_name(a) ((a) + 'A') -/* Used by dp and fdi links */ -struct intel_link_m_n { - u32 tu; - u32 data_m; - u32 data_n; - u32 link_m; - u32 link_n; -}; - enum phy { PHY_NONE = -1, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 64314273995d..9258d50a07a0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -969,6 +969,15 @@ struct intel_mpllb_state { u32 mpllb_sscstep; }; +/* Used by dp and fdi links */ +struct intel_link_m_n { + u32 tu; + u32 data_m; + u32 data_n; + u32 link_m; + u32 link_n; +}; + struct intel_crtc_state { /* * uapi (drm) state. This is the software state shown to userspace. -- cgit v1.2.3 From 15f8f168952f54d3c86d734dc764f20844e423ac Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Wed, 2 Nov 2022 23:55:37 -0700 Subject: net/mlx5: Bridge, verify LAG state when adding bond to bridge Mlx5 LAG is initialized asynchronously on a workqueue which means that for a brief moment after setting mlx5 UL representors as lower devices of a bond netdevice the LAG itself is not fully initialized in the driver. When adding such bond device to a bridge mlx5 bridge code will not consider it as offload-capable, skip creating necessary bookkeeping and fail any further bridge offload-related commands with it (setting VLANs, offloading FDBs, etc.). In order to make the error explicit during bridge initialization stage implement the code that detects such condition during NETDEV_PRECHANGEUPPER event and returns an error. Fixes: ff9b7521468b ("net/mlx5: Bridge, support LAG") Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Reviewed-by: Mark Bloch Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en/rep/bridge.c | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c index 39ef2a2561a3..8099a21e674c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c @@ -164,6 +164,36 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr return err; } +static int +mlx5_esw_bridge_changeupper_validate_netdev(void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info = ptr; + struct net_device *upper = info->upper_dev; + struct net_device *lower; + struct list_head *iter; + + if (!netif_is_bridge_master(upper) || !netif_is_lag_master(dev)) + return 0; + + netdev_for_each_lower_dev(dev, lower, iter) { + struct mlx5_core_dev *mdev; + struct mlx5e_priv *priv; + + if (!mlx5e_eswitch_rep(lower)) + continue; + + priv = netdev_priv(lower); + mdev = priv->mdev; + if (!mlx5_lag_is_active(mdev)) + return -EAGAIN; + if (!mlx5_lag_is_shared_fdb(mdev)) + return -EOPNOTSUPP; + } + + return 0; +} + static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb, unsigned long event, void *ptr) { @@ -171,6 +201,7 @@ static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb, switch (event) { case NETDEV_PRECHANGEUPPER: + err = mlx5_esw_bridge_changeupper_validate_netdev(ptr); break; case NETDEV_CHANGEUPPER: -- cgit v1.2.3 From 2808b37b59288ad8f1897e3546c2296df3384b65 Mon Sep 17 00:00:00 2001 From: Roy Novich Date: Wed, 2 Nov 2022 23:55:38 -0700 Subject: net/mlx5: Allow async trigger completion execution on single CPU systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For a single CPU system, the kernel thread executing mlx5_cmd_flush() never releases the CPU but calls down_trylock(&cmd→sem) in a busy loop. On a single processor system, this leads to a deadlock as the kernel thread which executes mlx5_cmd_invoke() never gets scheduled. Fix this, by adding the cond_resched() call to the loop, allow the command completion kernel thread to execute. Fixes: 8e715cd613a1 ("net/mlx5: Set command entry semaphore up once got index free") Signed-off-by: Alexander Schmidt Signed-off-by: Roy Novich Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 46ba4c2faad2..2e0d59ca62b5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1770,12 +1770,17 @@ void mlx5_cmd_flush(struct mlx5_core_dev *dev) struct mlx5_cmd *cmd = &dev->cmd; int i; - for (i = 0; i < cmd->max_reg_cmds; i++) - while (down_trylock(&cmd->sem)) + for (i = 0; i < cmd->max_reg_cmds; i++) { + while (down_trylock(&cmd->sem)) { mlx5_cmd_trigger_completions(dev); + cond_resched(); + } + } - while (down_trylock(&cmd->pages_sem)) + while (down_trylock(&cmd->pages_sem)) { mlx5_cmd_trigger_completions(dev); + cond_resched(); + } /* Unlock cmdif */ up(&cmd->pages_sem); -- cgit v1.2.3 From e12de39c07a7872c1ac7250311bb60b74ff29f25 Mon Sep 17 00:00:00 2001 From: Chris Mi Date: Wed, 2 Nov 2022 23:55:39 -0700 Subject: net/mlx5: E-switch, Set to legacy mode if failed to change switchdev mode No need to rollback to the other mode because probably will fail again. Just set to legacy mode and clear fdb table created flag. So that fdb table will not be cleared again. Fixes: f019679ea5f2 ("net/mlx5: E-switch, Remove dependency between sriov and eswitch mode") Signed-off-by: Chris Mi Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 14 ++++++++------ .../net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 18 +++--------------- 2 files changed, 11 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index c59107fa9e6d..2169486c4bfb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1387,12 +1387,14 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw) esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", esw->esw_funcs.num_vfs, esw->enabled_vports); - esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED; - if (esw->mode == MLX5_ESWITCH_OFFLOADS) - esw_offloads_disable(esw); - else if (esw->mode == MLX5_ESWITCH_LEGACY) - esw_legacy_disable(esw); - mlx5_esw_acls_ns_cleanup(esw); + if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) { + esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED; + if (esw->mode == MLX5_ESWITCH_OFFLOADS) + esw_offloads_disable(esw); + else if (esw->mode == MLX5_ESWITCH_LEGACY) + esw_legacy_disable(esw); + mlx5_esw_acls_ns_cleanup(esw); + } if (esw->mode == MLX5_ESWITCH_OFFLOADS) devl_rate_nodes_destroy(devlink); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 4e50df3139c6..728ca9f2bb9d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2310,7 +2310,7 @@ out_free: static int esw_offloads_start(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack) { - int err, err1; + int err; esw->mode = MLX5_ESWITCH_OFFLOADS; err = mlx5_eswitch_enable_locked(esw, esw->dev->priv.sriov.num_vfs); @@ -2318,11 +2318,6 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to offloads"); esw->mode = MLX5_ESWITCH_LEGACY; - err1 = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_IGNORE_NUM_VFS); - if (err1) { - NL_SET_ERR_MSG_MOD(extack, - "Failed setting eswitch back to legacy"); - } mlx5_rescan_drivers(esw->dev); } if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) { @@ -3389,19 +3384,12 @@ err_metadata: static int esw_offloads_stop(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack) { - int err, err1; + int err; esw->mode = MLX5_ESWITCH_LEGACY; err = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_IGNORE_NUM_VFS); - if (err) { + if (err) NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to legacy"); - esw->mode = MLX5_ESWITCH_OFFLOADS; - err1 = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_IGNORE_NUM_VFS); - if (err1) { - NL_SET_ERR_MSG_MOD(extack, - "Failed setting eswitch back to offloads"); - } - } return err; } -- cgit v1.2.3 From 7d167b4a4c810919ba1affd02fc6b7f40e7e6eeb Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Wed, 2 Nov 2022 23:55:40 -0700 Subject: net/mlx5: fw_reset: Don't try to load device in case PCI isn't working In case PCI reads fail after unload, there is no use in trying to load the device. Fixes: 5ec697446f46 ("net/mlx5: Add support for devlink reload action fw activate") Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index 07c583996c29..9d908a0ccfef 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -152,7 +152,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) mlx5_unload_one(dev); if (mlx5_health_wait_pci_up(dev)) mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); - mlx5_load_one(dev, false); + else + mlx5_load_one(dev, false); devlink_remote_reload_actions_performed(priv_to_devlink(dev), 0, BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); -- cgit v1.2.3 From f9c955b4fe5c8626d11b8a9b93ccc0ba77358fec Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Wed, 2 Nov 2022 23:55:42 -0700 Subject: net/mlx5e: Add missing sanity checks for max TX WQE size The commit cited below started using the firmware capability for the maximum TX WQE size. This commit adds an important check to verify that the driver doesn't attempt to exceed this capability, and also restores another check mistakenly removed in the cited commit (a WQE must not exceed the page size). Fixes: c27bd1718c06 ("net/mlx5e: Read max WQEBBs on the SQ from firmware") Signed-off-by: Maxim Mikityanskiy Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h | 24 ++++++++++++++++++++++- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 7 +++++++ drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 5 +++++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index cb164b62f543..853f312cd757 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -11,6 +11,27 @@ #define INL_HDR_START_SZ (sizeof(((struct mlx5_wqe_eth_seg *)NULL)->inline_hdr.start)) +/* IPSEC inline data includes: + * 1. ESP trailer: up to 255 bytes of padding, 1 byte for pad length, 1 byte for + * next header. + * 2. ESP authentication data: 16 bytes for ICV. + */ +#define MLX5E_MAX_TX_IPSEC_DS DIV_ROUND_UP(sizeof(struct mlx5_wqe_inline_seg) + \ + 255 + 1 + 1 + 16, MLX5_SEND_WQE_DS) + +/* 366 should be big enough to cover all L2, L3 and L4 headers with possible + * encapsulations. + */ +#define MLX5E_MAX_TX_INLINE_DS DIV_ROUND_UP(366 - INL_HDR_START_SZ + VLAN_HLEN, \ + MLX5_SEND_WQE_DS) + +/* Sync the calculation with mlx5e_sq_calc_wqe_attr. */ +#define MLX5E_MAX_TX_WQEBBS DIV_ROUND_UP(MLX5E_TX_WQE_EMPTY_DS_COUNT + \ + MLX5E_MAX_TX_INLINE_DS + \ + MLX5E_MAX_TX_IPSEC_DS + \ + MAX_SKB_FRAGS + 1, \ + MLX5_SEND_WQEBB_NUM_DS) + #define MLX5E_RX_ERR_CQE(cqe) (get_cqe_opcode(cqe) != MLX5_CQE_RESP_SEND) static inline @@ -424,6 +445,8 @@ mlx5e_set_eseg_swp(struct sk_buff *skb, struct mlx5_wqe_eth_seg *eseg, static inline u16 mlx5e_stop_room_for_wqe(struct mlx5_core_dev *mdev, u16 wqe_size) { + WARN_ON_ONCE(PAGE_SIZE / MLX5_SEND_WQE_BB < mlx5e_get_max_sq_wqebbs(mdev)); + /* A WQE must not cross the page boundary, hence two conditions: * 1. Its size must not exceed the page size. * 2. If the WQE size is X, and the space remaining in a page is less @@ -436,7 +459,6 @@ static inline u16 mlx5e_stop_room_for_wqe(struct mlx5_core_dev *mdev, u16 wqe_si "wqe_size %u is greater than max SQ WQEBBs %u", wqe_size, mlx5e_get_max_sq_wqebbs(mdev)); - return MLX5E_STOP_ROOM(wqe_size); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 364f04309149..e3a4f01bcceb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -5694,6 +5694,13 @@ int mlx5e_attach_netdev(struct mlx5e_priv *priv) mlx5e_fs_set_state_destroy(priv->fs, !test_bit(MLX5E_STATE_DESTROYING, &priv->state)); + /* Validate the max_wqe_size_sq capability. */ + if (WARN_ON_ONCE(mlx5e_get_max_sq_wqebbs(priv->mdev) < MLX5E_MAX_TX_WQEBBS)) { + mlx5_core_warn(priv->mdev, "MLX5E: Max SQ WQEBBs firmware capability: %u, needed %lu\n", + mlx5e_get_max_sq_wqebbs(priv->mdev), MLX5E_MAX_TX_WQEBBS); + return -EIO; + } + /* max number of channels may have changed */ max_nch = mlx5e_calc_max_nch(priv->mdev, priv->netdev, profile); if (priv->channels.params.num_channels > max_nch) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 6adca01fbdc9..f7897ddb29c5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -305,6 +305,8 @@ static void mlx5e_sq_calc_wqe_attr(struct sk_buff *skb, const struct mlx5e_tx_at u16 ds_cnt_inl = 0; u16 ds_cnt_ids = 0; + /* Sync the calculation with MLX5E_MAX_TX_WQEBBS. */ + if (attr->insz) ds_cnt_ids = DIV_ROUND_UP(sizeof(struct mlx5_wqe_inline_seg) + attr->insz, MLX5_SEND_WQE_DS); @@ -317,6 +319,9 @@ static void mlx5e_sq_calc_wqe_attr(struct sk_buff *skb, const struct mlx5e_tx_at inl += VLAN_HLEN; ds_cnt_inl = DIV_ROUND_UP(inl, MLX5_SEND_WQE_DS); + if (WARN_ON_ONCE(ds_cnt_inl > MLX5E_MAX_TX_INLINE_DS)) + netdev_warn(skb->dev, "ds_cnt_inl = %u > max %u\n", ds_cnt_inl, + (u16)MLX5E_MAX_TX_INLINE_DS); ds_cnt += ds_cnt_inl; } -- cgit v1.2.3 From 8d4b475e9d0f100c3920d8bf7d392a6dac88583e Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Wed, 2 Nov 2022 23:55:43 -0700 Subject: net/mlx5e: Fix usage of DMA sync API DMA sync functions should use the same direction that was used by DMA mapping. Use DMA_BIDIRECTIONAL for XDP_TX from regular RQ, which reuses the same mapping that was used for RX, and DMA_TO_DEVICE for XDP_TX from XSK RQ and XDP_REDIRECT, which establish a new mapping in this direction. On the RX side, use the same direction that was used when setting up the mapping (DMA_BIDIRECTIONAL for XDP, DMA_FROM_DEVICE otherwise). Also don't skip sync for device when establishing a DMA_FROM_DEVICE mapping for RX, as some architectures (ARM) may require invalidating caches before the device can use the mapping. It doesn't break the bugfix made in commit 0b7cfa4082fb ("net/mlx5e: Fix page DMA map/unmap attributes"), since the bug happened on unmap. Fixes: 0b7cfa4082fb ("net/mlx5e: Fix page DMA map/unmap attributes") Fixes: b5503b994ed5 ("net/mlx5e: XDP TX forwarding support") Signed-off-by: Maxim Mikityanskiy Reviewed-by: Gal Pressman Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 27 ++++++++++++------------ 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index 4685c652c97e..20507ef2f956 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -117,7 +117,7 @@ mlx5e_xmit_xdp_buff(struct mlx5e_xdpsq *sq, struct mlx5e_rq *rq, xdpi.page.rq = rq; dma_addr = page_pool_get_dma_addr(page) + (xdpf->data - (void *)xdpf); - dma_sync_single_for_device(sq->pdev, dma_addr, xdptxd.len, DMA_TO_DEVICE); + dma_sync_single_for_device(sq->pdev, dma_addr, xdptxd.len, DMA_BIDIRECTIONAL); if (unlikely(xdp_frame_has_frags(xdpf))) { sinfo = xdp_get_shared_info_from_frame(xdpf); @@ -131,7 +131,7 @@ mlx5e_xmit_xdp_buff(struct mlx5e_xdpsq *sq, struct mlx5e_rq *rq, skb_frag_off(frag); len = skb_frag_size(frag); dma_sync_single_for_device(sq->pdev, addr, len, - DMA_TO_DEVICE); + DMA_BIDIRECTIONAL); } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 58084650151f..a61a43fc8d5c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -266,7 +266,7 @@ static inline bool mlx5e_rx_cache_get(struct mlx5e_rq *rq, union mlx5e_alloc_uni addr = page_pool_get_dma_addr(au->page); /* Non-XSK always uses PAGE_SIZE. */ - dma_sync_single_for_device(rq->pdev, addr, PAGE_SIZE, DMA_FROM_DEVICE); + dma_sync_single_for_device(rq->pdev, addr, PAGE_SIZE, rq->buff.map_dir); return true; } @@ -282,8 +282,7 @@ static inline int mlx5e_page_alloc_pool(struct mlx5e_rq *rq, union mlx5e_alloc_u return -ENOMEM; /* Non-XSK always uses PAGE_SIZE. */ - addr = dma_map_page_attrs(rq->pdev, au->page, 0, PAGE_SIZE, - rq->buff.map_dir, DMA_ATTR_SKIP_CPU_SYNC); + addr = dma_map_page(rq->pdev, au->page, 0, PAGE_SIZE, rq->buff.map_dir); if (unlikely(dma_mapping_error(rq->pdev, addr))) { page_pool_recycle_direct(rq->page_pool, au->page); au->page = NULL; @@ -427,14 +426,15 @@ mlx5e_add_skb_frag(struct mlx5e_rq *rq, struct sk_buff *skb, { dma_addr_t addr = page_pool_get_dma_addr(au->page); - dma_sync_single_for_cpu(rq->pdev, addr + frag_offset, len, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(rq->pdev, addr + frag_offset, len, + rq->buff.map_dir); page_ref_inc(au->page); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, au->page, frag_offset, len, truesize); } static inline void -mlx5e_copy_skb_header(struct device *pdev, struct sk_buff *skb, +mlx5e_copy_skb_header(struct mlx5e_rq *rq, struct sk_buff *skb, struct page *page, dma_addr_t addr, int offset_from, int dma_offset, u32 headlen) { @@ -442,7 +442,8 @@ mlx5e_copy_skb_header(struct device *pdev, struct sk_buff *skb, /* Aligning len to sizeof(long) optimizes memcpy performance */ unsigned int len = ALIGN(headlen, sizeof(long)); - dma_sync_single_for_cpu(pdev, addr + dma_offset, len, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(rq->pdev, addr + dma_offset, len, + rq->buff.map_dir); skb_copy_to_linear_data(skb, from, len); } @@ -1538,7 +1539,7 @@ mlx5e_skb_from_cqe_linear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi, addr = page_pool_get_dma_addr(au->page); dma_sync_single_range_for_cpu(rq->pdev, addr, wi->offset, - frag_size, DMA_FROM_DEVICE); + frag_size, rq->buff.map_dir); net_prefetch(data); prog = rcu_dereference(rq->xdp_prog); @@ -1587,7 +1588,7 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi addr = page_pool_get_dma_addr(au->page); dma_sync_single_range_for_cpu(rq->pdev, addr, wi->offset, - rq->buff.frame0_sz, DMA_FROM_DEVICE); + rq->buff.frame0_sz, rq->buff.map_dir); net_prefetchw(va); /* xdp_frame data area */ net_prefetch(va + rx_headroom); @@ -1608,7 +1609,7 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi addr = page_pool_get_dma_addr(au->page); dma_sync_single_for_cpu(rq->pdev, addr + wi->offset, - frag_consumed_bytes, DMA_FROM_DEVICE); + frag_consumed_bytes, rq->buff.map_dir); if (!xdp_buff_has_frags(&xdp)) { /* Init on the first fragment to avoid cold cache access @@ -1905,7 +1906,7 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w mlx5e_fill_skb_data(skb, rq, au, byte_cnt, frag_offset); /* copy header */ addr = page_pool_get_dma_addr(head_au->page); - mlx5e_copy_skb_header(rq->pdev, skb, head_au->page, addr, + mlx5e_copy_skb_header(rq, skb, head_au->page, addr, head_offset, head_offset, headlen); /* skb linear part was allocated with headlen and aligned to long */ skb->tail += headlen; @@ -1939,7 +1940,7 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, addr = page_pool_get_dma_addr(au->page); dma_sync_single_range_for_cpu(rq->pdev, addr, head_offset, - frag_size, DMA_FROM_DEVICE); + frag_size, rq->buff.map_dir); net_prefetch(data); prog = rcu_dereference(rq->xdp_prog); @@ -1987,7 +1988,7 @@ mlx5e_skb_from_cqe_shampo(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, if (likely(frag_size <= BIT(MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE))) { /* build SKB around header */ - dma_sync_single_range_for_cpu(rq->pdev, head->addr, 0, frag_size, DMA_FROM_DEVICE); + dma_sync_single_range_for_cpu(rq->pdev, head->addr, 0, frag_size, rq->buff.map_dir); prefetchw(hdr); prefetch(data); skb = mlx5e_build_linear_skb(rq, hdr, frag_size, rx_headroom, head_size, 0); @@ -2009,7 +2010,7 @@ mlx5e_skb_from_cqe_shampo(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, } prefetchw(skb->data); - mlx5e_copy_skb_header(rq->pdev, skb, head->page, head->addr, + mlx5e_copy_skb_header(rq, skb, head->page, head->addr, head_offset + rx_headroom, rx_headroom, head_size); /* skb linear part was allocated with headlen and aligned to long */ -- cgit v1.2.3 From 08912ea799cd2a43b8999457e316967fe4e2f327 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Wed, 2 Nov 2022 23:55:44 -0700 Subject: net/mlx5e: Fix tc acts array not to be dependent on enum order The tc acts array should not be dependent on kernel internal flow action id enum. Fix the array initialization. Fixes: fad547906980 ("net/mlx5e: Add tc action infrastructure") Signed-off-by: Roi Dayan Reviewed-by: Maor Dickman Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en/tc/act/act.c | 92 ++++++++-------------- 1 file changed, 32 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c index 305fde62a78d..3337241cfd84 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c @@ -6,70 +6,42 @@ #include "en/tc_priv.h" #include "mlx5_core.h" -/* Must be aligned with enum flow_action_id. */ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = { - &mlx5e_tc_act_accept, - &mlx5e_tc_act_drop, - &mlx5e_tc_act_trap, - &mlx5e_tc_act_goto, - &mlx5e_tc_act_mirred, - &mlx5e_tc_act_mirred, - &mlx5e_tc_act_redirect_ingress, - NULL, /* FLOW_ACTION_MIRRED_INGRESS, */ - &mlx5e_tc_act_vlan, - &mlx5e_tc_act_vlan, - &mlx5e_tc_act_vlan_mangle, - &mlx5e_tc_act_tun_encap, - &mlx5e_tc_act_tun_decap, - &mlx5e_tc_act_pedit, - &mlx5e_tc_act_pedit, - &mlx5e_tc_act_csum, - NULL, /* FLOW_ACTION_MARK, */ - &mlx5e_tc_act_ptype, - NULL, /* FLOW_ACTION_PRIORITY, */ - NULL, /* FLOW_ACTION_WAKE, */ - NULL, /* FLOW_ACTION_QUEUE, */ - &mlx5e_tc_act_sample, - &mlx5e_tc_act_police, - &mlx5e_tc_act_ct, - NULL, /* FLOW_ACTION_CT_METADATA, */ - &mlx5e_tc_act_mpls_push, - &mlx5e_tc_act_mpls_pop, - NULL, /* FLOW_ACTION_MPLS_MANGLE, */ - NULL, /* FLOW_ACTION_GATE, */ - NULL, /* FLOW_ACTION_PPPOE_PUSH, */ - NULL, /* FLOW_ACTION_JUMP, */ - NULL, /* FLOW_ACTION_PIPE, */ - &mlx5e_tc_act_vlan, - &mlx5e_tc_act_vlan, + [FLOW_ACTION_ACCEPT] = &mlx5e_tc_act_accept, + [FLOW_ACTION_DROP] = &mlx5e_tc_act_drop, + [FLOW_ACTION_TRAP] = &mlx5e_tc_act_trap, + [FLOW_ACTION_GOTO] = &mlx5e_tc_act_goto, + [FLOW_ACTION_REDIRECT] = &mlx5e_tc_act_mirred, + [FLOW_ACTION_MIRRED] = &mlx5e_tc_act_mirred, + [FLOW_ACTION_REDIRECT_INGRESS] = &mlx5e_tc_act_redirect_ingress, + [FLOW_ACTION_VLAN_PUSH] = &mlx5e_tc_act_vlan, + [FLOW_ACTION_VLAN_POP] = &mlx5e_tc_act_vlan, + [FLOW_ACTION_VLAN_MANGLE] = &mlx5e_tc_act_vlan_mangle, + [FLOW_ACTION_TUNNEL_ENCAP] = &mlx5e_tc_act_tun_encap, + [FLOW_ACTION_TUNNEL_DECAP] = &mlx5e_tc_act_tun_decap, + [FLOW_ACTION_MANGLE] = &mlx5e_tc_act_pedit, + [FLOW_ACTION_ADD] = &mlx5e_tc_act_pedit, + [FLOW_ACTION_CSUM] = &mlx5e_tc_act_csum, + [FLOW_ACTION_PTYPE] = &mlx5e_tc_act_ptype, + [FLOW_ACTION_SAMPLE] = &mlx5e_tc_act_sample, + [FLOW_ACTION_POLICE] = &mlx5e_tc_act_police, + [FLOW_ACTION_CT] = &mlx5e_tc_act_ct, + [FLOW_ACTION_MPLS_PUSH] = &mlx5e_tc_act_mpls_push, + [FLOW_ACTION_MPLS_POP] = &mlx5e_tc_act_mpls_pop, + [FLOW_ACTION_VLAN_PUSH_ETH] = &mlx5e_tc_act_vlan, + [FLOW_ACTION_VLAN_POP_ETH] = &mlx5e_tc_act_vlan, }; -/* Must be aligned with enum flow_action_id. */ static struct mlx5e_tc_act *tc_acts_nic[NUM_FLOW_ACTIONS] = { - &mlx5e_tc_act_accept, - &mlx5e_tc_act_drop, - NULL, /* FLOW_ACTION_TRAP, */ - &mlx5e_tc_act_goto, - &mlx5e_tc_act_mirred_nic, - NULL, /* FLOW_ACTION_MIRRED, */ - NULL, /* FLOW_ACTION_REDIRECT_INGRESS, */ - NULL, /* FLOW_ACTION_MIRRED_INGRESS, */ - NULL, /* FLOW_ACTION_VLAN_PUSH, */ - NULL, /* FLOW_ACTION_VLAN_POP, */ - NULL, /* FLOW_ACTION_VLAN_MANGLE, */ - NULL, /* FLOW_ACTION_TUNNEL_ENCAP, */ - NULL, /* FLOW_ACTION_TUNNEL_DECAP, */ - &mlx5e_tc_act_pedit, - &mlx5e_tc_act_pedit, - &mlx5e_tc_act_csum, - &mlx5e_tc_act_mark, - NULL, /* FLOW_ACTION_PTYPE, */ - NULL, /* FLOW_ACTION_PRIORITY, */ - NULL, /* FLOW_ACTION_WAKE, */ - NULL, /* FLOW_ACTION_QUEUE, */ - NULL, /* FLOW_ACTION_SAMPLE, */ - NULL, /* FLOW_ACTION_POLICE, */ - &mlx5e_tc_act_ct, + [FLOW_ACTION_ACCEPT] = &mlx5e_tc_act_accept, + [FLOW_ACTION_DROP] = &mlx5e_tc_act_drop, + [FLOW_ACTION_GOTO] = &mlx5e_tc_act_goto, + [FLOW_ACTION_REDIRECT] = &mlx5e_tc_act_mirred_nic, + [FLOW_ACTION_MANGLE] = &mlx5e_tc_act_pedit, + [FLOW_ACTION_ADD] = &mlx5e_tc_act_pedit, + [FLOW_ACTION_CSUM] = &mlx5e_tc_act_csum, + [FLOW_ACTION_MARK] = &mlx5e_tc_act_mark, + [FLOW_ACTION_CT] = &mlx5e_tc_act_ct, }; /** -- cgit v1.2.3 From 9e06430841363a1d2932d546fdce1cc5edb3c2a0 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Wed, 2 Nov 2022 23:55:45 -0700 Subject: net/mlx5e: TC, Fix wrong rejection of packet-per-second policing In the bellow commit, we added support for PPS policing without removing the check which block offload of such cases. Fix it by removing this check. Fixes: a8d52b024d6d ("net/mlx5e: TC, Support offloading police action") Signed-off-by: Jianbo Liu Reviewed-by: Maor Dickman Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index dd6fea9e9a5b..372dfb89e396 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -4758,12 +4758,6 @@ int mlx5e_policer_validate(const struct flow_action *action, return -EOPNOTSUPP; } - if (act->police.rate_pkt_ps) { - NL_SET_ERR_MSG_MOD(extack, - "QoS offload not support packets per second"); - return -EOPNOTSUPP; - } - return 0; } -- cgit v1.2.3 From f4f4096b410e8d31c3f07f39de3b17d144edd53d Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Wed, 2 Nov 2022 23:55:46 -0700 Subject: net/mlx5e: E-Switch, Fix comparing termination table instance The pkt_reformat pointer being saved under flow_act and not dest attribute in the termination table instance. Fix the comparison pointers. Also fix returning success if one pkt_reformat pointer is null and the other is not. Fixes: 249ccc3c95bd ("net/mlx5e: Add support for offloading traffic from uplink to uplink") Signed-off-by: Roi Dayan Reviewed-by: Chris Mi Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c index ee568bf34ae2..108a3503f413 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c @@ -30,9 +30,9 @@ mlx5_eswitch_termtbl_hash(struct mlx5_flow_act *flow_act, sizeof(dest->vport.num), hash); hash = jhash((const void *)&dest->vport.vhca_id, sizeof(dest->vport.num), hash); - if (dest->vport.pkt_reformat) - hash = jhash(dest->vport.pkt_reformat, - sizeof(*dest->vport.pkt_reformat), + if (flow_act->pkt_reformat) + hash = jhash(flow_act->pkt_reformat, + sizeof(*flow_act->pkt_reformat), hash); return hash; } @@ -53,9 +53,11 @@ mlx5_eswitch_termtbl_cmp(struct mlx5_flow_act *flow_act1, if (ret) return ret; - return dest1->vport.pkt_reformat && dest2->vport.pkt_reformat ? - memcmp(dest1->vport.pkt_reformat, dest2->vport.pkt_reformat, - sizeof(*dest1->vport.pkt_reformat)) : 0; + if (flow_act1->pkt_reformat && flow_act2->pkt_reformat) + return memcmp(flow_act1->pkt_reformat, flow_act2->pkt_reformat, + sizeof(*flow_act1->pkt_reformat)); + + return !(flow_act1->pkt_reformat == flow_act2->pkt_reformat); } static int -- cgit v1.2.3 From 7f1a6d4b9e820b08479a07f6e14c36ccfa641751 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Wed, 2 Nov 2022 23:55:47 -0700 Subject: net/mlx5e: TC, Fix slab-out-of-bounds in parse_tc_actions esw_attr is only allocated if namespace is fdb. BUG: KASAN: slab-out-of-bounds in parse_tc_actions+0xdc6/0x10e0 [mlx5_core] Write of size 4 at addr ffff88815f185b04 by task tc/2135 CPU: 5 PID: 2135 Comm: tc Not tainted 6.1.0-rc2+ #2 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x57/0x7d print_report+0x170/0x471 ? parse_tc_actions+0xdc6/0x10e0 [mlx5_core] kasan_report+0xbc/0xf0 ? parse_tc_actions+0xdc6/0x10e0 [mlx5_core] parse_tc_actions+0xdc6/0x10e0 [mlx5_core] Fixes: 94d651739e17 ("net/mlx5e: TC, Fix cloned flow attr instance dests are not zeroed") Signed-off-by: Roi Dayan Reviewed-by: Maor Dickman Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 372dfb89e396..5a6aa61ec82a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3633,10 +3633,14 @@ mlx5e_clone_flow_attr_for_post_act(struct mlx5_flow_attr *attr, attr2->action = 0; attr2->flags = 0; attr2->parse_attr = parse_attr; - attr2->esw_attr->out_count = 0; - attr2->esw_attr->split_count = 0; attr2->dest_chain = 0; attr2->dest_ft = NULL; + + if (ns_type == MLX5_FLOW_NAMESPACE_FDB) { + attr2->esw_attr->out_count = 0; + attr2->esw_attr->split_count = 0; + } + return attr2; } -- cgit v1.2.3 From f23df5220d2bf8d5e639f074b76f206a736d09e1 Mon Sep 17 00:00:00 2001 From: Norbert Zulinski Date: Mon, 10 Oct 2022 10:22:22 -0400 Subject: ice: Fix spurious interrupt during removal of trusted VF Previously, during removal of trusted VF when VF is down there was number of spurious interrupt equal to number of queues on VF. Add check if VF already has inactive queues. If VF is disabled and has inactive rx queues then do not disable rx queues. Add check in ice_vsi_stop_tx_ring if it's VF's vsi and if VF is disabled. Fixes: efe41860008e ("ice: Fix memory corruption in VF driver") Signed-off-by: Norbert Zulinski Signed-off-by: Mateusz Palczewski Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_base.c | 2 +- drivers/net/ethernet/intel/ice/ice_lib.c | 25 +++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_lib.h | 1 + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 5 ++++- 4 files changed, 31 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c index 9e36f01dfa4f..e864634d66bc 100644 --- a/drivers/net/ethernet/intel/ice/ice_base.c +++ b/drivers/net/ethernet/intel/ice/ice_base.c @@ -958,7 +958,7 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, * associated to the queue to schedule NAPI handler */ q_vector = ring->q_vector; - if (q_vector) + if (q_vector && !(vsi->vf && ice_is_vf_disabled(vsi->vf))) ice_trigger_sw_intr(hw, q_vector); status = ice_dis_vsi_txq(vsi->port_info, txq_meta->vsi_idx, diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 938ba8c215cb..7276badfa19e 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2239,6 +2239,31 @@ int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi) return ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0, vsi->xdp_rings, vsi->num_xdp_txq); } +/** + * ice_vsi_is_rx_queue_active + * @vsi: the VSI being configured + * + * Return true if at least one queue is active. + */ +bool ice_vsi_is_rx_queue_active(struct ice_vsi *vsi) +{ + struct ice_pf *pf = vsi->back; + struct ice_hw *hw = &pf->hw; + int i; + + ice_for_each_rxq(vsi, i) { + u32 rx_reg; + int pf_q; + + pf_q = vsi->rxq_map[i]; + rx_reg = rd32(hw, QRX_CTRL(pf_q)); + if (rx_reg & QRX_CTRL_QENA_STAT_M) + return true; + } + + return false; +} + /** * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not * @vsi: VSI to check whether or not VLAN pruning is enabled. diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index ec4bf0c89857..dcdf69a693e9 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -129,4 +129,5 @@ u16 ice_vsi_num_non_zero_vlans(struct ice_vsi *vsi); bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f); void ice_clear_feature_support(struct ice_pf *pf, enum ice_feature f); void ice_init_feature_support(struct ice_pf *pf); +bool ice_vsi_is_rx_queue_active(struct ice_vsi *vsi); #endif /* !_ICE_LIB_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index 0abeed092de1..1c51778db951 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -576,7 +576,10 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) return -EINVAL; } ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id); - ice_vsi_stop_all_rx_rings(vsi); + + if (ice_vsi_is_rx_queue_active(vsi)) + ice_vsi_stop_all_rx_rings(vsi); + dev_dbg(dev, "VF is already disabled, there is no need for resetting it, telling VM, all is fine %d\n", vf->vf_id); return 0; -- cgit v1.2.3 From 0e710a3ffd0caaf23b8791b041e8792f252f8e4f Mon Sep 17 00:00:00 2001 From: Michal Jaron Date: Fri, 14 Oct 2022 10:45:37 +0200 Subject: iavf: Fix VF driver counting VLAN 0 filters VF driver mistakenly counts VLAN 0 filters, when no PF driver counts them. Do not count VLAN 0 filters, when VLAN_V2 is engaged. Counting those filters in, will affect filters size by -1, when sending batched VLAN addition message. Fixes: 968996c070ef ("iavf: Fix VLAN_V2 addition/rejection") Signed-off-by: Przemyslaw Patynowski Signed-off-by: Michal Jaron Signed-off-by: Kamil Maziarz Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 5a9e6563923e..24a701fd140e 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -2438,6 +2438,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, list_for_each_entry(f, &adapter->vlan_filter_list, list) { if (f->is_new_vlan) { f->is_new_vlan = false; + if (!f->vlan.vid) + continue; if (f->vlan.tpid == ETH_P_8021Q) set_bit(f->vlan.vid, adapter->vsi.active_cvlans); -- cgit v1.2.3 From bcde9dad1bfa3754e004c14774d42e1f1210efe9 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Thu, 3 Nov 2022 11:05:19 +0800 Subject: drm/amd/pm: update SMU IP v13.0.4 msg interface header Some of the unused messages that were used earlier in development have been freed up as spare messages, no intended functional changes. Signed-off-by: Mario Limonciello Signed-off-by: Tim Huang Acked-by: Alex Deucher Reviewed-by: Yifan Zhang Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h index d9b0cd752200..f4d6c07b56ea 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h @@ -54,14 +54,14 @@ #define PPSMC_MSG_TestMessage 0x01 ///< To check if PMFW is alive and responding. Requirement specified by PMFW team #define PPSMC_MSG_GetPmfwVersion 0x02 ///< Get PMFW version #define PPSMC_MSG_GetDriverIfVersion 0x03 ///< Get PMFW_DRIVER_IF version -#define PPSMC_MSG_EnableGfxOff 0x04 ///< Enable GFXOFF -#define PPSMC_MSG_DisableGfxOff 0x05 ///< Disable GFXOFF +#define PPSMC_MSG_SPARE0 0x04 ///< SPARE +#define PPSMC_MSG_SPARE1 0x05 ///< SPARE #define PPSMC_MSG_PowerDownVcn 0x06 ///< Power down VCN #define PPSMC_MSG_PowerUpVcn 0x07 ///< Power up VCN; VCN is power gated by default #define PPSMC_MSG_SetHardMinVcn 0x08 ///< For wireless display #define PPSMC_MSG_SetSoftMinGfxclk 0x09 ///< Set SoftMin for GFXCLK, argument is frequency in MHz -#define PPSMC_MSG_ActiveProcessNotify 0x0A ///< Needs update -#define PPSMC_MSG_ForcePowerDownGfx 0x0B ///< Force power down GFX, i.e. enter GFXOFF +#define PPSMC_MSG_SPARE2 0x0A ///< SPARE +#define PPSMC_MSG_SPARE3 0x0B ///< SPARE #define PPSMC_MSG_PrepareMp1ForUnload 0x0C ///< Prepare PMFW for GFX driver unload #define PPSMC_MSG_SetDriverDramAddrHigh 0x0D ///< Set high 32 bits of DRAM address for Driver table transfer #define PPSMC_MSG_SetDriverDramAddrLow 0x0E ///< Set low 32 bits of DRAM address for Driver table transfer @@ -73,8 +73,7 @@ #define PPSMC_MSG_SetSoftMinFclk 0x14 ///< Set hard min for FCLK #define PPSMC_MSG_SetSoftMinVcn 0x15 ///< Set soft min for VCN clocks (VCLK and DCLK) - -#define PPSMC_MSG_EnableGfxImu 0x16 ///< Needs update +#define PPSMC_MSG_EnableGfxImu 0x16 ///< Enable GFX IMU #define PPSMC_MSG_GetGfxclkFrequency 0x17 ///< Get GFX clock frequency #define PPSMC_MSG_GetFclkFrequency 0x18 ///< Get FCLK frequency @@ -102,8 +101,8 @@ #define PPSMC_MSG_SetHardMinIspxclkByFreq 0x2C ///< Set HardMin by frequency for ISPXCLK #define PPSMC_MSG_PowerDownUmsch 0x2D ///< Power down VCN.UMSCH (aka VSCH) scheduler #define PPSMC_MSG_PowerUpUmsch 0x2E ///< Power up VCN.UMSCH (aka VSCH) scheduler -#define PPSMC_Message_IspStutterOn_MmhubPgDis 0x2F ///< ISP StutterOn mmHub PgDis -#define PPSMC_Message_IspStutterOff_MmhubPgEn 0x30 ///< ISP StufferOff mmHub PgEn +#define PPSMC_MSG_IspStutterOn_MmhubPgDis 0x2F ///< ISP StutterOn mmHub PgDis +#define PPSMC_MSG_IspStutterOff_MmhubPgEn 0x30 ///< ISP StufferOff mmHub PgEn #define PPSMC_Message_Count 0x31 ///< Total number of PPSMC messages /** @}*/ -- cgit v1.2.3 From 2d2ccc4cbf440931843e64974da9fcd129d401a8 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Thu, 3 Nov 2022 17:01:46 -0400 Subject: drm/amdkfd: Fix error handling in kfd_criu_restore_events mutex_unlock before the exit label because all the error code paths that jump there didn't take that lock. This fixes unbalanced locking errors in case of restore errors. Fixes: 40e8a766a761 ("drm/amdkfd: CRIU checkpoint and restore events") Signed-off-by: Felix Kuehling Reviewed-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 83e3ce9f6049..729d26d648af 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -506,6 +506,7 @@ int kfd_criu_restore_event(struct file *devkfd, ret = create_other_event(p, ev, &ev_priv->event_id); break; } + mutex_unlock(&p->event_mutex); exit: if (ret) @@ -513,8 +514,6 @@ exit: kfree(ev_priv); - mutex_unlock(&p->event_mutex); - return ret; } -- cgit v1.2.3 From a0fba3e078801b9596e61a0687d398664cdc36e6 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Tue, 1 Nov 2022 15:02:48 -0400 Subject: drm/amdkfd: Fix error handling in criu_checkpoint Checkpoint BOs last. That way we don't need to close dmabuf FDs if something else fails later. This avoids problematic access to user mode memory in the error handling code path. criu_checkpoint_bos has its own error handling and cleanup that does not depend on access to user memory. In the private data, keep BOs before the remaining objects. This is necessary to restore things in the correct order as restoring events depends on the events-page BO being restored first. Fixes: be072b06c739 ("drm/amdkfd: CRIU export BOs as prime dmabuf objects") Reported-by: Jann Horn CC: Rajneesh Bhardwaj Signed-off-by: Felix Kuehling Reviewed-and-tested-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 34 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 5feaba6a77de..6d291aa6386b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1950,7 +1950,7 @@ static int criu_checkpoint(struct file *filep, { int ret; uint32_t num_devices, num_bos, num_objects; - uint64_t priv_size, priv_offset = 0; + uint64_t priv_size, priv_offset = 0, bo_priv_offset; if (!args->devices || !args->bos || !args->priv_data) return -EINVAL; @@ -1994,38 +1994,34 @@ static int criu_checkpoint(struct file *filep, if (ret) goto exit_unlock; - ret = criu_checkpoint_bos(p, num_bos, (uint8_t __user *)args->bos, - (uint8_t __user *)args->priv_data, &priv_offset); - if (ret) - goto exit_unlock; + /* Leave room for BOs in the private data. They need to be restored + * before events, but we checkpoint them last to simplify the error + * handling. + */ + bo_priv_offset = priv_offset; + priv_offset += num_bos * sizeof(struct kfd_criu_bo_priv_data); if (num_objects) { ret = kfd_criu_checkpoint_queues(p, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) - goto close_bo_fds; + goto exit_unlock; ret = kfd_criu_checkpoint_events(p, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) - goto close_bo_fds; + goto exit_unlock; ret = kfd_criu_checkpoint_svm(p, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) - goto close_bo_fds; + goto exit_unlock; } -close_bo_fds: - if (ret) { - /* If IOCTL returns err, user assumes all FDs opened in criu_dump_bos are closed */ - uint32_t i; - struct kfd_criu_bo_bucket *bo_buckets = (struct kfd_criu_bo_bucket *) args->bos; - - for (i = 0; i < num_bos; i++) { - if (bo_buckets[i].alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) - close_fd(bo_buckets[i].dmabuf_fd); - } - } + /* This must be the last thing in this function that can fail. + * Otherwise we leak dmabuf file descriptors. + */ + ret = criu_checkpoint_bos(p, num_bos, (uint8_t __user *)args->bos, + (uint8_t __user *)args->priv_data, &bo_priv_offset); exit_unlock: mutex_unlock(&p->mutex); -- cgit v1.2.3 From f9e69496450352fa0504fd5a8fd9134b31116558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 2 Nov 2022 14:55:13 +0100 Subject: drm/amdgpu: workaround for TLB seq race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can happen that we query the sequence value before the callback had a chance to run. Workaround that by grabbing the fence lock and releasing it again. Should be replaced by hw handling soon. Signed-off-by: Christian König CC: stable@vger.kernel.org # 5.19+ Fixes: 5255e146c99a6 ("drm/amdgpu: rework TLB flushing") Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2113 Acked-by: Alex Deucher Acked-by: Philip Yang Tested-by: Stefan Springer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 83acb7bd80fe..1d31771b4230 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -492,6 +492,21 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m); */ static inline uint64_t amdgpu_vm_tlb_seq(struct amdgpu_vm *vm) { + unsigned long flags; + spinlock_t *lock; + + /* + * Workaround to stop racing between the fence signaling and handling + * the cb. The lock is static after initially setting it up, just make + * sure that the dma_fence structure isn't freed up. + */ + rcu_read_lock(); + lock = vm->last_tlb_flush->lock; + rcu_read_unlock(); + + spin_lock_irqsave(lock, flags); + spin_unlock_irqrestore(lock, flags); + return atomic64_read(&vm->tlb_seq); } -- cgit v1.2.3 From 00efc965a7b7990e63e3506e6d240e6271bd8571 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Mon, 24 Oct 2022 13:39:02 -0400 Subject: drm/amd/display: Wait for VBLANK during pipe programming [Description] - Wait for vblank during front end programming for global sync to ensure all double buffer updates take. - This prevents underflow in some cases. Reviewed-by: Martin Leung Acked-by: Alan Liu Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index f3334f513eb4..b465a83bde6f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1663,6 +1663,7 @@ static void dcn20_program_pipe( pipe_ctx->pipe_dlg_param.vupdate_width); if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); } -- cgit v1.2.3 From ea8626425859cf99de0c7f7e5b2c485d5f19b20e Mon Sep 17 00:00:00 2001 From: Leo Ma Date: Thu, 15 Sep 2022 12:03:04 -0400 Subject: drm/amd/display: Adding HDMI SCDC DEVICE_ID define [Why && How] We will need to differentiate vendor behavior in the future. Reviewed-by: Chris Park Acked-by: Alan Liu Signed-off-by: Leo Ma Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 651231387043..ce8d6a54ca54 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -82,6 +82,7 @@ struct dp_hdmi_dongle_signature_data { #define HDMI_SCDC_STATUS_FLAGS 0x40 #define HDMI_SCDC_ERR_DETECT 0x50 #define HDMI_SCDC_TEST_CONFIG 0xC0 +#define HDMI_SCDC_DEVICE_ID 0xD3 union hdmi_scdc_update_read_data { uint8_t byte[2]; -- cgit v1.2.3 From f7085cbf117e4fc2af96790cbc34f5a38a236943 Mon Sep 17 00:00:00 2001 From: Max Tseng Date: Mon, 17 Oct 2022 20:55:36 +0800 Subject: drm/amd/display: Cursor update refactor: PSR-SU support condition [Why] PSR-SU requires extra conditions while cursor update. Reviewed-by: Robin Chen Acked-by: Alan Liu Signed-off-by: Max Tseng Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 67eef5beab95..4cb912bf400b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -859,11 +859,59 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) diag_data.is_cw6_enabled); } +static bool dc_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) +{ + struct pipe_ctx *test_pipe, *split_pipe; + const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data; + struct rect r1 = scl_data->recout, r2, r2_half; + int r1_r = r1.x + r1.width, r1_b = r1.y + r1.height, r2_r, r2_b; + int cur_layer = pipe_ctx->plane_state->layer_index; + + /** + * Disable the cursor if there's another pipe above this with a + * plane that contains this pipe's viewport to prevent double cursor + * and incorrect scaling artifacts. + */ + for (test_pipe = pipe_ctx->top_pipe; test_pipe; + test_pipe = test_pipe->top_pipe) { + // Skip invisible layer and pipe-split plane on same layer + if (!test_pipe->plane_state->visible || test_pipe->plane_state->layer_index == cur_layer) + continue; + + r2 = test_pipe->plane_res.scl_data.recout; + r2_r = r2.x + r2.width; + r2_b = r2.y + r2.height; + split_pipe = test_pipe; + + /** + * There is another half plane on same layer because of + * pipe-split, merge together per same height. + */ + for (split_pipe = pipe_ctx->top_pipe; split_pipe; + split_pipe = split_pipe->top_pipe) + if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) { + r2_half = split_pipe->plane_res.scl_data.recout; + r2.x = (r2_half.x < r2.x) ? r2_half.x : r2.x; + r2.width = r2.width + r2_half.width; + r2_r = r2.x + r2.width; + break; + } + + if (r1.x >= r2.x && r1.y >= r2.y && r1_r <= r2_r && r1_b <= r2_b) + return true; + } + + return false; +} + static bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx) { if (pipe_ctx->plane_state != NULL) { if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) return false; + + if (dc_can_pipe_disable_cursor(pipe_ctx)) + return false; } if ((pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 || -- cgit v1.2.3 From a36021b1fccf1807a5557f35b0b407f1c1a65743 Mon Sep 17 00:00:00 2001 From: Nawwar Ali Date: Wed, 19 Oct 2022 17:57:06 +0800 Subject: drm/amd/display: Update 709 gamma to 2.222 as stated in the standerd [WHY] Previously driver use gamma 2.2 for 709 color space, but the standard is to use gamma of 2.222 [HOW] Change it gamma to 2.222 Reviewed-by: Krunoslav Kovac Acked-by: Alan Liu Signed-off-by: Nawwar Ali Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color_gamma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index 447a0ec9cbe2..f6034213c700 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -61,7 +61,7 @@ static const int32_t numerator01[] = { 31308, 180000, 0, 0, 0}; static const int32_t numerator02[] = { 12920, 4500, 0, 0, 0}; static const int32_t numerator03[] = { 55, 99, 0, 0, 0}; static const int32_t numerator04[] = { 55, 99, 0, 0, 0}; -static const int32_t numerator05[] = { 2400, 2200, 2200, 2400, 2600}; +static const int32_t numerator05[] = { 2400, 2222, 2200, 2400, 2600}; /* one-time setup of X points */ void setup_x_points_distribution(void) -- cgit v1.2.3 From 5abb360ba74f59cc7ea5a4ab149c49d70d869239 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 24 Oct 2022 12:18:41 -0400 Subject: drm/amd/display: Consider dp cable id only when data is non zero Cable ID is a DP2 feature to identify max certified link rate that a cable can carry. The cable identification method requires both cable and display hardware support. Since the specs comes late, it is anticipated that the first round of DP2 cables and displays may not be fully compatible to reliably return cable ID data. Therefore the decision of our cable id policy is that if the cable can return non zero cable id data, we will take cable's link rate capability into account. However if we get zero data, the cable link rate capability is considered inconclusive. In this case, we will not take cable's capability into account to avoid of over limiting hardware capability from users. The max overall link rate capability is still determined after actual dp pre-training. Cable id is considered as an auxiliary method of determining max link bandwidth capability. Reviewed-by: George Shen Acked-by: Alan Liu Signed-off-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e5ab751a5ca1..b0cfe21871e4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3020,7 +3020,7 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) static enum dc_link_rate get_cable_max_link_rate(struct dc_link *link) { - enum dc_link_rate cable_max_link_rate = LINK_RATE_HIGH3; + enum dc_link_rate cable_max_link_rate = LINK_RATE_UNKNOWN; if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR20) cable_max_link_rate = LINK_RATE_UHBR20; @@ -3083,15 +3083,29 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) max_link_cap.link_spread = link->reported_link_cap.link_spread; - /* Lower link settings based on cable attributes */ + /* Lower link settings based on cable attributes + * Cable ID is a DP2 feature to identify max certified link rate that + * a cable can carry. The cable identification method requires both + * cable and display hardware support. Since the specs comes late, it is + * anticipated that the first round of DP2 cables and displays may not + * be fully compatible to reliably return cable ID data. Therefore the + * decision of our cable id policy is that if the cable can return non + * zero cable id data, we will take cable's link rate capability into + * account. However if we get zero data, the cable link rate capability + * is considered inconclusive. In this case, we will not take cable's + * capability into account to avoid of over limiting hardware capability + * from users. The max overall link rate capability is still determined + * after actual dp pre-training. Cable id is considered as an auxiliary + * method of determining max link bandwidth capability. + */ cable_max_link_rate = get_cable_max_link_rate(link); if (!link->dc->debug.ignore_cable_id && + cable_max_link_rate != LINK_RATE_UNKNOWN && cable_max_link_rate < max_link_cap.link_rate) max_link_cap.link_rate = cable_max_link_rate; - /* - * account for lttpr repeaters cap + /* account for lttpr repeaters cap * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3). */ if (dp_is_lttpr_present(link)) { -- cgit v1.2.3 From 1a2b886b1f242044840147347db1a595cd7f5f56 Mon Sep 17 00:00:00 2001 From: Ryan Lin Date: Wed, 26 Oct 2022 15:12:26 +0800 Subject: drm/amd/display: Waiting for 1 frame to fix the flash issue on PSR1 [Why] Needs more frames waiting before the PSR_Exit sending for the specific TCON. [How] Add relock_delay_frame_cnt to control how many frames waiting are needed before the PSR_Exit sending. The default value is 0. The Driver side can set this variable for specific TCONs. Reviewed-by: Robin Chen Acked-by: Alan Liu Signed-off-by: Ryan Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 5 +++++ drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index cda1592c3a5b..2d3201b77d6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -413,6 +413,11 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, else copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 0; + //WA for PSR1 on specific TCON, require frame delay for frame re-lock + copy_settings_data->relock_delay_frame_cnt = 0; + if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) + copy_settings_data->relock_delay_frame_cnt = 2; + dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); dc_dmub_srv_cmd_execute(dc->dmub_srv); dc_dmub_srv_wait_idle(dc->dmub_srv); diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 9df330c86a55..34b03bc7f838 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -1876,10 +1876,14 @@ struct dmub_cmd_psr_copy_settings_data { * Use FSM state for PSR power up/down */ uint8_t use_phy_fsm; + /** + * frame delay for frame re-lock + */ + uint8_t relock_delay_frame_cnt; /** * Explicit padding to 2 byte boundary. */ - uint8_t pad3[2]; + uint8_t pad3; }; /** -- cgit v1.2.3 From 4df7e2c8d7783f53863725e21efefde19d85402f Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 25 Oct 2022 11:26:04 -0400 Subject: drm/amd/display: Update SR watermarks for DCN314 [Why & How] New values requested by hardware after fine-tuning. Update for all memory types. Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 32 +++++++++++----------- .../gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index 1131c6d73f6c..20a06c04e4a1 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -363,32 +363,32 @@ static struct wm_table ddr5_wm_table = { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 14.5, .valid = true, }, { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 14.5, .valid = true, }, { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 14.5, .valid = true, }, { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 14.5, .valid = true, }, } @@ -400,32 +400,32 @@ static struct wm_table lpddr5_wm_table = { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .valid = true, }, { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .valid = true, }, { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .valid = true, }, { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .valid = true, }, } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index cf420ad2b8dc..34b6c763a455 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -146,8 +146,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { }, }, .num_states = 5, - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .sr_exit_z8_time_us = 442.0, .sr_enter_plus_exit_z8_time_us = 560.0, .writeback_latency_us = 12.0, -- cgit v1.2.3 From b17710f42d4b57fa2353b1aeff02920c9560e2e7 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 25 Oct 2022 11:31:30 -0400 Subject: drm/amd/display: Allow tuning DCN314 bounding box [Why] We're missing the helpers from dcn20 that would allow overriding these with DC debug options. [How] Use dcn20_patch_bounding_box to support overriding all the relevant values. Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index 34b6c763a455..796c9d19e671 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -264,11 +264,8 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; } - if ((int)(dcn3_14_soc.dram_clock_change_latency_us * 1000) - != dc->debug.dram_clock_change_latency_ns - && dc->debug.dram_clock_change_latency_ns) { - dcn3_14_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000; - } + dcn20_patch_bounding_box(dc, &dcn3_14_soc); + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN314); else -- cgit v1.2.3 From a1b6667ef90b38e2480d96f11414fcb923c13ba2 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Thu, 20 Oct 2022 17:26:24 -0400 Subject: drm/amd/display: Zeromem mypipe heap struct before using it [Why&How] Bug was caused when moving variable from stack to heap because it was reusable and garbage was left over, so we need to zero mem. Reviewed-by: Martin Leung Acked-by: Alan Liu Signed-off-by: Aurabindo Pillai Signed-off-by: Martin Leung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 3d184679f129..ae6e6abc620b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -3192,6 +3192,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.FCLKChangeLatency, mode_lib->vba.UrgLatency[i], mode_lib->vba.SREnterPlusExitTime); + memset(&v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull, 0, sizeof(DmlPipe)); v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.myPipe.Dppclk = mode_lib->vba.RequiredDPPCLK[i][j][k]; v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.myPipe.Dispclk = mode_lib->vba.RequiredDISPCLK[i][j]; v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.myPipe.PixelClock = mode_lib->vba.PixelClock[k]; -- cgit v1.2.3 From 9e7d03e8b046c84e1b2973a29cd800495a5a2f09 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 20 Oct 2022 18:33:05 -0400 Subject: drm/amd/display: Use min transition for SubVP into MPO [Description] - For SubVP transitioning into MPO, we want to use a minimal transition to prevent transient underflow - Transitioning a phantom pipe directly into a "real" pipe can result in underflow due to the HUBP still having it's "phantom" programming when HUBP is unblanked (have to wait for next VUPDATE of the new OTG) - Also ensure subvp pipe lock is acquired early enough for programming in dc_commit_state_no_check - When disabling phantom planes, enable phantom OTG first so the disable gets the double buffer update Reviewed-by: Aric Cyr Acked-by: Alan Liu Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 43 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d446e6098948..da808996e21d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1054,6 +1054,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) int i, j; struct dc_state *dangling_context = dc_create_state(dc); struct dc_state *current_ctx; + struct pipe_ctx *pipe; if (dangling_context == NULL) return; @@ -1096,6 +1097,16 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) } if (should_disable && old_stream) { + pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + /* When disabling plane for a phantom pipe, we must turn on the + * phantom OTG so the disable programming gets the double buffer + * update. Otherwise the pipe will be left in a partially disabled + * state that can result in underflow or hang when enabling it + * again for different use. + */ + if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) { + pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); + } dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); @@ -1749,6 +1760,12 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c context->stream_count == 0) dc->hwss.prepare_bandwidth(dc, context); + /* When SubVP is active, all HW programming must be done while + * SubVP lock is acquired + */ + if (dc->hwss.subvp_pipe_control_lock) + dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use); + if (dc->debug.enable_double_buffered_dsc_pg_support) dc->hwss.update_dsc_pg(dc, context, false); @@ -1776,9 +1793,6 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); } - if (dc->hwss.subvp_pipe_control_lock) - dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use); - result = dc->hwss.apply_ctx_to_hw(dc, context); if (result != DC_OK) { @@ -3675,7 +3689,6 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); bool force_minimal_pipe_splitting = false; - uint32_t i; *is_plane_addition = false; @@ -3707,27 +3720,11 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, } } - /* For SubVP pipe split case when adding MPO video - * we need to add a minimal transition. In this case - * there will be 2 streams (1 main stream, 1 phantom - * stream). + /* For SubVP when adding MPO video we need to add a minimal transition. */ - if (cur_stream_status && - dc->current_state->stream_count == 2 && - stream->mall_stream_config.type == SUBVP_MAIN) { - bool is_pipe_split = false; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream && - (dc->current_state->res_ctx.pipe_ctx[i].bottom_pipe || - dc->current_state->res_ctx.pipe_ctx[i].next_odm_pipe)) { - is_pipe_split = true; - break; - } - } - + if (cur_stream_status && stream->mall_stream_config.type == SUBVP_MAIN) { /* determine if minimal transition is required due to SubVP*/ - if (surface_count > 0 && is_pipe_split) { + if (surface_count > 0) { if (cur_stream_status->plane_count > surface_count) { force_minimal_pipe_splitting = true; } else if (cur_stream_status->plane_count < surface_count) { -- cgit v1.2.3 From dc55b106ad477c67f969f3432d9070c6846fb557 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 27 Oct 2022 10:51:15 -0400 Subject: drm/amd/display: Disable phantom OTG after enable for plane disable [Description] - Need to disable phantom OTG after it's enabled in order to restore it to it's original state. - If it's enabled and then an MCLK switch comes in we may not prefetch the correct data since the phantom OTG could already be in the middle of the frame. Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 +++++++++++++- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 8 ++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index da808996e21d..9c3704c4d7e4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1055,6 +1055,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) struct dc_state *dangling_context = dc_create_state(dc); struct dc_state *current_ctx; struct pipe_ctx *pipe; + struct timing_generator *tg; if (dangling_context == NULL) return; @@ -1098,6 +1099,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) if (should_disable && old_stream) { pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + tg = pipe->stream_res.tg; /* When disabling plane for a phantom pipe, we must turn on the * phantom OTG so the disable programming gets the double buffer * update. Otherwise the pipe will be left in a partially disabled @@ -1105,7 +1107,8 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) * again for different use. */ if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) { - pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); + if (tg->funcs->enable_crtc) + tg->funcs->enable_crtc(tg); } dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); @@ -1122,6 +1125,15 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) dc->hwss.interdependent_update_lock(dc, dc->current_state, false); dc->hwss.post_unlock_program_front_end(dc, dangling_context); } + /* We need to put the phantom OTG back into it's default (disabled) state or we + * can get corruption when transition from one SubVP config to a different one. + * The OTG is set to disable on falling edge of VUPDATE so the plane disable + * will still get it's double buffer update. + */ + if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) { + if (tg->funcs->disable_phantom_crtc) + tg->funcs->disable_phantom_crtc(tg); + } } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c index 2b33eeb213e2..2ee798965bc2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c @@ -167,6 +167,13 @@ static void optc32_phantom_crtc_post_enable(struct timing_generator *optc) REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000); } +static void optc32_disable_phantom_otg(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0); +} + static void optc32_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing) { @@ -260,6 +267,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = { .enable_crtc = optc32_enable_crtc, .disable_crtc = optc32_disable_crtc, .phantom_crtc_post_enable = optc32_phantom_crtc_post_enable, + .disable_phantom_crtc = optc32_disable_phantom_otg, /* used by enable_timing_synchronization. Not need for FPGA */ .is_counter_moving = optc1_is_counter_moving, .get_position = optc1_get_position, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 65f18f9dad34..43eb61961e0f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -184,6 +184,7 @@ struct timing_generator_funcs { bool (*disable_crtc)(struct timing_generator *tg); #ifdef CONFIG_DRM_AMD_DC_DCN void (*phantom_crtc_post_enable)(struct timing_generator *tg); + void (*disable_phantom_crtc)(struct timing_generator *tg); #endif bool (*immediate_disable_crtc)(struct timing_generator *tg); bool (*is_counter_moving)(struct timing_generator *tg); -- cgit v1.2.3 From de020e5fa9ebc6fc32e82ae6ccb0282451ed937c Mon Sep 17 00:00:00 2001 From: Wesley Chalmers Date: Fri, 21 Oct 2022 19:06:10 -0400 Subject: drm/amd/display: Disable DRR actions during state commit [WHY] Committing a state while performing DRR actions can cause underflow. [HOW] Disabled features performing DRR actions during state commit. Need to follow-up on why DRR actions affect state commit. Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Wesley Chalmers Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 8c5045711264..c20e9f76f021 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -992,8 +992,5 @@ void dcn30_prepare_bandwidth(struct dc *dc, dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz); dcn20_prepare_bandwidth(dc, context); - - dc_dmub_srv_p_state_delegate(dc, - context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching, context); } -- cgit v1.2.3 From be9f6b222c529f315a77c0a182a47c988c28f7f1 Mon Sep 17 00:00:00 2001 From: Mustapha Ghaddar Date: Wed, 26 Oct 2022 13:54:27 -0400 Subject: drm/amd/display: Fix fallback issues for DP LL 1.4a tests [WHY] Unlike DP or USBC, the USB4 link does not get its own encoder and has to share therefore verify_caps is skipped. [HOW] Fix the fallback logic for automated tests and take that into consideration for LT and LS. Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Mustapha Ghaddar Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 22 +++++++++++++++++++--- drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c | 15 ++++++++++----- drivers/gpu/drm/amd/display/dc/dc_link.h | 1 + 3 files changed, 30 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index b0cfe21871e4..a3e1aeccd3f5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -4554,9 +4554,19 @@ void dc_link_dp_handle_link_loss(struct dc_link *link) for (i = 0; i < MAX_PIPES; i++) { pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && - pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) + if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off + && pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { + // Always use max settings here for DP 1.4a LL Compliance CTS + if (link->is_automated) { + pipe_ctx->link_config.dp_link_settings.lane_count = + link->verified_link_cap.lane_count; + pipe_ctx->link_config.dp_link_settings.link_rate = + link->verified_link_cap.link_rate; + pipe_ctx->link_config.dp_link_settings.link_spread = + link->verified_link_cap.link_spread; + } core_link_enable_stream(link->dc->current_state, pipe_ctx); + } } } @@ -4597,6 +4607,8 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd } if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) { + // Workaround for DP 1.4a LL Compliance CTS as USB4 has to share encoders unlike DP and USBC + link->is_automated = true; device_service_clear.bits.AUTOMATED_TEST = 1; core_link_write_dpcd( link, @@ -7240,6 +7252,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, struct pipe_ctx *pipes = &link->dc->current_state->res_ctx.pipe_ctx[0]; unsigned int i; + bool do_fallback = false; for (i = 0; i < MAX_PIPES; i++) { @@ -7272,13 +7285,16 @@ void dp_retrain_link_dp_test(struct dc_link *link, memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings)); + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) + do_fallback = true; + perform_link_training_with_retries( link_setting, skip_video_pattern, LINK_TRAINING_ATTEMPTS, &pipes[i], SIGNAL_TYPE_DISPLAY_PORT, - false); + do_fallback); link->dc->hwss.enable_stream(&pipes[i]); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c index 74e36b34d3f7..d130d58ac08e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c @@ -791,10 +791,14 @@ static enum link_training_result dpia_training_eq_transparent( } if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) && - dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) && - dp_is_interlane_aligned(dpcd_lane_status_updated)) { - result = LINK_TRAINING_SUCCESS; - break; + dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status)) { + /* Take into consideration corner case for DP 1.4a LL Compliance CTS as USB4 + * has to share encoders unlike DP and USBC + */ + if (dp_is_interlane_aligned(dpcd_lane_status_updated) || (link->is_automated && retries_eq)) { + result = LINK_TRAINING_SUCCESS; + break; + } } /* Update VS/PE. */ @@ -1008,7 +1012,8 @@ enum link_training_result dc_link_dpia_perform_link_training( */ if (result == LINK_TRAINING_SUCCESS) { msleep(5); - result = dp_check_link_loss_status(link, <_settings); + if (!link->is_automated) + result = dp_check_link_loss_status(link, <_settings); } else if (result == LINK_TRAINING_ABORT) { dpia_training_abort(link, <_settings, repeater_id); } else { diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index edb4532eaa39..dc6afe33bca2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -184,6 +184,7 @@ struct dc_link { bool is_dig_mapping_flexible; bool hpd_status; /* HPD status of link without physical HPD pin. */ bool is_hpd_pending; /* Indicates a new received hpd */ + bool is_automated; /* Indicates automated testing */ bool edp_sink_present; -- cgit v1.2.3 From 2f8f9118129dd4603cb425404f1df1f5013b6019 Mon Sep 17 00:00:00 2001 From: Chaitanya Dhere Date: Thu, 27 Oct 2022 09:51:19 -0400 Subject: drm/amd/display: Fix FCLK deviation and tool compile issues [Why] Recent backports from open source do not have header inclusion pattern that is consistent with inclusion style in the rest of the file. This breaks the internal tool builds as well. A recent commit erronously modified the original DML formula for calculating ActiveClockChangeLatencyHidingY. This resulted in a FCLK deviation from the golden values. [How] Change the way in which display_mode_vba.h is included so that it is consistent with the inclusion style in rest of the file which also fixes the tool build. Restore the DML formula to its original state to fix the FCLK deviation. Reviewed-by: Aurabindo Pillai Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Chaitanya Dhere Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 968924c491c1..ab9217732a17 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -4397,7 +4397,7 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( if (v->NumberOfActiveSurfaces > 1) { ActiveClockChangeLatencyHidingY = ActiveClockChangeLatencyHidingY - - (1 - 1 / v->NumberOfActiveSurfaces) * SwathHeightY[k] * v->HTotal[k] + - (1.0 - 1.0 / v->NumberOfActiveSurfaces) * SwathHeightY[k] * v->HTotal[k] / v->PixelClock[k] / v->VRatio[k]; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index 2c3827546ac7..fdccaa93eb2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -30,7 +30,7 @@ #include "os_types.h" #include "../dc_features.h" #include "../display_mode_structs.h" -#include "dml/display_mode_vba.h" +#include "../display_mode_vba.h" unsigned int dml32_dscceComputeDelay( unsigned int bpc, -- cgit v1.2.3 From 98f9229ff60e39d3d7babd42a13358bb5a392e4b Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Thu, 27 Oct 2022 15:34:33 -0400 Subject: drm/amd/display: Fix reg timeout in enc314_enable_fifo [Why] The link enablement sequence can end up resetting the encoder while the PHY symclk isn't yet on. This means that waiting for symclk on will timeout, along with the reset bit never asserting high. This causes unnecessary delay when enabling the link and produces a warning affecting multiple IGT tests. [How] Don't wait for the symclk to be on here because firmware already does. Don't wait for reset if we know the symclk isn't on. Split the reset into a helper function that checks the bit and decides whether or not a delay is sufficient. Reviewed-by: Roman Li Acked-by: Alan Liu Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/dc/dcn314/dcn314_dio_stream_encoder.c | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c index 7e773bf7b895..38842f938bed 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c @@ -49,18 +49,30 @@ #define CTX \ enc1->base.ctx +static void enc314_reset_fifo(struct stream_encoder *enc, bool reset) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t reset_val = reset ? 1 : 0; + uint32_t is_symclk_on; + + REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, reset_val); + REG_GET(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, &is_symclk_on); + + if (is_symclk_on) + REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, reset_val, 10, 5000); + else + udelay(10); +} static void enc314_enable_fifo(struct stream_encoder *enc) { struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - /* TODO: Confirm if we need to wait for DIG_SYMCLK_FE_ON */ - REG_WAIT(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, 1, 10, 5000); REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7); - REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1); - REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 10, 5000); - REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0); - REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 10, 5000); + + enc314_reset_fifo(enc, true); + enc314_reset_fifo(enc, false); + REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1); } -- cgit v1.2.3 From 1df6b9b07e334cee60afebcaca69297477655325 Mon Sep 17 00:00:00 2001 From: Steve Su Date: Fri, 28 Oct 2022 05:52:32 +0800 Subject: drm/amd/display: Fix gpio port mapping issue [Why] 1. Port of gpio has different mapping. [How] 1. Add a dummy entry in mapping table. 2. Fix incorrect mask bit field access. Reviewed-by: Alvin Lee Acked-by: Alan Liu Signed-off-by: Steve Su Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c | 14 ++++++++++++++ drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 9 ++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c index d635b73af46f..0ea52ba5ac82 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c @@ -107,6 +107,13 @@ static const struct ddc_registers ddc_data_regs_dcn[] = { ddc_data_regs_dcn2(3), ddc_data_regs_dcn2(4), ddc_data_regs_dcn2(5), + { + // add a dummy entry for cases no such port + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + .ddc_setup = 0, + .phy_aux_cntl = 0, + .dc_gpio_aux_ctrl_5 = 0 + }, { DDC_GPIO_VGA_REG_LIST(DATA), .ddc_setup = 0, @@ -121,6 +128,13 @@ static const struct ddc_registers ddc_clk_regs_dcn[] = { ddc_clk_regs_dcn2(3), ddc_clk_regs_dcn2(4), ddc_clk_regs_dcn2(5), + { + // add a dummy entry for cases no such port + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + .ddc_setup = 0, + .phy_aux_cntl = 0, + .dc_gpio_aux_ctrl_5 = 0 + }, { DDC_GPIO_VGA_REG_LIST(CLK), .ddc_setup = 0, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c index 6fd38cdd68c0..525bc8881950 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -94,11 +94,14 @@ static enum gpio_result set_config( * is required for detection of AUX mode */ if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) { if (!ddc_data_pd_en || !ddc_clk_pd_en) { - - REG_SET_2(gpio.MASK_reg, regval, + if (hw_gpio->base.en == GPIO_DDC_LINE_DDC_VGA) { + // bit 4 of mask has different usage in some cases + REG_SET(gpio.MASK_reg, regval, DC_GPIO_DDC1DATA_PD_EN, 1); + } else { + REG_SET_2(gpio.MASK_reg, regval, DC_GPIO_DDC1DATA_PD_EN, 1, DC_GPIO_DDC1CLK_PD_EN, 1); - + } if (config_data->type == GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) msleep(3); -- cgit v1.2.3 From ea192af507d99014775a757bbdb5f6e487fc6c7a Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Thu, 20 Oct 2022 15:57:36 -0400 Subject: drm/amd/display: Only update link settings after successful MST link train [WHY] Currently driver reduces verified link caps on DPIA devices if a link is trained at a link rate below the max rate verified during link detection. This blocks high bandwidth modes after setting a low bandwidth mode. [HOW] Only update link rate after a successful link train if link is MST. Reviewed-by: Mustapha Ghaddar Acked-by: Alan Liu Signed-off-by: Michael Strauss Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 8 ++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++++ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 7 +++++-- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index f72c013d3a5b..e47098fa5aac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -971,3 +971,11 @@ void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable) { /* TODO: add periodic detection implementation */ } + +void dm_helpers_dp_mst_update_branch_bandwidth( + struct dc_context *ctx, + struct dc_link *link) +{ + // TODO +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 24ed057414e1..5304e9daf90a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -4663,6 +4663,10 @@ void dc_link_set_preferred_training_settings(struct dc *dc, link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN; } + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && + link->type == dc_connection_mst_branch) + dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link); + /* Retrain now, or wait until next stream update to apply */ if (skip_immediate_retrain == false) dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index a3e1aeccd3f5..b772d7f2301c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2771,8 +2771,11 @@ bool perform_link_training_with_retries( /* Update verified link settings to current one * Because DPIA LT might fallback to lower link setting. */ - link->verified_link_cap.link_rate = link->cur_link_settings.link_rate; - link->verified_link_cap.lane_count = link->cur_link_settings.lane_count; + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + link->verified_link_cap.link_rate = link->cur_link_settings.link_rate; + link->verified_link_cap.lane_count = link->cur_link_settings.lane_count; + dm_helpers_dp_mst_update_branch_bandwidth(link->ctx, link); + } } } else { status = dc_link_dp_perform_link_training(link, diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index e3e5c39895a3..af1c50ed905a 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -116,6 +116,11 @@ bool dm_helpers_dp_mst_start_top_mgr( bool dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, struct dc_link *link); + +void dm_helpers_dp_mst_update_branch_bandwidth( + struct dc_context *ctx, + struct dc_link *link); + /** * OS specific aux read callback. */ -- cgit v1.2.3 From 01c0c124b9ecaa905468c6f3b3bf3962b276008b Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 27 Oct 2022 16:22:26 -0400 Subject: drm/amd/display: Enforce minimum prefetch time for low memclk on DCN32 [WHY?] Data return times when using lowest memclk can be <= 60us, which can cause underflow on high bandwidth displays with a workload. [HOW?] Enforce a minimum prefetch time during validation for low memclk modes. Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Dillon Varone Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 2 ++ .../gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 4 ++++ .../gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h | 3 +++ .../drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 12 ++++++++++-- .../drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c | 2 ++ drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 1 + 10 files changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 84c82d3a6761..d69121809524 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -864,6 +864,7 @@ struct dc_debug_options { bool enable_dp_dig_pixel_rate_div_policy; enum lttpr_mode lttpr_mode_override; unsigned int dsc_delay_factor_wa_x1000; + unsigned int min_prefetch_in_strobe_ns; }; struct gpu_info_soc_bounding_box_v1_0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 4ba9a8662185..4bd861427b3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -724,6 +724,7 @@ static const struct dc_debug_options debug_defaults_drv = { .enable_dp_dig_pixel_rate_div_policy = 1, .allow_sw_cursor_fallback = false, .alloc_extra_way_for_cursor = true, + .min_prefetch_in_strobe_ns = 60000, // 60us }; static const struct dc_debug_options debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index 61087f2385a9..6292ac515d1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -722,6 +722,7 @@ static const struct dc_debug_options debug_defaults_drv = { .enable_dp_dig_pixel_rate_div_policy = 1, .allow_sw_cursor_fallback = false, .alloc_extra_way_for_cursor = true, + .min_prefetch_in_strobe_ns = 60000, // 60us }; static const struct dc_debug_options debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 0d704e302d03..853ffb704985 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -2351,6 +2351,8 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa /* DML DSC delay factor workaround */ dcn3_2_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0; + dcn3_2_ip.min_prefetch_in_strobe_us = dc->debug.min_prefetch_in_strobe_ns / 1000.0; + /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */ dcn3_2_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index ae6e6abc620b..244fd15d24b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -786,6 +786,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->SwathHeightY[k], v->SwathHeightC[k], TWait, + v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ ? + mode_lib->vba.ip.min_prefetch_in_strobe_us : 0, /* Output */ &v->DSTXAfterScaler[k], &v->DSTYAfterScaler[k], @@ -3245,6 +3247,8 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l v->swath_width_chroma_ub_this_state[k], v->SwathHeightYThisState[k], v->SwathHeightCThisState[k], v->TWait, + v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ ? + mode_lib->vba.ip.min_prefetch_in_strobe_us : 0, /* Output */ &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.DSTXAfterScaler[k], diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h index c62e0991358b..f82e14cd9d8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h @@ -49,6 +49,9 @@ #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff +#define MEM_STROBE_FREQ_MHZ 1600 +#define MEM_STROBE_MAX_DELIVERY_TIME_US 60.0 + struct display_mode_lib; void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index ab9217732a17..635fc54338fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -3417,6 +3417,7 @@ bool dml32_CalculatePrefetchSchedule( unsigned int SwathHeightY, unsigned int SwathHeightC, double TWait, + double TPreReq, /* Output */ double *DSTXAfterScaler, double *DSTYAfterScaler, @@ -3474,6 +3475,7 @@ bool dml32_CalculatePrefetchSchedule( double min_Lsw; double Tsw_est1 = 0; double Tsw_est3 = 0; + double TPreMargin = 0; if (v->GPUVMEnable == true && v->HostVMEnable == true) HostVMDynamicLevelsTrips = v->HostVMMaxNonCachedPageTableLevels; @@ -3699,6 +3701,8 @@ bool dml32_CalculatePrefetchSchedule( dst_y_prefetch_equ = dml_floor(4.0 * (dst_y_prefetch_equ + 0.125), 1) / 4.0; Tpre_rounded = dst_y_prefetch_equ * LineTime; + + TPreMargin = Tpre_rounded - TPreReq; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: dst_y_prefetch_equ: %f (after round)\n", __func__, dst_y_prefetch_equ); dml_print("DML::%s: LineTime: %f\n", __func__, LineTime); @@ -3726,7 +3730,7 @@ bool dml32_CalculatePrefetchSchedule( *VRatioPrefetchY = 0; *VRatioPrefetchC = 0; *RequiredPrefetchPixDataBWLuma = 0; - if (dst_y_prefetch_equ > 1) { + if (dst_y_prefetch_equ > 1 && TPreMargin > 0.0) { double PrefetchBandwidth1; double PrefetchBandwidth2; double PrefetchBandwidth3; @@ -3872,7 +3876,11 @@ bool dml32_CalculatePrefetchSchedule( } if (dst_y_prefetch_oto < dst_y_prefetch_equ) { - *DestinationLinesForPrefetch = dst_y_prefetch_oto; + if (dst_y_prefetch_oto * LineTime < TPreReq) { + *DestinationLinesForPrefetch = dst_y_prefetch_equ; + } else { + *DestinationLinesForPrefetch = dst_y_prefetch_oto; + } TimeForFetchingMetaPTE = Tvm_oto; TimeForFetchingRowInVBlank = Tr0_oto; *PrefetchBandwidth = prefetch_bw_oto; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index fdccaa93eb2e..3989c2a28fae 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -743,6 +743,7 @@ bool dml32_CalculatePrefetchSchedule( unsigned int SwathHeightY, unsigned int SwathHeightC, double TWait, + double TPreReq, /* Output */ double *DSTXAfterScaler, double *DSTYAfterScaler, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index ec0486efab14..432b4ecd01a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -544,6 +544,8 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p /* DML DSC delay factor workaround */ dcn3_21_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0; + dcn3_21_ip.min_prefetch_in_strobe_us = dc->debug.min_prefetch_in_strobe_ns / 1000.0; + /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */ dcn3_21_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index d7be01ac0751..64d602e6412f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -367,6 +367,7 @@ struct _vcs_dpi_ip_params_st { /* DM workarounds */ double dsc_delay_factor_wa; // TODO: Remove after implementing root cause fix + double min_prefetch_in_strobe_us; }; struct _vcs_dpi_display_xfc_params_st { -- cgit v1.2.3 From 52b5432cd70a2d6d998cb9b48378c37d5bb31e12 Mon Sep 17 00:00:00 2001 From: Mike Hsieh Date: Tue, 4 Oct 2022 14:58:07 +0800 Subject: drm/amd/display: Set correct EOTF and Gamut flag in VRR info [Why] FreeSync always use G2.2 EOTF and Native gamut [How] Set EOTF and Gamut flags accordingly Reviewed-by: Krunoslav Kovac Acked-by: Alan Liu Signed-off-by: Mike Hsieh Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 0f39ab9dc5b4..c2e00f7b8381 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -688,10 +688,10 @@ static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf, if (app_tf != TRANSFER_FUNC_UNKNOWN) { infopacket->valid = true; - infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active] - - if (app_tf == TRANSFER_FUNC_GAMMA_22) { - infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active] + if (app_tf != TRANSFER_FUNC_PQ2084) { + infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active] + if (app_tf == TRANSFER_FUNC_GAMMA_22) + infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active] } } } -- cgit v1.2.3 From 964d641632fa0c8eb52d577c23c1b5b5525a9bc7 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Sun, 30 Oct 2022 15:56:53 -0400 Subject: drm/amd/display: Add margin for max vblank time for SubVP + DRR [Description] - Incorporate FW delays as port of max VTOTAL calculated for SubVP + DRR cases (since it is part of the microschedule). - Also add margin for the max VTOTAL possible for SubVP + DRR cases. - Due to rounding errors in FW (integer arithmetic), the microschedule calculation can get pushed to the next frame (incorrectly) in cases where we use the max VTOTAL possible to complete the MCLK switch. - When the rounding error occurs, we are only off by 1-2 lines, use 40us margin which is working consistently. Reviewed-by: Jun Lei Reviewed-by: Aric Cyr Acked-by: Alan Liu Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 12 ++++++++++-- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d69121809524..1ec1b441d5cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -261,6 +261,7 @@ struct dc_caps { uint32_t cache_line_size; uint32_t cache_num_ways; uint16_t subvp_fw_processing_delay_us; + uint8_t subvp_drr_max_vblank_margin_us; uint16_t subvp_prefetch_end_to_mall_start_us; uint8_t subvp_swath_height_margin_lines; // subvp start line must be aligned to 2 x swath height uint16_t subvp_pstate_allow_width_us; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 4cb912bf400b..097556f7b32c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -477,12 +477,20 @@ static void populate_subvp_cmd_drr_info(struct dc *dc, (((uint64_t)main_timing->pix_clk_100hz * 100))); drr_active_us = div64_u64(((uint64_t)drr_timing->v_addressable * drr_timing->h_total * 1000000), (((uint64_t)drr_timing->pix_clk_100hz * 100))); - max_drr_vblank_us = div64_u64((subvp_active_us - prefetch_us - drr_active_us), 2) + drr_active_us; - max_drr_mallregion_us = subvp_active_us - prefetch_us - mall_region_us; + max_drr_vblank_us = div64_u64((subvp_active_us - prefetch_us - + dc->caps.subvp_fw_processing_delay_us - drr_active_us), 2) + drr_active_us; + max_drr_mallregion_us = subvp_active_us - prefetch_us - mall_region_us - dc->caps.subvp_fw_processing_delay_us; max_drr_supported_us = max_drr_vblank_us > max_drr_mallregion_us ? max_drr_vblank_us : max_drr_mallregion_us; max_vtotal_supported = div64_u64(((uint64_t)drr_timing->pix_clk_100hz * 100 * max_drr_supported_us), (((uint64_t)drr_timing->h_total * 1000000))); + /* When calculating the max vtotal supported for SubVP + DRR cases, add + * margin due to possible rounding errors (being off by 1 line in the + * FW calculation can incorrectly push the P-State switch to wait 1 frame + * longer). + */ + max_vtotal_supported = max_vtotal_supported - dc->caps.subvp_drr_max_vblank_margin_us; + pipe_data->pipe_config.vblank_data.drr_info.min_vtotal_supported = min_vtotal_supported; pipe_data->pipe_config.vblank_data.drr_info.max_vtotal_supported = max_vtotal_supported; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 4bd861427b3c..77e40ee488bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -2117,6 +2117,7 @@ static bool dcn32_resource_construct( dc->caps.cache_num_ways = 16; dc->caps.max_cab_allocation_bytes = 67108864; // 64MB = 1024 * 1024 * 64 dc->caps.subvp_fw_processing_delay_us = 15; + dc->caps.subvp_drr_max_vblank_margin_us = 40; dc->caps.subvp_prefetch_end_to_mall_start_us = 15; dc->caps.subvp_swath_height_margin_lines = 16; dc->caps.subvp_pstate_allow_width_us = 20; diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index 6292ac515d1a..e5861225f1df 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -1704,6 +1704,7 @@ static bool dcn321_resource_construct( dc->caps.cache_num_ways = 16; dc->caps.max_cab_allocation_bytes = 33554432; // 32MB = 1024 * 1024 * 32 dc->caps.subvp_fw_processing_delay_us = 15; + dc->caps.subvp_drr_max_vblank_margin_us = 40; dc->caps.subvp_prefetch_end_to_mall_start_us = 15; dc->caps.subvp_swath_height_margin_lines = 16; dc->caps.subvp_pstate_allow_width_us = 20; -- cgit v1.2.3 From b7ada7ee61d3eb0ebf08089edcefdc272b5f7b1e Mon Sep 17 00:00:00 2001 From: George Shen Date: Thu, 14 Apr 2022 21:29:38 -0400 Subject: drm/amd/display: Populate DP2.0 output type for DML pipe [Why] DCN3.2 DML logic uses a new output type for DP2.0, which will enable validation to pass for higher BW timings that require DP2.0 link rates. [How] Populate the DML pipe with DP2.0 output type if the signal type of the pipe_ctx is 128b/132b. Reviewed-by: Alvin Lee Acked-by: Jasdeep Dhillon Signed-off-by: George Shen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index 602e885ed52c..75dbb7ee193b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -1296,6 +1296,8 @@ int dcn20_populate_dml_pipes_from_context( case SIGNAL_TYPE_DISPLAY_PORT_MST: case SIGNAL_TYPE_DISPLAY_PORT: pipes[pipe_cnt].dout.output_type = dm_dp; + if (is_dp_128b_132b_signal(&res_ctx->pipe_ctx[i])) + pipes[pipe_cnt].dout.output_type = dm_dp2p0; break; case SIGNAL_TYPE_EDP: pipes[pipe_cnt].dout.output_type = dm_edp; -- cgit v1.2.3 From adf65dff5d61d3adad669a1f5c6dd009107eacd7 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Wed, 20 Apr 2022 12:28:20 -0400 Subject: drm/amdgpu: Fix the kerneldoc description amdgpu_ttm_tt_set_userptr() is also called by the KFD as part of initializing the user pages for userptr BOs and also while initializing the GPUVM for a KFD process so update the function description. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8c00a7a06c32..c9ceea46711e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1177,8 +1177,9 @@ int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo, * @addr: The address in the current tasks VM space to use * @flags: Requirements of userptr object. * - * Called by amdgpu_gem_userptr_ioctl() to bind userptr pages - * to current task + * Called by amdgpu_gem_userptr_ioctl() and kfd_ioctl_alloc_memory_of_gpu() to + * bind userptr pages to current task and by kfd_ioctl_acquire_vm() to + * initialize GPU VM for a KFD process. */ int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo, uint64_t addr, uint32_t flags) -- cgit v1.2.3 From f936f535fa70f35ce3369b1418ebae0e657cda6a Mon Sep 17 00:00:00 2001 From: Asher Song Date: Thu, 3 Nov 2022 18:28:40 +0800 Subject: Revert "drm/amdgpu: Revert "drm/amdgpu: getting fan speed pwm for vega10 properly"" This reverts commit 4545ae2ed3f2f7c3f615a53399c9c8460ee5bca7. The origin patch "drm/amdgpu: getting fan speed pwm for vega10 properly" works fine. Test failure is caused by test case self. Signed-off-by: Asher Song Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- .../drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 25 +++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index dad3e3741a4e..190af79f3236 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -67,22 +67,21 @@ int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, int vega10_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr, uint32_t *speed) { - uint32_t current_rpm; - uint32_t percent = 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return 0; + struct amdgpu_device *adev = hwmgr->adev; + uint32_t duty100, duty; + uint64_t tmp64; - if (vega10_get_current_rpm(hwmgr, ¤t_rpm)) - return -1; + duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), + CG_FDO_CTRL1, FMAX_DUTY100); + duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS), + CG_THERMAL_STATUS, FDO_PWM_DUTY); - if (hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM != 0) - percent = current_rpm * 255 / - hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM; + if (!duty100) + return -EINVAL; - *speed = MIN(percent, 255); + tmp64 = (uint64_t)duty * 255; + do_div(tmp64, duty100); + *speed = MIN((uint32_t)tmp64, 255); return 0; } -- cgit v1.2.3 From e198e55b28202f78bca74feec9d568f4e96c6aab Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 30 Oct 2022 19:20:05 -0400 Subject: drm/amd/display: 3.2.211 DC version 3.2.211 brings along the following fixes: - Wait for VBLANK during pipe programming - Adding HDMI SCDC DEVICE_ID define - Cursor update refactor: PSR-SU support condition - Update 709 gamma to 2.222 as stated in the standerd - Consider dp cable id only when data is non zero - Waiting for 1 frame to fix the flash issue on PSR1 - Update SR watermarks for DCN314 - Allow tuning DCN314 bounding box - Zeromem mypipe heap struct before using it - Use min transition for SubVP into MPO - Disable phantom OTG after enable for plane disable - Disable DRR actions during state commit - Fix fallback issues for DP LL 1.4a tests - Fix FCLK deviation and tool compile issues - Fix reg timeout in enc314_enable_fifo - Fix gpio port mapping issue - Only update link settings after successful MST link train - Enforce minimum prefetch time for low memclk on DCN32 - Set correct EOTF and Gamut flag in VRR info - Add margin for max vblank time for SubVP + DRR - Populate DP2.0 output type for DML pipe Acked-by: Alan Liu Reviewed-by: Alan Liu Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1ec1b441d5cb..caed5597d1dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.210" +#define DC_VER "3.2.211" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From c70e2166967dc4ecb5e3a9b162741a9726755d9b Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Thu, 3 Nov 2022 10:24:52 -0400 Subject: drm/amdgpu: Unlock bo_list_mutex after error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get below kernel WARNING backtrace when pressing ctrl-C to kill kfdtest application. If amdgpu_cs_parser_bos returns error after taking bo_list_mutex, as caller amdgpu_cs_ioctl will not unlock bo_list_mutex, this generates the kernel WARNING. Add unlock bo_list_mutex after amdgpu_cs_parser_bos error handling to cleanup bo_list userptr bo. WARNING: kfdtest/2930 still has locks held! 1 lock held by kfdtest/2930: (&list->bo_list_mutex){+.+.}-{3:3}, at: amdgpu_cs_ioctl+0xce5/0x1f10 [amdgpu] stack backtrace: dump_stack_lvl+0x44/0x57 get_signal+0x79f/0xd00 arch_do_signal_or_restart+0x36/0x7b0 exit_to_user_mode_prepare+0xfd/0x1b0 syscall_exit_to_user_mode+0x19/0x40 do_syscall_64+0x40/0x80 Signed-off-by: Philip Yang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1bbd39b3b0fc..d371000a5727 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -992,6 +992,7 @@ out_free_user_pages: kvfree(e->user_pages); e->user_pages = NULL; } + mutex_unlock(&p->bo_list->bo_list_mutex); return r; } -- cgit v1.2.3 From 0bc71adc8b1b65a369d4b8ef098e74ed4aab62d9 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Wed, 2 Nov 2022 16:55:31 -0400 Subject: drm/amdgpu: Drop eviction lock when allocating PT BO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-take the eviction lock immediately again after the allocation is completed, to fix circular locking warning with drm_buddy allocator. Move amdgpu_vm_eviction_lock/unlock/trylock to amdgpu_vm.h as they are called from multiple files. Signed-off-by: Philip Yang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 26 -------------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 26 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 2 ++ 3 files changed, 28 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 2291aa14d888..003aa9e47085 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -143,32 +143,6 @@ int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm, return 0; } -/* - * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS - * happens while holding this lock anywhere to prevent deadlocks when - * an MMU notifier runs in reclaim-FS context. - */ -static inline void amdgpu_vm_eviction_lock(struct amdgpu_vm *vm) -{ - mutex_lock(&vm->eviction_lock); - vm->saved_flags = memalloc_noreclaim_save(); -} - -static inline int amdgpu_vm_eviction_trylock(struct amdgpu_vm *vm) -{ - if (mutex_trylock(&vm->eviction_lock)) { - vm->saved_flags = memalloc_noreclaim_save(); - return 1; - } - return 0; -} - -static inline void amdgpu_vm_eviction_unlock(struct amdgpu_vm *vm) -{ - memalloc_noreclaim_restore(vm->saved_flags); - mutex_unlock(&vm->eviction_lock); -} - /** * amdgpu_vm_bo_evicted - vm_bo is evicted * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 1d31771b4230..6546e786bf00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -510,4 +510,30 @@ static inline uint64_t amdgpu_vm_tlb_seq(struct amdgpu_vm *vm) return atomic64_read(&vm->tlb_seq); } +/* + * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS + * happens while holding this lock anywhere to prevent deadlocks when + * an MMU notifier runs in reclaim-FS context. + */ +static inline void amdgpu_vm_eviction_lock(struct amdgpu_vm *vm) +{ + mutex_lock(&vm->eviction_lock); + vm->saved_flags = memalloc_noreclaim_save(); +} + +static inline bool amdgpu_vm_eviction_trylock(struct amdgpu_vm *vm) +{ + if (mutex_trylock(&vm->eviction_lock)) { + vm->saved_flags = memalloc_noreclaim_save(); + return true; + } + return false; +} + +static inline void amdgpu_vm_eviction_unlock(struct amdgpu_vm *vm) +{ + memalloc_noreclaim_restore(vm->saved_flags); + mutex_unlock(&vm->eviction_lock); +} + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c index 358b91243e37..b5f3bba851db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c @@ -597,7 +597,9 @@ static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev, if (entry->bo) return 0; + amdgpu_vm_eviction_unlock(vm); r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt); + amdgpu_vm_eviction_lock(vm); if (r) return r; -- cgit v1.2.3 From 407a5bdd5513a3617aa3f8a5c738561e157f8d83 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Mon, 7 Nov 2022 16:46:59 +0800 Subject: drm/amdgpu: disable BACO on special BEIGE_GOBY card Still avoid intermittent failure. Signed-off-by: Guchun Chen Reviewed-by: Lijo Lazar Acked-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 74996a8fb671..6212fd270857 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -377,7 +377,9 @@ static void sienna_cichlid_check_bxco_support(struct smu_context *smu) if (((adev->pdev->device == 0x73A1) && (adev->pdev->revision == 0x00)) || ((adev->pdev->device == 0x73BF) && - (adev->pdev->revision == 0xCF))) + (adev->pdev->revision == 0xCF)) || + ((adev->pdev->device == 0x7422) && + (adev->pdev->revision == 0x00))) smu_baco->platform_support = false; } -- cgit v1.2.3 From 4cc16d64b6cdb179a26fb389cae9dce788e88f5d Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Sun, 6 Nov 2022 20:34:27 +0800 Subject: drm/amdkfd: Fix the memory overrun Fix the memory overrun issue caused by wrong array size. Signed-off-by: Ma Jun Reviewed-by: Felix Kuehling Reported-by: coverity-bot Addresses-Coverity-ID: 1527133 ("Memory - corruptions") Fixes: c0cc999f3c32e6 ("drm/amdkfd: Fix the warning of array-index-out-of-bounds") Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 267dd69737fa..af01ba061e1b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -1111,7 +1111,7 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache, props->cache_latency = cache->cache_latency; memcpy(props->sibling_map, cache->sibling_map, - sizeof(props->sibling_map)); + CRAT_SIBLINGMAP_SIZE); /* set the sibling_map_size as 32 for CRAT from ACPI */ props->sibling_map_size = CRAT_SIBLINGMAP_SIZE; -- cgit v1.2.3 From 60cfad329ab877cb62975ea78ed442c2496990ba Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Tue, 8 Nov 2022 08:30:36 +0800 Subject: drm/amd/pm: enable mode1 reset on smu_v13_0_10 enable mode1 reset and prioritize debug port on smu_v13_0_10 as a more reliable message processing v2 - move mode1 reset callback to smu_v13_0_0_ppt.c Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 4 ++ .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 53 +++++++++++++++++++++- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 18 ++++++++ drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 3 ++ 5 files changed, 77 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 1d4013ed0d10..b258e9aa0558 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -322,6 +322,7 @@ soc21_asic_reset_method(struct amdgpu_device *adev) switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 0): case IP_VERSION(13, 0, 7): + case IP_VERSION(13, 0, 10): return AMD_RESET_METHOD_MODE1; case IP_VERSION(13, 0, 4): return AMD_RESET_METHOD_MODE2; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index e2fa3b066b96..1bc26e93a83c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -568,6 +568,10 @@ struct smu_context u32 param_reg; u32 msg_reg; u32 resp_reg; + + u32 debug_param_reg; + u32 debug_msg_reg; + u32 debug_resp_reg; }; struct i2c_adapter; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 29529328152d..969a5e80a74c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -70,6 +70,26 @@ #define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000 +#define mmMP1_SMN_C2PMSG_66 0x0282 +#define mmMP1_SMN_C2PMSG_66_BASE_IDX 0 + +#define mmMP1_SMN_C2PMSG_82 0x0292 +#define mmMP1_SMN_C2PMSG_82_BASE_IDX 0 + +#define mmMP1_SMN_C2PMSG_90 0x029a +#define mmMP1_SMN_C2PMSG_90_BASE_IDX 0 + +#define mmMP1_SMN_C2PMSG_75 0x028b +#define mmMP1_SMN_C2PMSG_75_BASE_IDX 0 + +#define mmMP1_SMN_C2PMSG_53 0x0275 +#define mmMP1_SMN_C2PMSG_53_BASE_IDX 0 + +#define mmMP1_SMN_C2PMSG_54 0x0276 +#define mmMP1_SMN_C2PMSG_54_BASE_IDX 0 + +#define DEBUGSMC_MSG_Mode1Reset 2 + static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), @@ -1763,6 +1783,35 @@ static int smu_v13_0_0_set_df_cstate(struct smu_context *smu, NULL); } +static int smu_v13_0_0_mode1_reset(struct smu_context *smu) +{ + int ret; + struct amdgpu_device *adev = smu->adev; + + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 10)) + ret = smu_cmn_send_debug_smc_msg(smu, DEBUGSMC_MSG_Mode1Reset); + else + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_Mode1Reset, NULL); + + if (!ret) + msleep(SMU13_MODE1_RESET_WAIT_TIME_IN_MS); + + return ret; +} + +static void smu_v13_0_0_set_smu_mailbox_registers(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + smu->param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_82); + smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_66); + smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); + + smu->debug_param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_53); + smu->debug_msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_75); + smu->debug_resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_54); +} + static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask, .set_default_dpm_table = smu_v13_0_0_set_default_dpm_table, @@ -1830,7 +1879,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .baco_enter = smu_v13_0_baco_enter, .baco_exit = smu_v13_0_baco_exit, .mode1_reset_is_support = smu_v13_0_0_is_mode1_reset_supported, - .mode1_reset = smu_v13_0_mode1_reset, + .mode1_reset = smu_v13_0_0_mode1_reset, .set_mp1_state = smu_v13_0_0_set_mp1_state, .set_df_cstate = smu_v13_0_0_set_df_cstate, }; @@ -1844,5 +1893,5 @@ void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu) smu->table_map = smu_v13_0_0_table_map; smu->pwr_src_map = smu_v13_0_0_pwr_src_map; smu->workload_map = smu_v13_0_0_workload_map; - smu_v13_0_set_smu_mailbox_registers(smu); + smu_v13_0_0_set_smu_mailbox_registers(smu); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index e4f8f90ac5aa..768b6e7dbd77 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -233,6 +233,18 @@ static void __smu_cmn_send_msg(struct smu_context *smu, WREG32(smu->msg_reg, msg); } +static int __smu_cmn_send_debug_msg(struct smu_context *smu, + u32 msg, + u32 param) +{ + struct amdgpu_device *adev = smu->adev; + + WREG32(smu->debug_param_reg, param); + WREG32(smu->debug_msg_reg, msg); + WREG32(smu->debug_resp_reg, 0); + + return 0; +} /** * smu_cmn_send_msg_without_waiting -- send the message; don't wait for status * @smu: pointer to an SMU context @@ -386,6 +398,12 @@ int smu_cmn_send_smc_msg(struct smu_context *smu, read_arg); } +int smu_cmn_send_debug_smc_msg(struct smu_context *smu, + uint32_t msg) +{ + return __smu_cmn_send_debug_msg(smu, msg, 0); +} + int smu_cmn_to_asic_specific_index(struct smu_context *smu, enum smu_cmn2asic_mapping_type type, uint32_t index) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index 1526ce09c399..f82cf76dd3a4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -42,6 +42,9 @@ int smu_cmn_send_smc_msg(struct smu_context *smu, enum smu_message_type msg, uint32_t *read_arg); +int smu_cmn_send_debug_smc_msg(struct smu_context *smu, + uint32_t msg); + int smu_cmn_wait_for_response(struct smu_context *smu); int smu_cmn_to_asic_specific_index(struct smu_context *smu, -- cgit v1.2.3 From 43fca649e668f9f8f75a9d905de8c61bcf1d0986 Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Sun, 6 Nov 2022 11:43:06 +0800 Subject: drm/amdkfd: Make kfd_fill_cache_non_crat_info() as static kfd_fill_cache_non_crat_info() is only used in kfd_topology.c, so make it as static. Signed-off-by: Ma Jun Reviewed-by: Guchun Chen Reported-by: kernel test robot Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 1d9b90d979c4..ef9c6fdfb88d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -1723,7 +1723,7 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext, /* kfd_fill_cache_non_crat_info - Fill GPU cache info using kfd_gpu_cache_info * tables */ -void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct kfd_dev *kdev) +static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct kfd_dev *kdev) { struct kfd_gpu_cache_info *pcache_info = NULL; int i, j, k; -- cgit v1.2.3 From da858deab88eb561f2196bc99b6dbd2320e56456 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Mon, 7 Nov 2022 12:06:44 -0500 Subject: drm/amdgpu: Remove redundant I2C EEPROM address Remove redundant EEPROM_I2C_MADDR_54H address, since we already have it represented (ARCTURUS), and since we don't include the I2C device type identifier in EEPROM memory addresses, i.e. that high up in the device abstraction--we only use EEPROM memory addresses, as memory is continuously represented by EEPROM device(s) on the I2C bus. Add a comment describing what these memory addresses are, how they come about and how they're usually extracted from the device address byte. Cc: Candice Li Cc: Tao Zhou Cc: Alex Deucher Fixes: c9bdc6c3cf39df ("drm/amdgpu: Add EEPROM I2C address support for ip discovery") Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 24 +++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c index 4d9eb0137f8c..d6c4293829aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c @@ -79,6 +79,8 @@ * That is, for an I2C EEPROM driver everything is controlled by * the "eeprom_addr". * + * See also top of amdgpu_ras_eeprom.c. + * * P.S. If you need to write, lock and read the Identification Page, * (M24M02-DR device only, which we do not use), change the "7" to * "0xF" in the macro below, and let the client set bit 20 to 1 in diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 7268ae65c140..1bb92a64f24a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -33,12 +33,30 @@ #include "amdgpu_reset.h" +/* These are memory addresses as would be seen by one or more EEPROM + * chips strung on the I2C bus, usually by manipulating pins 1-3 of a + * set of EEPROM devices. They form a continuous memory space. + * + * The I2C device address includes the device type identifier, 1010b, + * which is a reserved value and indicates that this is an I2C EEPROM + * device. It also includes the top 3 bits of the 19 bit EEPROM memory + * address, namely bits 18, 17, and 16. This makes up the 7 bit + * address sent on the I2C bus with bit 0 being the direction bit, + * which is not represented here, and sent by the hardware directly. + * + * For instance, + * 50h = 1010000b => device type identifier 1010b, bits 18:16 = 000b, address 0. + * 54h = 1010100b => --"--, bits 18:16 = 100b, address 40000h. + * 56h = 1010110b => --"--, bits 18:16 = 110b, address 60000h. + * Depending on the size of the I2C EEPROM device(s), bits 18:16 may + * address memory in a device or a device on the I2C bus, depending on + * the status of pins 1-3. See top of amdgpu_eeprom.c. + */ #define EEPROM_I2C_MADDR_VEGA20 0x0 #define EEPROM_I2C_MADDR_ARCTURUS 0x40000 #define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0 #define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0 #define EEPROM_I2C_MADDR_ALDEBARAN 0x0 -#define EEPROM_I2C_MADDR_54H (0x54UL << 16) /* * The 2 macros bellow represent the actual size in bytes that @@ -130,7 +148,7 @@ static bool __get_eeprom_i2c_addr_ip_discovery(struct amdgpu_device *adev, switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 0): case IP_VERSION(13, 0, 10): - control->i2c_address = EEPROM_I2C_MADDR_54H; + control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS; return true; default: return false; @@ -185,7 +203,7 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 0): - control->i2c_address = EEPROM_I2C_MADDR_54H; + control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS; break; default: -- cgit v1.2.3 From 3b8164f8084ff7888ed24970efa230ff5d36eda8 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Mon, 7 Nov 2022 12:38:03 -0500 Subject: drm/amdgpu: Decouple RAS EEPROM addresses from chips Abstract RAS I2C EEPROM addresses from chip names, and set their macro definition names to the address they set, not the chip they attach to. Since most chips either use I2C EEPROM address 0 or 40000h for the RAS table start offset, this leaves us with only two macro definitions as opposed to five, and removes the redundancy of four. Cc: Candice Li Cc: Tao Zhou Cc: Alex Deucher Signed-off-by: Luben Tuikov Reviewed-by: Kent Russell Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 1bb92a64f24a..f63bd31e199c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -51,12 +51,11 @@ * Depending on the size of the I2C EEPROM device(s), bits 18:16 may * address memory in a device or a device on the I2C bus, depending on * the status of pins 1-3. See top of amdgpu_eeprom.c. + * + * The RAS table lives either at address 0 or address 40000h of EEPROM. */ -#define EEPROM_I2C_MADDR_VEGA20 0x0 -#define EEPROM_I2C_MADDR_ARCTURUS 0x40000 -#define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0 -#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0 -#define EEPROM_I2C_MADDR_ALDEBARAN 0x0 +#define EEPROM_I2C_MADDR_0 0x0 +#define EEPROM_I2C_MADDR_4 0x40000 /* * The 2 macros bellow represent the actual size in bytes that @@ -135,9 +134,9 @@ static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev, if (strnstr(atom_ctx->vbios_version, "D342", sizeof(atom_ctx->vbios_version))) - control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS_D342; + control->i2c_address = EEPROM_I2C_MADDR_0; else - control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS; + control->i2c_address = EEPROM_I2C_MADDR_4; return true; } @@ -148,7 +147,7 @@ static bool __get_eeprom_i2c_addr_ip_discovery(struct amdgpu_device *adev, switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 0): case IP_VERSION(13, 0, 10): - control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS; + control->i2c_address = EEPROM_I2C_MADDR_4; return true; default: return false; @@ -180,18 +179,18 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, switch (adev->asic_type) { case CHIP_VEGA20: - control->i2c_address = EEPROM_I2C_MADDR_VEGA20; + control->i2c_address = EEPROM_I2C_MADDR_0; break; case CHIP_ARCTURUS: return __get_eeprom_i2c_addr_arct(adev, control); case CHIP_SIENNA_CICHLID: - control->i2c_address = EEPROM_I2C_MADDR_SIENNA_CICHLID; + control->i2c_address = EEPROM_I2C_MADDR_0; break; case CHIP_ALDEBARAN: - control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN; + control->i2c_address = EEPROM_I2C_MADDR_0; break; case CHIP_IP_DISCOVERY: @@ -203,7 +202,7 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 0): - control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS; + control->i2c_address = EEPROM_I2C_MADDR_4; break; default: -- cgit v1.2.3 From 4b31b92b143f7d209f3d494c56d4c4673e9fc53d Mon Sep 17 00:00:00 2001 From: Harsh Jain Date: Wed, 2 Nov 2022 15:23:08 +0530 Subject: drm/amdgpu: complete gfxoff allow signal during suspend without delay change guarantees that gfxoff is allowed before moving further in s2idle sequence to add more reliablity about gfxoff in amdgpu IP's suspend flow Signed-off-by: Harsh Jain Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 9546adc8a76f..23692e5d4d13 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -583,10 +583,14 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable) if (adev->gfx.gfx_off_req_count == 0 && !adev->gfx.gfx_off_state) { /* If going to s2idle, no need to wait */ - if (adev->in_s0ix) - delay = GFX_OFF_NO_DELAY; - schedule_delayed_work(&adev->gfx.gfx_off_delay_work, + if (adev->in_s0ix) { + if (!amdgpu_dpm_set_powergating_by_smu(adev, + AMD_IP_BLOCK_TYPE_GFX, true)) + adev->gfx.gfx_off_state = true; + } else { + schedule_delayed_work(&adev->gfx.gfx_off_delay_work, delay); + } } } else { if (adev->gfx.gfx_off_req_count == 0) { -- cgit v1.2.3 From 10276a20be1115e1f76c189330da2992df980eee Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Fri, 4 Nov 2022 17:50:02 +0800 Subject: drm/radeon: Add the missed acpi_put_table() to fix memory leak When the radeon driver reads the bios information from ACPI table in radeon_acpi_vfct_bios(), it misses to call acpi_put_table() to release the ACPI memory after the init, so add acpi_put_table() properly to fix the memory leak. v2: fix text formatting (Alex) Fixes: 268ba0a99f89 ("drm/radeon: implement ACPI VFCT vbios fetch (v3)") Signed-off-by: Hanjun Guo Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_bios.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 33121655d50b..1d99c9a2b56e 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -612,13 +612,14 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) acpi_size tbl_size; UEFI_ACPI_VFCT *vfct; unsigned offset; + bool r = false; if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) return false; tbl_size = hdr->length; if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); - return false; + goto out; } vfct = (UEFI_ACPI_VFCT *)hdr; @@ -631,13 +632,13 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) offset += sizeof(VFCT_IMAGE_HEADER); if (offset > tbl_size) { DRM_ERROR("ACPI VFCT image header truncated\n"); - return false; + goto out; } offset += vhdr->ImageLength; if (offset > tbl_size) { DRM_ERROR("ACPI VFCT image truncated\n"); - return false; + goto out; } if (vhdr->ImageLength && @@ -649,15 +650,18 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); + if (rdev->bios) + r = true; - if (!rdev->bios) - return false; - return true; + goto out; } } DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); - return false; + +out: + acpi_put_table(hdr); + return r; } #else static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) -- cgit v1.2.3 From e50db38342d5d2243e9738a51c9737cbb017e456 Mon Sep 17 00:00:00 2001 From: Paulo Miguel Almeida Date: Mon, 7 Nov 2022 22:32:51 +1300 Subject: drm/amdgpu: Replace 1-element array with flexible-array member One-element arrays are deprecated, and we are replacing them with flexible array members instead. So, replace one-element array with flexible-array member in structs _ATOM_GPIO_PIN_ASSIGNMENT, _ATOM_DISPLAY_OBJECT_PATH, _ATOM_DISPLAY_OBJECT_PATH_TABLE, _ATOM_OBJECT_TABLE and refactor the rest of the code accordingly. Important to mention is that doing a build before/after this patch results in no functional binary output differences. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/79 Link: https://github.com/KSPP/linux/issues/238 Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101836 [1] Signed-off-by: Paulo Miguel Almeida Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 23 +++++++++++++++-------- drivers/gpu/drm/amd/include/atombios.h | 8 ++++---- 2 files changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 9b8ea6e9a2b9..39dd8b2dc254 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -138,7 +138,9 @@ static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset) uint32_t object_table_offset = bp->object_info_tbl_offset + offset; - table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset); + table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, + object_table_offset, + struct_size(table, asObjects, 1))); if (!table) return 0; @@ -166,8 +168,9 @@ static struct graphics_object_id bios_parser_get_connector_id( uint32_t connector_table_offset = bp->object_info_tbl_offset + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); - ATOM_OBJECT_TABLE *tbl = - GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset); + ATOM_OBJECT_TABLE *tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, + connector_table_offset, + struct_size(tbl, asObjects, 1))); if (!tbl) { dm_error("Can't get connector table from atom bios.\n"); @@ -1789,11 +1792,13 @@ static enum bp_result bios_parser_get_gpio_pin_info( if (!DATA_TABLES(GPIO_Pin_LUT)) return BP_RESULT_BADBIOSTABLE; - header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT)); + header = ((ATOM_GPIO_PIN_LUT *) bios_get_image(&bp->base, + DATA_TABLES(GPIO_Pin_LUT), + struct_size(header, asGPIO_Pin, 1))); if (!header) return BP_RESULT_BADBIOSTABLE; - if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT) + if (sizeof(ATOM_COMMON_TABLE_HEADER) + struct_size(header, asGPIO_Pin, 1) > le16_to_cpu(header->sHeader.usStructureSize)) return BP_RESULT_BADBIOSTABLE; @@ -1978,7 +1983,8 @@ static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, offset += bp->object_info_tbl_offset; - tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset); + tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, offset, + struct_size(tbl, asObjects, 1))); if (!tbl) return NULL; @@ -2709,8 +2715,9 @@ static enum bp_result get_bracket_layout_record( genericTableOffset = bp->object_info_tbl_offset + bp->object_info_tbl.v1_3->usMiscObjectTableOffset; - object_table = (ATOM_OBJECT_TABLE *) - GET_IMAGE(ATOM_OBJECT_TABLE, genericTableOffset); + object_table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, + genericTableOffset, + struct_size(object_table, asObjects, 1))); if (!object_table) return BP_RESULT_FAILURE; diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index b5b1d073f8e2..55ae93c1e365 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -4386,7 +4386,7 @@ typedef struct _ATOM_GPIO_PIN_ASSIGNMENT typedef struct _ATOM_GPIO_PIN_LUT { ATOM_COMMON_TABLE_HEADER sHeader; - ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[1]; + ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[]; }ATOM_GPIO_PIN_LUT; /****************************************************************************/ @@ -4513,7 +4513,7 @@ typedef struct _ATOM_DISPLAY_OBJECT_PATH USHORT usSize; //the size of ATOM_DISPLAY_OBJECT_PATH USHORT usConnObjectId; //Connector Object ID USHORT usGPUObjectId; //GPU ID - USHORT usGraphicObjIds[1]; //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. + USHORT usGraphicObjIds[]; //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. }ATOM_DISPLAY_OBJECT_PATH; typedef struct _ATOM_DISPLAY_EXTERNAL_OBJECT_PATH @@ -4530,7 +4530,7 @@ typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE UCHAR ucNumOfDispPath; UCHAR ucVersion; UCHAR ucPadding[2]; - ATOM_DISPLAY_OBJECT_PATH asDispPath[1]; + ATOM_DISPLAY_OBJECT_PATH asDispPath[]; }ATOM_DISPLAY_OBJECT_PATH_TABLE; typedef struct _ATOM_OBJECT //each object has this structure @@ -4545,7 +4545,7 @@ typedef struct _ATOM_OBJECT_TABLE //Above 4 object table { UCHAR ucNumberOfObjects; UCHAR ucPadding[3]; - ATOM_OBJECT asObjects[1]; + ATOM_OBJECT asObjects[]; }ATOM_OBJECT_TABLE; typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT //usSrcDstTableOffset pointing to this structure -- cgit v1.2.3 From fcb4f9193ee550aad05c8d0f8f6637143e567c80 Mon Sep 17 00:00:00 2001 From: LongJun Tang Date: Fri, 4 Nov 2022 17:29:31 +0800 Subject: drm/amd/display: Have risk for memory exhaustion In dcn*_clock_source_create when dcn*_clk_src_construct fails allocated clk_src needs release. A local attack could use this to cause memory exhaustion. Signed-off-by: LongJun Tang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c | 1 + 8 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index af4fe695535e..e057f8a93377 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1328,6 +1328,7 @@ static struct clock_source *dcn30_clock_source_create( return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index f04595b750ab..7c1225046544 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -1288,6 +1288,7 @@ static struct clock_source *dcn301_clock_source_create( return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index d3945876aced..9ca7db0ec7b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -464,6 +464,7 @@ static struct clock_source *dcn302_clock_source_create(struct dc_context *ctx, s return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 7e7f18bef098..932c5d5706ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -431,6 +431,7 @@ static struct clock_source *dcn303_clock_source_create(struct dc_context *ctx, s return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 8f5e89cb9d3e..15e73f4d92ab 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1629,6 +1629,7 @@ static struct clock_source *dcn31_clock_source_create( return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index 96a3d41febff..2c68862b0d8e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -1627,6 +1627,7 @@ static struct clock_source *dcn31_clock_source_create( return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 77e40ee488bd..f7fea3544c31 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -830,6 +830,7 @@ static struct clock_source *dcn32_clock_source_create( return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index e5861225f1df..d7d2c42bdb0f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -829,6 +829,7 @@ static struct clock_source *dcn321_clock_source_create( return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } -- cgit v1.2.3 From d852871c6dd17b19ae12354be1eaf7037ac79221 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Wed, 9 Nov 2022 12:06:27 -0500 Subject: drm/amd/display: only fill dirty rectangles when PSR is enabled Currently, we are calling fill_dc_dirty_rects() even if PSR isn't supported by the relevant link in amdgpu_dm_commit_planes(), this is undesirable especially because when drm.debug is enabled we are printing messages in fill_dc_dirty_rects() that are only useful for debugging PSR (and confusing otherwise). So, we can instead limit the filling of dirty rectangles to only when PSR is enabled. Reviewed-by: Leo Li Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 3db79f0b5a8f..5114726dedf7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7684,9 +7684,10 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, bundle->surface_updates[planes_count].plane_info = &bundle->plane_infos[planes_count]; - fill_dc_dirty_rects(plane, old_plane_state, new_plane_state, - new_crtc_state, - &bundle->flip_addrs[planes_count]); + if (acrtc_state->stream->link->psr_settings.psr_feature_enabled) + fill_dc_dirty_rects(plane, old_plane_state, + new_plane_state, new_crtc_state, + &bundle->flip_addrs[planes_count]); /* * Only allow immediate flips for fast updates that don't -- cgit v1.2.3 From d1a372af1c3d834c2346b2e822cd6c40abc09866 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Fri, 26 Aug 2022 18:22:35 -0400 Subject: drm/amdgpu: Set MTYPE in PTE based on BO flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same BO may need different MTYPEs and SNOOP flags in PTEs depending on its current location relative to the mapping GPU. Setting MTYPEs from clients ahead of time is not practical for coherent memory sharing. Instead determine the correct MTYPE for the desired coherence model and current BO location when updating the page tables. To maintain backwards compatibility with MTYPE-selection in AMDGPU_VA_OP_MAP, the coherence-model-based MTYPE selection is only applied if it chooses an MTYPE other than MTYPE_NC (the default). Add two AMDGPU_GEM_CREATE_... flags to indicate the coherence model. The default if no flag is specified is non-coherent (i.e. coarse-grained coherent at dispatch boundaries). Update amdgpu_amdkfd_gpuvm.c to use this new method to choose the correct MTYPE depending on the current memory location. v2: * check that bo is not NULL (e.g. PRT mappings) * Fix missing ~ bitmask in gmc_v11_0.c v3: * squash in "drm/amdgpu: Inherit coherence flags on dmabuf import" Suggested-by: Christian König Signed-off-by: Felix Kuehling Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 59 +++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 4 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 7 +++ drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 7 +++ drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 79 +++++++++++++++++++++--- 5 files changed, 96 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index ba72a910d0d5..c5c9bfa2772e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -405,63 +405,15 @@ static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync) static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem) { - struct amdgpu_device *bo_adev = amdgpu_ttm_adev(mem->bo->tbo.bdev); - bool coherent = mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT; - bool uncached = mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED; - uint32_t mapping_flags; - uint64_t pte_flags; - bool snoop = false; + uint32_t mapping_flags = AMDGPU_VM_PAGE_READABLE | + AMDGPU_VM_MTYPE_DEFAULT; - mapping_flags = AMDGPU_VM_PAGE_READABLE; if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE) mapping_flags |= AMDGPU_VM_PAGE_WRITEABLE; if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE) mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE; - switch (adev->ip_versions[GC_HWIP][0]) { - case IP_VERSION(9, 4, 1): - case IP_VERSION(9, 4, 2): - if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { - if (bo_adev == adev) { - if (uncached) - mapping_flags |= AMDGPU_VM_MTYPE_UC; - else if (coherent) - mapping_flags |= AMDGPU_VM_MTYPE_CC; - else - mapping_flags |= AMDGPU_VM_MTYPE_RW; - if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) && - adev->gmc.xgmi.connected_to_cpu) - snoop = true; - } else { - if (uncached || coherent) - mapping_flags |= AMDGPU_VM_MTYPE_UC; - else - mapping_flags |= AMDGPU_VM_MTYPE_NC; - if (amdgpu_xgmi_same_hive(adev, bo_adev)) - snoop = true; - } - } else { - if (uncached || coherent) - mapping_flags |= AMDGPU_VM_MTYPE_UC; - else - mapping_flags |= AMDGPU_VM_MTYPE_NC; - snoop = true; - } - break; - default: - if (uncached || coherent) - mapping_flags |= AMDGPU_VM_MTYPE_UC; - else - mapping_flags |= AMDGPU_VM_MTYPE_NC; - - if (!(mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM)) - snoop = true; - } - - pte_flags = amdgpu_gem_va_map_flags(adev, mapping_flags); - pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0; - - return pte_flags; + return amdgpu_gem_va_map_flags(adev, mapping_flags); } /** @@ -1673,6 +1625,11 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( } } + if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT) + alloc_flags |= AMDGPU_GEM_CREATE_COHERENT; + if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED) + alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED; + *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); if (!*mem) { ret = -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 7bd8e33b14be..271e30e34d93 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -328,7 +328,9 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf) if (dma_buf->ops == &amdgpu_dmabuf_ops) { struct amdgpu_bo *other = gem_to_amdgpu_bo(dma_buf->priv); - flags |= other->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC; + flags |= other->flags & (AMDGPU_GEM_CREATE_CPU_GTT_USWC | + AMDGPU_GEM_CREATE_COHERENT | + AMDGPU_GEM_CREATE_UNCACHED); } ret = amdgpu_gem_object_create(adev, dma_buf->size, PAGE_SIZE, diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index f513e2c2e964..a83efdc8aa0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -612,6 +612,8 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *mapping, uint64_t *flags) { + struct amdgpu_bo *bo = mapping->bo_va->base.bo; + *flags &= ~AMDGPU_PTE_EXECUTABLE; *flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE; @@ -628,6 +630,11 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev, *flags |= AMDGPU_PTE_SYSTEM; *flags &= ~AMDGPU_PTE_VALID; } + + if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT | + AMDGPU_GEM_CREATE_UNCACHED)) + *flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) | + AMDGPU_PTE_MTYPE_NV10(MTYPE_UC); } static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index 66dfb574cc7d..16f52049d986 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -503,6 +503,8 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *mapping, uint64_t *flags) { + struct amdgpu_bo *bo = mapping->bo_va->base.bo; + *flags &= ~AMDGPU_PTE_EXECUTABLE; *flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE; @@ -519,6 +521,11 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev, *flags |= AMDGPU_PTE_SYSTEM; *flags &= ~AMDGPU_PTE_VALID; } + + if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT | + AMDGPU_GEM_CREATE_UNCACHED)) + *flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) | + AMDGPU_PTE_MTYPE_NV10(MTYPE_UC); } static unsigned gmc_v11_0_get_vbios_fb_size(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 67ca16a8027c..50386eb2eec8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1113,6 +1113,74 @@ static void gmc_v9_0_get_vm_pde(struct amdgpu_device *adev, int level, } } +static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev, + struct amdgpu_bo *bo, + struct amdgpu_bo_va_mapping *mapping, + uint64_t *flags) +{ + struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev); + bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM; + bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT; + bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED; + unsigned int mtype; + bool snoop = false; + + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(9, 4, 1): + case IP_VERSION(9, 4, 2): + if (is_vram) { + if (bo_adev == adev) { + if (uncached) + mtype = MTYPE_UC; + else if (coherent) + mtype = MTYPE_CC; + else + mtype = MTYPE_RW; + /* FIXME: is this still needed? Or does + * amdgpu_ttm_tt_pde_flags already handle this? + */ + if (adev->ip_versions[GC_HWIP][0] == + IP_VERSION(9, 4, 2) && + adev->gmc.xgmi.connected_to_cpu) + snoop = true; + } else { + if (uncached || coherent) + mtype = MTYPE_UC; + else + mtype = MTYPE_NC; + if (mapping->bo_va->is_xgmi) + snoop = true; + } + } else { + if (uncached || coherent) + mtype = MTYPE_UC; + else + mtype = MTYPE_NC; + /* FIXME: is this still needed? Or does + * amdgpu_ttm_tt_pde_flags already handle this? + */ + snoop = true; + } + break; + default: + if (uncached || coherent) + mtype = MTYPE_UC; + else + mtype = MTYPE_NC; + + /* FIXME: is this still needed? Or does + * amdgpu_ttm_tt_pde_flags already handle this? + */ + if (!is_vram) + snoop = true; + } + + if (mtype != MTYPE_NC) + *flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) | + AMDGPU_PTE_MTYPE_VG10(mtype); + *flags |= snoop ? AMDGPU_PTE_SNOOPED : 0; +} + static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *mapping, uint64_t *flags) @@ -1128,14 +1196,9 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev, *flags &= ~AMDGPU_PTE_VALID; } - if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) || - adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) && - !(*flags & AMDGPU_PTE_SYSTEM) && - mapping->bo_va->is_xgmi) - *flags |= AMDGPU_PTE_SNOOPED; - - if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) - *flags |= mapping->flags & AMDGPU_PTE_SNOOPED; + if (mapping->bo_va->base.bo) + gmc_v9_0_get_coherence_flags(adev, mapping->bo_va->base.bo, + mapping, flags); } static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) -- cgit v1.2.3 From bc66c9ab162d2a633ee3eb864d7bc2369e79c1e4 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Thu, 3 Nov 2022 11:05:19 +0800 Subject: drm/amd/pm: update SMU IP v13.0.4 msg interface header Some of the unused messages that were used earlier in development have been freed up as spare messages, no intended functional changes. Signed-off-by: Mario Limonciello Signed-off-by: Tim Huang Acked-by: Alex Deucher Reviewed-by: Yifan Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- .../gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h index d9b0cd752200..f4d6c07b56ea 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h @@ -54,14 +54,14 @@ #define PPSMC_MSG_TestMessage 0x01 ///< To check if PMFW is alive and responding. Requirement specified by PMFW team #define PPSMC_MSG_GetPmfwVersion 0x02 ///< Get PMFW version #define PPSMC_MSG_GetDriverIfVersion 0x03 ///< Get PMFW_DRIVER_IF version -#define PPSMC_MSG_EnableGfxOff 0x04 ///< Enable GFXOFF -#define PPSMC_MSG_DisableGfxOff 0x05 ///< Disable GFXOFF +#define PPSMC_MSG_SPARE0 0x04 ///< SPARE +#define PPSMC_MSG_SPARE1 0x05 ///< SPARE #define PPSMC_MSG_PowerDownVcn 0x06 ///< Power down VCN #define PPSMC_MSG_PowerUpVcn 0x07 ///< Power up VCN; VCN is power gated by default #define PPSMC_MSG_SetHardMinVcn 0x08 ///< For wireless display #define PPSMC_MSG_SetSoftMinGfxclk 0x09 ///< Set SoftMin for GFXCLK, argument is frequency in MHz -#define PPSMC_MSG_ActiveProcessNotify 0x0A ///< Needs update -#define PPSMC_MSG_ForcePowerDownGfx 0x0B ///< Force power down GFX, i.e. enter GFXOFF +#define PPSMC_MSG_SPARE2 0x0A ///< SPARE +#define PPSMC_MSG_SPARE3 0x0B ///< SPARE #define PPSMC_MSG_PrepareMp1ForUnload 0x0C ///< Prepare PMFW for GFX driver unload #define PPSMC_MSG_SetDriverDramAddrHigh 0x0D ///< Set high 32 bits of DRAM address for Driver table transfer #define PPSMC_MSG_SetDriverDramAddrLow 0x0E ///< Set low 32 bits of DRAM address for Driver table transfer @@ -73,8 +73,7 @@ #define PPSMC_MSG_SetSoftMinFclk 0x14 ///< Set hard min for FCLK #define PPSMC_MSG_SetSoftMinVcn 0x15 ///< Set soft min for VCN clocks (VCLK and DCLK) - -#define PPSMC_MSG_EnableGfxImu 0x16 ///< Needs update +#define PPSMC_MSG_EnableGfxImu 0x16 ///< Enable GFX IMU #define PPSMC_MSG_GetGfxclkFrequency 0x17 ///< Get GFX clock frequency #define PPSMC_MSG_GetFclkFrequency 0x18 ///< Get FCLK frequency @@ -102,8 +101,8 @@ #define PPSMC_MSG_SetHardMinIspxclkByFreq 0x2C ///< Set HardMin by frequency for ISPXCLK #define PPSMC_MSG_PowerDownUmsch 0x2D ///< Power down VCN.UMSCH (aka VSCH) scheduler #define PPSMC_MSG_PowerUpUmsch 0x2E ///< Power up VCN.UMSCH (aka VSCH) scheduler -#define PPSMC_Message_IspStutterOn_MmhubPgDis 0x2F ///< ISP StutterOn mmHub PgDis -#define PPSMC_Message_IspStutterOff_MmhubPgEn 0x30 ///< ISP StufferOff mmHub PgEn +#define PPSMC_MSG_IspStutterOn_MmhubPgDis 0x2F ///< ISP StutterOn mmHub PgDis +#define PPSMC_MSG_IspStutterOff_MmhubPgEn 0x30 ///< ISP StufferOff mmHub PgEn #define PPSMC_Message_Count 0x31 ///< Total number of PPSMC messages /** @}*/ -- cgit v1.2.3 From 66f7903779fbbc620bf1040017e4833ef6a0b541 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Thu, 3 Nov 2022 17:01:46 -0400 Subject: drm/amdkfd: Fix error handling in kfd_criu_restore_events mutex_unlock before the exit label because all the error code paths that jump there didn't take that lock. This fixes unbalanced locking errors in case of restore errors. Fixes: 40e8a766a761 ("drm/amdkfd: CRIU checkpoint and restore events") Signed-off-by: Felix Kuehling Reviewed-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 83e3ce9f6049..729d26d648af 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -506,6 +506,7 @@ int kfd_criu_restore_event(struct file *devkfd, ret = create_other_event(p, ev, &ev_priv->event_id); break; } + mutex_unlock(&p->event_mutex); exit: if (ret) @@ -513,8 +514,6 @@ exit: kfree(ev_priv); - mutex_unlock(&p->event_mutex); - return ret; } -- cgit v1.2.3 From b91c23e099f0b65d62159da13458c5eefa76083f Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Tue, 1 Nov 2022 15:02:48 -0400 Subject: drm/amdkfd: Fix error handling in criu_checkpoint Checkpoint BOs last. That way we don't need to close dmabuf FDs if something else fails later. This avoids problematic access to user mode memory in the error handling code path. criu_checkpoint_bos has its own error handling and cleanup that does not depend on access to user memory. In the private data, keep BOs before the remaining objects. This is necessary to restore things in the correct order as restoring events depends on the events-page BO being restored first. Fixes: be072b06c739 ("drm/amdkfd: CRIU export BOs as prime dmabuf objects") Reported-by: Jann Horn CC: Rajneesh Bhardwaj Signed-off-by: Felix Kuehling Reviewed-and-tested-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 34 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 5feaba6a77de..6d291aa6386b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1950,7 +1950,7 @@ static int criu_checkpoint(struct file *filep, { int ret; uint32_t num_devices, num_bos, num_objects; - uint64_t priv_size, priv_offset = 0; + uint64_t priv_size, priv_offset = 0, bo_priv_offset; if (!args->devices || !args->bos || !args->priv_data) return -EINVAL; @@ -1994,38 +1994,34 @@ static int criu_checkpoint(struct file *filep, if (ret) goto exit_unlock; - ret = criu_checkpoint_bos(p, num_bos, (uint8_t __user *)args->bos, - (uint8_t __user *)args->priv_data, &priv_offset); - if (ret) - goto exit_unlock; + /* Leave room for BOs in the private data. They need to be restored + * before events, but we checkpoint them last to simplify the error + * handling. + */ + bo_priv_offset = priv_offset; + priv_offset += num_bos * sizeof(struct kfd_criu_bo_priv_data); if (num_objects) { ret = kfd_criu_checkpoint_queues(p, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) - goto close_bo_fds; + goto exit_unlock; ret = kfd_criu_checkpoint_events(p, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) - goto close_bo_fds; + goto exit_unlock; ret = kfd_criu_checkpoint_svm(p, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) - goto close_bo_fds; + goto exit_unlock; } -close_bo_fds: - if (ret) { - /* If IOCTL returns err, user assumes all FDs opened in criu_dump_bos are closed */ - uint32_t i; - struct kfd_criu_bo_bucket *bo_buckets = (struct kfd_criu_bo_bucket *) args->bos; - - for (i = 0; i < num_bos; i++) { - if (bo_buckets[i].alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) - close_fd(bo_buckets[i].dmabuf_fd); - } - } + /* This must be the last thing in this function that can fail. + * Otherwise we leak dmabuf file descriptors. + */ + ret = criu_checkpoint_bos(p, num_bos, (uint8_t __user *)args->bos, + (uint8_t __user *)args->priv_data, &bo_priv_offset); exit_unlock: mutex_unlock(&p->mutex); -- cgit v1.2.3 From 77c092e054262b594614bad5e5f47e57c5d29639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 2 Nov 2022 14:55:13 +0100 Subject: drm/amdgpu: workaround for TLB seq race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can happen that we query the sequence value before the callback had a chance to run. Workaround that by grabbing the fence lock and releasing it again. Should be replaced by hw handling soon. Signed-off-by: Christian König CC: stable@vger.kernel.org # 5.19+ Fixes: 5255e146c99a6 ("drm/amdgpu: rework TLB flushing") Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2113 Acked-by: Alex Deucher Acked-by: Philip Yang Tested-by: Stefan Springer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 83acb7bd80fe..1d31771b4230 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -492,6 +492,21 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m); */ static inline uint64_t amdgpu_vm_tlb_seq(struct amdgpu_vm *vm) { + unsigned long flags; + spinlock_t *lock; + + /* + * Workaround to stop racing between the fence signaling and handling + * the cb. The lock is static after initially setting it up, just make + * sure that the dma_fence structure isn't freed up. + */ + rcu_read_lock(); + lock = vm->last_tlb_flush->lock; + rcu_read_unlock(); + + spin_lock_irqsave(lock, flags); + spin_unlock_irqrestore(lock, flags); + return atomic64_read(&vm->tlb_seq); } -- cgit v1.2.3 From 632d06985235d988c9d7e6eec8fa655be0761fd0 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 25 Oct 2022 11:26:04 -0400 Subject: drm/amd/display: Update SR watermarks for DCN314 [Why & How] New values requested by hardware after fine-tuning. Update for all memory types. Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- .../amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 32 +++++++++++----------- .../gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index 1131c6d73f6c..20a06c04e4a1 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -363,32 +363,32 @@ static struct wm_table ddr5_wm_table = { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 14.5, .valid = true, }, { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 14.5, .valid = true, }, { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 14.5, .valid = true, }, { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 14.5, .valid = true, }, } @@ -400,32 +400,32 @@ static struct wm_table lpddr5_wm_table = { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .valid = true, }, { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .valid = true, }, { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .valid = true, }, { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .valid = true, }, } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index cf420ad2b8dc..34b6c763a455 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -146,8 +146,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { }, }, .num_states = 5, - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, + .sr_exit_time_us = 16.5, + .sr_enter_plus_exit_time_us = 18.5, .sr_exit_z8_time_us = 442.0, .sr_enter_plus_exit_z8_time_us = 560.0, .writeback_latency_us = 12.0, -- cgit v1.2.3 From ab4b35008db9b7ae747679250e5c26d7c3a90cea Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Thu, 20 Oct 2022 17:26:24 -0400 Subject: drm/amd/display: Zeromem mypipe heap struct before using it [Why&How] Bug was caused when moving variable from stack to heap because it was reusable and garbage was left over, so we need to zero mem. Reviewed-by: Martin Leung Acked-by: Alan Liu Signed-off-by: Aurabindo Pillai Signed-off-by: Martin Leung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 3d184679f129..ae6e6abc620b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -3192,6 +3192,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.FCLKChangeLatency, mode_lib->vba.UrgLatency[i], mode_lib->vba.SREnterPlusExitTime); + memset(&v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull, 0, sizeof(DmlPipe)); v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.myPipe.Dppclk = mode_lib->vba.RequiredDPPCLK[i][j][k]; v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.myPipe.Dispclk = mode_lib->vba.RequiredDISPCLK[i][j]; v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.myPipe.PixelClock = mode_lib->vba.PixelClock[k]; -- cgit v1.2.3 From 0d5c5c210a4d4e655feb93b379647f0b179cdafe Mon Sep 17 00:00:00 2001 From: Chaitanya Dhere Date: Thu, 27 Oct 2022 09:51:19 -0400 Subject: drm/amd/display: Fix FCLK deviation and tool compile issues [Why] Recent backports from open source do not have header inclusion pattern that is consistent with inclusion style in the rest of the file. This breaks the internal tool builds as well. A recent commit erronously modified the original DML formula for calculating ActiveClockChangeLatencyHidingY. This resulted in a FCLK deviation from the golden values. [How] Change the way in which display_mode_vba.h is included so that it is consistent with the inclusion style in rest of the file which also fixes the tool build. Restore the DML formula to its original state to fix the FCLK deviation. Reviewed-by: Aurabindo Pillai Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Chaitanya Dhere Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 968924c491c1..ab9217732a17 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -4397,7 +4397,7 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( if (v->NumberOfActiveSurfaces > 1) { ActiveClockChangeLatencyHidingY = ActiveClockChangeLatencyHidingY - - (1 - 1 / v->NumberOfActiveSurfaces) * SwathHeightY[k] * v->HTotal[k] + - (1.0 - 1.0 / v->NumberOfActiveSurfaces) * SwathHeightY[k] * v->HTotal[k] / v->PixelClock[k] / v->VRatio[k]; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index 2c3827546ac7..fdccaa93eb2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -30,7 +30,7 @@ #include "os_types.h" #include "../dc_features.h" #include "../display_mode_structs.h" -#include "dml/display_mode_vba.h" +#include "../display_mode_vba.h" unsigned int dml32_dscceComputeDelay( unsigned int bpc, -- cgit v1.2.3 From ce62198d8b62734a985d22652e75a649be052390 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Thu, 27 Oct 2022 15:34:33 -0400 Subject: drm/amd/display: Fix reg timeout in enc314_enable_fifo [Why] The link enablement sequence can end up resetting the encoder while the PHY symclk isn't yet on. This means that waiting for symclk on will timeout, along with the reset bit never asserting high. This causes unnecessary delay when enabling the link and produces a warning affecting multiple IGT tests. [How] Don't wait for the symclk to be on here because firmware already does. Don't wait for reset if we know the symclk isn't on. Split the reset into a helper function that checks the bit and decides whether or not a delay is sufficient. Reviewed-by: Roman Li Acked-by: Alan Liu Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.0.x --- .../display/dc/dcn314/dcn314_dio_stream_encoder.c | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c index 7e773bf7b895..38842f938bed 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c @@ -49,18 +49,30 @@ #define CTX \ enc1->base.ctx +static void enc314_reset_fifo(struct stream_encoder *enc, bool reset) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t reset_val = reset ? 1 : 0; + uint32_t is_symclk_on; + + REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, reset_val); + REG_GET(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, &is_symclk_on); + + if (is_symclk_on) + REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, reset_val, 10, 5000); + else + udelay(10); +} static void enc314_enable_fifo(struct stream_encoder *enc) { struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - /* TODO: Confirm if we need to wait for DIG_SYMCLK_FE_ON */ - REG_WAIT(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, 1, 10, 5000); REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7); - REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1); - REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 10, 5000); - REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0); - REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 10, 5000); + + enc314_reset_fifo(enc, true); + enc314_reset_fifo(enc, false); + REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1); } -- cgit v1.2.3 From c0b2753f5db281b07013899c79b5f06a614055f9 Mon Sep 17 00:00:00 2001 From: Steve Su Date: Fri, 28 Oct 2022 05:52:32 +0800 Subject: drm/amd/display: Fix gpio port mapping issue [Why] 1. Port of gpio has different mapping. [How] 1. Add a dummy entry in mapping table. 2. Fix incorrect mask bit field access. Reviewed-by: Alvin Lee Acked-by: Alan Liu Signed-off-by: Steve Su Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c | 14 ++++++++++++++ drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 9 ++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c index d635b73af46f..0ea52ba5ac82 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c @@ -107,6 +107,13 @@ static const struct ddc_registers ddc_data_regs_dcn[] = { ddc_data_regs_dcn2(3), ddc_data_regs_dcn2(4), ddc_data_regs_dcn2(5), + { + // add a dummy entry for cases no such port + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + .ddc_setup = 0, + .phy_aux_cntl = 0, + .dc_gpio_aux_ctrl_5 = 0 + }, { DDC_GPIO_VGA_REG_LIST(DATA), .ddc_setup = 0, @@ -121,6 +128,13 @@ static const struct ddc_registers ddc_clk_regs_dcn[] = { ddc_clk_regs_dcn2(3), ddc_clk_regs_dcn2(4), ddc_clk_regs_dcn2(5), + { + // add a dummy entry for cases no such port + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + .ddc_setup = 0, + .phy_aux_cntl = 0, + .dc_gpio_aux_ctrl_5 = 0 + }, { DDC_GPIO_VGA_REG_LIST(CLK), .ddc_setup = 0, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c index 6fd38cdd68c0..525bc8881950 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -94,11 +94,14 @@ static enum gpio_result set_config( * is required for detection of AUX mode */ if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) { if (!ddc_data_pd_en || !ddc_clk_pd_en) { - - REG_SET_2(gpio.MASK_reg, regval, + if (hw_gpio->base.en == GPIO_DDC_LINE_DDC_VGA) { + // bit 4 of mask has different usage in some cases + REG_SET(gpio.MASK_reg, regval, DC_GPIO_DDC1DATA_PD_EN, 1); + } else { + REG_SET_2(gpio.MASK_reg, regval, DC_GPIO_DDC1DATA_PD_EN, 1, DC_GPIO_DDC1CLK_PD_EN, 1); - + } if (config_data->type == GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) msleep(3); -- cgit v1.2.3 From ce902d987a8caa5c9a96080e280ecc992414a127 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 27 Oct 2022 16:22:26 -0400 Subject: drm/amd/display: Enforce minimum prefetch time for low memclk on DCN32 [WHY?] Data return times when using lowest memclk can be <= 60us, which can cause underflow on high bandwidth displays with a workload. [HOW?] Enforce a minimum prefetch time during validation for low memclk modes. Reviewed-by: Jun Lei Acked-by: Alan Liu Signed-off-by: Dillon Varone Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 2 ++ .../gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 4 ++++ .../gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h | 3 +++ .../drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 12 ++++++++++-- .../drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c | 2 ++ drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 1 + 10 files changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 737b221ca689..0598465fd1a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -853,6 +853,7 @@ struct dc_debug_options { bool enable_dp_dig_pixel_rate_div_policy; enum lttpr_mode lttpr_mode_override; unsigned int dsc_delay_factor_wa_x1000; + unsigned int min_prefetch_in_strobe_ns; }; struct gpu_info_soc_bounding_box_v1_0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index a88dd7b3d1c1..d1598e3131f6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -724,6 +724,7 @@ static const struct dc_debug_options debug_defaults_drv = { .enable_dp_dig_pixel_rate_div_policy = 1, .allow_sw_cursor_fallback = false, .alloc_extra_way_for_cursor = true, + .min_prefetch_in_strobe_ns = 60000, // 60us }; static const struct dc_debug_options debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index 61087f2385a9..6292ac515d1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -722,6 +722,7 @@ static const struct dc_debug_options debug_defaults_drv = { .enable_dp_dig_pixel_rate_div_policy = 1, .allow_sw_cursor_fallback = false, .alloc_extra_way_for_cursor = true, + .min_prefetch_in_strobe_ns = 60000, // 60us }; static const struct dc_debug_options debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index f37c9a6b3b7e..659323ebd79d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -2364,6 +2364,8 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa /* DML DSC delay factor workaround */ dcn3_2_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0; + dcn3_2_ip.min_prefetch_in_strobe_us = dc->debug.min_prefetch_in_strobe_ns / 1000.0; + /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */ dcn3_2_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index ae6e6abc620b..244fd15d24b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -786,6 +786,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->SwathHeightY[k], v->SwathHeightC[k], TWait, + v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ ? + mode_lib->vba.ip.min_prefetch_in_strobe_us : 0, /* Output */ &v->DSTXAfterScaler[k], &v->DSTYAfterScaler[k], @@ -3245,6 +3247,8 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l v->swath_width_chroma_ub_this_state[k], v->SwathHeightYThisState[k], v->SwathHeightCThisState[k], v->TWait, + v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ ? + mode_lib->vba.ip.min_prefetch_in_strobe_us : 0, /* Output */ &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.DSTXAfterScaler[k], diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h index c62e0991358b..f82e14cd9d8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h @@ -49,6 +49,9 @@ #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff +#define MEM_STROBE_FREQ_MHZ 1600 +#define MEM_STROBE_MAX_DELIVERY_TIME_US 60.0 + struct display_mode_lib; void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index ab9217732a17..635fc54338fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -3417,6 +3417,7 @@ bool dml32_CalculatePrefetchSchedule( unsigned int SwathHeightY, unsigned int SwathHeightC, double TWait, + double TPreReq, /* Output */ double *DSTXAfterScaler, double *DSTYAfterScaler, @@ -3474,6 +3475,7 @@ bool dml32_CalculatePrefetchSchedule( double min_Lsw; double Tsw_est1 = 0; double Tsw_est3 = 0; + double TPreMargin = 0; if (v->GPUVMEnable == true && v->HostVMEnable == true) HostVMDynamicLevelsTrips = v->HostVMMaxNonCachedPageTableLevels; @@ -3699,6 +3701,8 @@ bool dml32_CalculatePrefetchSchedule( dst_y_prefetch_equ = dml_floor(4.0 * (dst_y_prefetch_equ + 0.125), 1) / 4.0; Tpre_rounded = dst_y_prefetch_equ * LineTime; + + TPreMargin = Tpre_rounded - TPreReq; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: dst_y_prefetch_equ: %f (after round)\n", __func__, dst_y_prefetch_equ); dml_print("DML::%s: LineTime: %f\n", __func__, LineTime); @@ -3726,7 +3730,7 @@ bool dml32_CalculatePrefetchSchedule( *VRatioPrefetchY = 0; *VRatioPrefetchC = 0; *RequiredPrefetchPixDataBWLuma = 0; - if (dst_y_prefetch_equ > 1) { + if (dst_y_prefetch_equ > 1 && TPreMargin > 0.0) { double PrefetchBandwidth1; double PrefetchBandwidth2; double PrefetchBandwidth3; @@ -3872,7 +3876,11 @@ bool dml32_CalculatePrefetchSchedule( } if (dst_y_prefetch_oto < dst_y_prefetch_equ) { - *DestinationLinesForPrefetch = dst_y_prefetch_oto; + if (dst_y_prefetch_oto * LineTime < TPreReq) { + *DestinationLinesForPrefetch = dst_y_prefetch_equ; + } else { + *DestinationLinesForPrefetch = dst_y_prefetch_oto; + } TimeForFetchingMetaPTE = Tvm_oto; TimeForFetchingRowInVBlank = Tr0_oto; *PrefetchBandwidth = prefetch_bw_oto; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index fdccaa93eb2e..3989c2a28fae 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -743,6 +743,7 @@ bool dml32_CalculatePrefetchSchedule( unsigned int SwathHeightY, unsigned int SwathHeightC, double TWait, + double TPreReq, /* Output */ double *DSTXAfterScaler, double *DSTYAfterScaler, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index ec0486efab14..432b4ecd01a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -544,6 +544,8 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p /* DML DSC delay factor workaround */ dcn3_21_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0; + dcn3_21_ip.min_prefetch_in_strobe_us = dc->debug.min_prefetch_in_strobe_ns / 1000.0; + /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */ dcn3_21_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index d7be01ac0751..64d602e6412f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -367,6 +367,7 @@ struct _vcs_dpi_ip_params_st { /* DM workarounds */ double dsc_delay_factor_wa; // TODO: Remove after implementing root cause fix + double min_prefetch_in_strobe_us; }; struct _vcs_dpi_display_xfc_params_st { -- cgit v1.2.3 From 30b8e7b8ee3be003e0df85c857c5cd0e0bd58b82 Mon Sep 17 00:00:00 2001 From: Asher Song Date: Thu, 3 Nov 2022 18:28:40 +0800 Subject: Revert "drm/amdgpu: Revert "drm/amdgpu: getting fan speed pwm for vega10 properly"" This reverts commit 4545ae2ed3f2f7c3f615a53399c9c8460ee5bca7. The origin patch "drm/amdgpu: getting fan speed pwm for vega10 properly" works fine. Test failure is caused by test case self. Signed-off-by: Asher Song Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- .../drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 25 +++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index dad3e3741a4e..190af79f3236 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -67,22 +67,21 @@ int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, int vega10_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr, uint32_t *speed) { - uint32_t current_rpm; - uint32_t percent = 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return 0; + struct amdgpu_device *adev = hwmgr->adev; + uint32_t duty100, duty; + uint64_t tmp64; - if (vega10_get_current_rpm(hwmgr, ¤t_rpm)) - return -1; + duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), + CG_FDO_CTRL1, FMAX_DUTY100); + duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS), + CG_THERMAL_STATUS, FDO_PWM_DUTY); - if (hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM != 0) - percent = current_rpm * 255 / - hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM; + if (!duty100) + return -EINVAL; - *speed = MIN(percent, 255); + tmp64 = (uint64_t)duty * 255; + do_div(tmp64, duty100); + *speed = MIN((uint32_t)tmp64, 255); return 0; } -- cgit v1.2.3 From 64f65135c41a75f933d3bca236417ad8e9eb75de Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Thu, 3 Nov 2022 10:24:52 -0400 Subject: drm/amdgpu: Unlock bo_list_mutex after error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get below kernel WARNING backtrace when pressing ctrl-C to kill kfdtest application. If amdgpu_cs_parser_bos returns error after taking bo_list_mutex, as caller amdgpu_cs_ioctl will not unlock bo_list_mutex, this generates the kernel WARNING. Add unlock bo_list_mutex after amdgpu_cs_parser_bos error handling to cleanup bo_list userptr bo. WARNING: kfdtest/2930 still has locks held! 1 lock held by kfdtest/2930: (&list->bo_list_mutex){+.+.}-{3:3}, at: amdgpu_cs_ioctl+0xce5/0x1f10 [amdgpu] stack backtrace: dump_stack_lvl+0x44/0x57 get_signal+0x79f/0xd00 arch_do_signal_or_restart+0x36/0x7b0 exit_to_user_mode_prepare+0xfd/0x1b0 syscall_exit_to_user_mode+0x19/0x40 do_syscall_64+0x40/0x80 Signed-off-by: Philip Yang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1bbd39b3b0fc..d371000a5727 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -992,6 +992,7 @@ out_free_user_pages: kvfree(e->user_pages); e->user_pages = NULL; } + mutex_unlock(&p->bo_list->bo_list_mutex); return r; } -- cgit v1.2.3 From e034a0d9aaee5c9129d5dfdfdfcab988a953412d Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Wed, 2 Nov 2022 16:55:31 -0400 Subject: drm/amdgpu: Drop eviction lock when allocating PT BO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-take the eviction lock immediately again after the allocation is completed, to fix circular locking warning with drm_buddy allocator. Move amdgpu_vm_eviction_lock/unlock/trylock to amdgpu_vm.h as they are called from multiple files. Signed-off-by: Philip Yang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 26 -------------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 26 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 2 ++ 3 files changed, 28 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 2291aa14d888..003aa9e47085 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -143,32 +143,6 @@ int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm, return 0; } -/* - * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS - * happens while holding this lock anywhere to prevent deadlocks when - * an MMU notifier runs in reclaim-FS context. - */ -static inline void amdgpu_vm_eviction_lock(struct amdgpu_vm *vm) -{ - mutex_lock(&vm->eviction_lock); - vm->saved_flags = memalloc_noreclaim_save(); -} - -static inline int amdgpu_vm_eviction_trylock(struct amdgpu_vm *vm) -{ - if (mutex_trylock(&vm->eviction_lock)) { - vm->saved_flags = memalloc_noreclaim_save(); - return 1; - } - return 0; -} - -static inline void amdgpu_vm_eviction_unlock(struct amdgpu_vm *vm) -{ - memalloc_noreclaim_restore(vm->saved_flags); - mutex_unlock(&vm->eviction_lock); -} - /** * amdgpu_vm_bo_evicted - vm_bo is evicted * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 1d31771b4230..6546e786bf00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -510,4 +510,30 @@ static inline uint64_t amdgpu_vm_tlb_seq(struct amdgpu_vm *vm) return atomic64_read(&vm->tlb_seq); } +/* + * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS + * happens while holding this lock anywhere to prevent deadlocks when + * an MMU notifier runs in reclaim-FS context. + */ +static inline void amdgpu_vm_eviction_lock(struct amdgpu_vm *vm) +{ + mutex_lock(&vm->eviction_lock); + vm->saved_flags = memalloc_noreclaim_save(); +} + +static inline bool amdgpu_vm_eviction_trylock(struct amdgpu_vm *vm) +{ + if (mutex_trylock(&vm->eviction_lock)) { + vm->saved_flags = memalloc_noreclaim_save(); + return true; + } + return false; +} + +static inline void amdgpu_vm_eviction_unlock(struct amdgpu_vm *vm) +{ + memalloc_noreclaim_restore(vm->saved_flags); + mutex_unlock(&vm->eviction_lock); +} + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c index 358b91243e37..b5f3bba851db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c @@ -597,7 +597,9 @@ static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev, if (entry->bo) return 0; + amdgpu_vm_eviction_unlock(vm); r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt); + amdgpu_vm_eviction_lock(vm); if (r) return r; -- cgit v1.2.3 From 0c85c067c9d9d7a1b2cc2e01a236d5d0d4a872b5 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Mon, 7 Nov 2022 16:46:59 +0800 Subject: drm/amdgpu: disable BACO on special BEIGE_GOBY card Still avoid intermittent failure. Signed-off-by: Guchun Chen Reviewed-by: Lijo Lazar Acked-by: Evan Quan Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 74996a8fb671..6212fd270857 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -377,7 +377,9 @@ static void sienna_cichlid_check_bxco_support(struct smu_context *smu) if (((adev->pdev->device == 0x73A1) && (adev->pdev->revision == 0x00)) || ((adev->pdev->device == 0x73BF) && - (adev->pdev->revision == 0xCF))) + (adev->pdev->revision == 0xCF)) || + ((adev->pdev->device == 0x7422) && + (adev->pdev->revision == 0x00))) smu_baco->platform_support = false; } -- cgit v1.2.3 From 675d84621a24490e1de3d59a4992a17fa9ff92b5 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Wed, 9 Nov 2022 12:06:27 -0500 Subject: drm/amd/display: only fill dirty rectangles when PSR is enabled Currently, we are calling fill_dc_dirty_rects() even if PSR isn't supported by the relevant link in amdgpu_dm_commit_planes(), this is undesirable especially because when drm.debug is enabled we are printing messages in fill_dc_dirty_rects() that are only useful for debugging PSR (and confusing otherwise). So, we can instead limit the filling of dirty rectangles to only when PSR is enabled. Reviewed-by: Leo Li Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 589bee9acf16..509739d83b5a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7622,9 +7622,10 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, bundle->surface_updates[planes_count].plane_info = &bundle->plane_infos[planes_count]; - fill_dc_dirty_rects(plane, old_plane_state, new_plane_state, - new_crtc_state, - &bundle->flip_addrs[planes_count]); + if (acrtc_state->stream->link->psr_settings.psr_feature_enabled) + fill_dc_dirty_rects(plane, old_plane_state, + new_plane_state, new_crtc_state, + &bundle->flip_addrs[planes_count]); /* * Only allow immediate flips for fast updates that don't -- cgit v1.2.3 From 6d47b53fb3f363a74538a1dbd09954af3d8d4131 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 9 Nov 2022 09:15:37 +0800 Subject: net: cpsw: disable napi in cpsw_ndo_open() When failed to create xdp rxqs or fill rx channels in cpsw_ndo_open() for opening device, napi isn't disabled. When open cpsw device next time, it will report a invalid opcode issue. Compiled tested only. Fixes: d354eb85d618 ("drivers: net: cpsw: dual_emac: simplify napi usage") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221109011537.96975-1-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ti/cpsw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 709ca6dd6ecb..13c9c2d6b79b 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -854,6 +854,8 @@ static int cpsw_ndo_open(struct net_device *ndev) err_cleanup: if (!cpsw->usage_count) { + napi_disable(&cpsw->napi_rx); + napi_disable(&cpsw->napi_tx); cpdma_ctlr_stop(cpsw->dma); cpsw_destroy_xdp_rxqs(cpsw); } -- cgit v1.2.3 From d75aed1428da787cbe42bc073d76f1354f364d92 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 9 Nov 2022 10:14:51 +0800 Subject: net: cxgb3_main: disable napi when bind qsets failed in cxgb_up() When failed to bind qsets in cxgb_up() for opening device, napi isn't disabled. When open cxgb3 device next time, it will trigger a BUG_ON() in napi_enable(). Compile tested only. Fixes: 48c4b6dbb7e2 ("cxgb3 - fix port up/down error path") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221109021451.121490-1-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index a52e6b6e2876..9b84c8d8d309 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -1301,6 +1301,7 @@ static int cxgb_up(struct adapter *adap) if (ret < 0) { CH_ERR(adap, "failed to bind qsets, err %d\n", ret); t3_intr_disable(adap); + quiesce_rx(adap); free_irq_resources(adap); err = ret; goto out; -- cgit v1.2.3 From dcea1a8107c04b9521dee1dd37971757a22db162 Mon Sep 17 00:00:00 2001 From: "Tan, Tee Min" Date: Mon, 7 Nov 2022 21:08:11 -0500 Subject: stmmac: intel: Update PCH PTP clock rate from 200MHz to 204.8MHz Current Intel platform has an output of ~976ms interval when probed on 1 Pulse-per-Second(PPS) hardware pin. The correct PTP clock frequency for PCH GbE should be 204.8MHz instead of 200MHz. PSE GbE PTP clock rate remains at 200MHz. Fixes: 58da0cfa6cf1 ("net: stmmac: create dwmac-intel.c to contain all Intel platform") Signed-off-by: Ling Pei Lee Signed-off-by: Tan, Tee Min Signed-off-by: Voon Weifeng Signed-off-by: Gan Yi Fang Link: https://lore.kernel.org/r/20221108020811.12919-1-yi.fang.gan@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 0a2afc1a3124..7deb1f817dac 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -629,7 +629,6 @@ static int ehl_common_data(struct pci_dev *pdev, { plat->rx_queues_to_use = 8; plat->tx_queues_to_use = 8; - plat->clk_ptp_rate = 200000000; plat->use_phy_wol = 1; plat->safety_feat_cfg->tsoee = 1; @@ -654,6 +653,8 @@ static int ehl_sgmii_data(struct pci_dev *pdev, plat->serdes_powerup = intel_serdes_powerup; plat->serdes_powerdown = intel_serdes_powerdown; + plat->clk_ptp_rate = 204800000; + return ehl_common_data(pdev, plat); } @@ -667,6 +668,8 @@ static int ehl_rgmii_data(struct pci_dev *pdev, plat->bus_id = 1; plat->phy_interface = PHY_INTERFACE_MODE_RGMII; + plat->clk_ptp_rate = 204800000; + return ehl_common_data(pdev, plat); } @@ -683,6 +686,8 @@ static int ehl_pse0_common_data(struct pci_dev *pdev, plat->bus_id = 2; plat->addr64 = 32; + plat->clk_ptp_rate = 200000000; + intel_mgbe_pse_crossts_adj(intel_priv, EHL_PSE_ART_MHZ); return ehl_common_data(pdev, plat); @@ -722,6 +727,8 @@ static int ehl_pse1_common_data(struct pci_dev *pdev, plat->bus_id = 3; plat->addr64 = 32; + plat->clk_ptp_rate = 200000000; + intel_mgbe_pse_crossts_adj(intel_priv, EHL_PSE_ART_MHZ); return ehl_common_data(pdev, plat); @@ -757,7 +764,7 @@ static int tgl_common_data(struct pci_dev *pdev, { plat->rx_queues_to_use = 6; plat->tx_queues_to_use = 4; - plat->clk_ptp_rate = 200000000; + plat->clk_ptp_rate = 204800000; plat->speed_mode_2500 = intel_speed_mode_2500; plat->safety_feat_cfg->tsoee = 1; -- cgit v1.2.3 From c6092ea1e6d7bd12acd881f6aa2b5054cd70e096 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 9 Nov 2022 09:21:00 +0800 Subject: cxgb4vf: shut down the adapter when t4vf_update_port_info() failed in cxgb4vf_open() When t4vf_update_port_info() failed in cxgb4vf_open(), resources applied during adapter goes up are not cleared. Fix it. Only be compiled, not be tested. Fixes: 18d79f721e0a ("cxgb4vf: Update port information in cxgb4vf_open()") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221109012100.99132-1-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 54db79f4dcfe..63b2bd084130 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -858,7 +858,7 @@ static int cxgb4vf_open(struct net_device *dev) */ err = t4vf_update_port_info(pi); if (err < 0) - return err; + goto err_unwind; /* * Note that this interface is up and start everything up ... -- cgit v1.2.3 From 764afecbbcd26bea57fcd928680d413b2c851590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Oct 2022 14:39:06 +0300 Subject: drm/i915: Create resized LUTs for ivb+ split gamma mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently when opeating in split gamma mode we do the "skip ever other sw LUT entry" trick in the low level LUT programming/readout functions. That is very annoying and a big hinderance to revamping the color management uapi. Let's get rid of that problem by making half sized copies of the software LUTs and plugging those into the internal {pre,post}_csc_lut attachment points (instead of the sticking the uapi provide sw LUTs there directly). With this the low level stuff will operate purely in terms the hardware LUT sizes, and all uapi nonsense is contained to the atomic check phase. The one thing we do lose is intel_color_assert_luts() since we no longer have a way to check that the uapi LUTs were correctly used when generating the internal copies. But that seems like a price worth paying. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221026113906.10551-12-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_color.c | 81 +++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 458e69578da6..93509cf7bbcc 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -597,6 +597,30 @@ create_linear_lut(struct drm_i915_private *i915, int lut_size) return blob; } +static struct drm_property_blob * +create_resized_lut(struct drm_i915_private *i915, + const struct drm_property_blob *blob_in, int lut_out_size) +{ + int i, lut_in_size = drm_color_lut_size(blob_in); + struct drm_property_blob *blob_out; + const struct drm_color_lut *lut_in; + struct drm_color_lut *lut_out; + + blob_out = drm_property_create_blob(&i915->drm, + sizeof(lut_out[0]) * lut_out_size, + NULL); + if (IS_ERR(blob_out)) + return blob_out; + + lut_in = blob_in->data; + lut_out = blob_out->data; + + for (i = 0; i < lut_out_size; i++) + lut_out[i] = lut_in[i * (lut_in_size - 1) / (lut_out_size - 1)]; + + return blob_out; +} + static void i9xx_load_lut_8(struct intel_crtc *crtc, const struct drm_property_blob *blob) { @@ -723,19 +747,14 @@ static void ivb_load_lut_10(struct intel_crtc *crtc, u32 prec_index) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - int hw_lut_size = ivb_lut_10_size(prec_index); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; - for (i = 0; i < hw_lut_size; i++) { - /* We discard half the user entries in split gamma mode */ - const struct drm_color_lut *entry = - &lut[i * (lut_size - 1) / (hw_lut_size - 1)]; - + for (i = 0; i < lut_size; i++) { intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), prec_index++); intel_de_write_fw(i915, PREC_PAL_DATA(pipe), - ilk_lut_10(entry)); + ilk_lut_10(&lut[i])); } /* @@ -751,7 +770,6 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, u32 prec_index) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - int hw_lut_size = ivb_lut_10_size(prec_index); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; @@ -759,14 +777,9 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), prec_index | PAL_PREC_AUTO_INCREMENT); - for (i = 0; i < hw_lut_size; i++) { - /* We discard half the user entries in split gamma mode */ - const struct drm_color_lut *entry = - &lut[i * (lut_size - 1) / (hw_lut_size - 1)]; - + for (i = 0; i < lut_size; i++) intel_de_write_fw(i915, PREC_PAL_DATA(pipe), - ilk_lut_10(entry)); - } + ilk_lut_10(&lut[i])); /* * Reset the index, otherwise it prevents the legacy palette to be @@ -1343,7 +1356,7 @@ void intel_color_assert_luts(const struct intel_crtc_state *crtc_state) crtc_state->pre_csc_lut != i915->display.color.glk_linear_degamma_lut); drm_WARN_ON(&i915->drm, crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); - } else { + } else if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) { drm_WARN_ON(&i915->drm, crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut && crtc_state->pre_csc_lut != crtc_state->hw.gamma_lut); @@ -1564,6 +1577,38 @@ static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state) return CSC_POSITION_BEFORE_GAMMA; } +static int ivb_assign_luts(struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct drm_property_blob *degamma_lut, *gamma_lut; + + if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) { + ilk_assign_luts(crtc_state); + return 0; + } + + drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.degamma_lut) != 1024); + drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.gamma_lut) != 1024); + + degamma_lut = create_resized_lut(i915, crtc_state->hw.degamma_lut, 512); + if (IS_ERR(degamma_lut)) + return PTR_ERR(degamma_lut); + + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, 512); + if (IS_ERR(gamma_lut)) { + drm_property_blob_put(degamma_lut); + return PTR_ERR(gamma_lut); + } + + drm_property_replace_blob(&crtc_state->pre_csc_lut, degamma_lut); + drm_property_replace_blob(&crtc_state->post_csc_lut, gamma_lut); + + drm_property_blob_put(degamma_lut); + drm_property_blob_put(gamma_lut); + + return 0; +} + static int ivb_color_check(struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -1599,7 +1644,9 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; - ilk_assign_luts(crtc_state); + ret = ivb_assign_luts(crtc_state); + if (ret) + return ret; crtc_state->preload_luts = intel_can_preload_luts(crtc_state); -- cgit v1.2.3 From f2d45fdf9a0ed2c94c01c422a0d0add8ffd42099 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 8 Nov 2022 19:46:45 +0800 Subject: stmmac: dwmac-loongson: fix missing pci_disable_msi() while module exiting pci_enable_msi() has been called in loongson_dwmac_probe(), so pci_disable_msi() needs be called in remove path and error path of probe(). Fixes: 30bba69d7db4 ("stmmac: pci: Add dwmac support for Loongson") Signed-off-by: Yang Yingliang Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 79fa7870563b..16915b4d9505 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -125,6 +125,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id if (res.irq < 0) { dev_err(&pdev->dev, "IRQ macirq not found\n"); ret = -ENODEV; + goto err_disable_msi; } res.wol_irq = of_irq_get_byname(np, "eth_wake_irq"); @@ -137,9 +138,18 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id if (res.lpi_irq < 0) { dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); ret = -ENODEV; + goto err_disable_msi; } - return stmmac_dvr_probe(&pdev->dev, plat, &res); + ret = stmmac_dvr_probe(&pdev->dev, plat, &res); + if (ret) + goto err_disable_msi; + + return ret; + +err_disable_msi: + pci_disable_msi(pdev); + return ret; } static void loongson_dwmac_remove(struct pci_dev *pdev) @@ -155,6 +165,7 @@ static void loongson_dwmac_remove(struct pci_dev *pdev) break; } + pci_disable_msi(pdev); pci_disable_device(pdev); } -- cgit v1.2.3 From fe5b3ce8b4377e543960220f539b989a927afd8a Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 8 Nov 2022 19:46:46 +0800 Subject: stmmac: dwmac-loongson: fix missing pci_disable_device() in loongson_dwmac_probe() Add missing pci_disable_device() in the error path in loongson_dwmac_probe(). Fixes: 30bba69d7db4 ("stmmac: pci: Add dwmac support for Loongson") Signed-off-by: Yang Yingliang Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 16915b4d9505..2d480bc49c51 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -97,7 +97,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id continue; ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); if (ret) - return ret; + goto err_disable_device; break; } @@ -108,7 +108,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id phy_mode = device_get_phy_mode(&pdev->dev); if (phy_mode < 0) { dev_err(&pdev->dev, "phy_mode not found\n"); - return phy_mode; + ret = phy_mode; + goto err_disable_device; } plat->phy_interface = phy_mode; @@ -149,6 +150,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id err_disable_msi: pci_disable_msi(pdev); +err_disable_device: + pci_disable_device(pdev); return ret; } -- cgit v1.2.3 From 7f94d0498f9c763f37172c08059ae91804c3075a Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 8 Nov 2022 19:46:47 +0800 Subject: stmmac: dwmac-loongson: fix missing of_node_put() while module exiting The node returned by of_get_child_by_name() with refcount decremented, of_node_put() needs be called when finish using it. So add it in the error path in loongson_dwmac_probe() and in loongson_dwmac_remove(). Fixes: 2ae34111fe4e ("stmmac: dwmac-loongson: fix invalid mdio_node") Signed-off-by: Yang Yingliang Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 2d480bc49c51..a25c187d3185 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -75,20 +75,24 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id plat->mdio_bus_data = devm_kzalloc(&pdev->dev, sizeof(*plat->mdio_bus_data), GFP_KERNEL); - if (!plat->mdio_bus_data) - return -ENOMEM; + if (!plat->mdio_bus_data) { + ret = -ENOMEM; + goto err_put_node; + } plat->mdio_bus_data->needs_reset = true; } plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL); - if (!plat->dma_cfg) - return -ENOMEM; + if (!plat->dma_cfg) { + ret = -ENOMEM; + goto err_put_node; + } /* Enable pci device */ ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n", __func__); - return ret; + goto err_put_node; } /* Get the base address of device */ @@ -152,13 +156,18 @@ err_disable_msi: pci_disable_msi(pdev); err_disable_device: pci_disable_device(pdev); +err_put_node: + of_node_put(plat->mdio_node); return ret; } static void loongson_dwmac_remove(struct pci_dev *pdev) { + struct net_device *ndev = dev_get_drvdata(&pdev->dev); + struct stmmac_priv *priv = netdev_priv(ndev); int i; + of_node_put(priv->plat->mdio_node); stmmac_dvr_remove(&pdev->dev); for (i = 0; i < PCI_STD_NUM_BARS; i++) { -- cgit v1.2.3 From 1b16b3fdf675cca15a537572bac50cc5354368fc Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Tue, 8 Nov 2022 16:34:58 +0100 Subject: net: phy: mscc: macsec: clear encryption keys when freeing a flow Commit aaab73f8fba4 ("macsec: clear encryption keys from the stack after setting up offload") made sure to clean encryption keys from the stack after setting up offloading, but the MSCC PHY driver made a copy, kept it in the flow data and did not clear it when freeing a flow. Fix this. Fixes: 28c5107aa904 ("net: phy: mscc: macsec support") Signed-off-by: Antoine Tenart Signed-off-by: Paolo Abeni --- drivers/net/phy/mscc/mscc_macsec.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/phy/mscc/mscc_macsec.c b/drivers/net/phy/mscc/mscc_macsec.c index ee5b17edca39..f81b077618f4 100644 --- a/drivers/net/phy/mscc/mscc_macsec.c +++ b/drivers/net/phy/mscc/mscc_macsec.c @@ -632,6 +632,7 @@ static void vsc8584_macsec_free_flow(struct vsc8531_private *priv, list_del(&flow->list); clear_bit(flow->index, bitmap); + memzero_explicit(flow->key, sizeof(flow->key)); kfree(flow); } -- cgit v1.2.3 From 879785def0f5e71d54399de0f8a5cb399db14171 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Tue, 8 Nov 2022 16:34:59 +0100 Subject: net: atlantic: macsec: clear encryption keys from the stack Commit aaab73f8fba4 ("macsec: clear encryption keys from the stack after setting up offload") made sure to clean encryption keys from the stack after setting up offloading, but the atlantic driver made a copy and did not clear it. Fix this. [4 Fixes tags below, all part of the same series, no need to split this] Fixes: 9ff40a751a6f ("net: atlantic: MACSec ingress offload implementation") Fixes: b8f8a0b7b5cb ("net: atlantic: MACSec ingress offload HW bindings") Fixes: 27736563ce32 ("net: atlantic: MACSec egress offload implementation") Fixes: 9d106c6dd81b ("net: atlantic: MACSec egress offload HW bindings") Signed-off-by: Antoine Tenart Signed-off-by: Paolo Abeni --- drivers/net/ethernet/aquantia/atlantic/aq_macsec.c | 2 ++ .../net/ethernet/aquantia/atlantic/macsec/macsec_api.c | 18 +++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c index a0180811305d..7eb5851eb95d 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c @@ -570,6 +570,7 @@ static int aq_update_txsa(struct aq_nic_s *nic, const unsigned int sc_idx, ret = aq_mss_set_egress_sakey_record(hw, &key_rec, sa_idx); + memzero_explicit(&key_rec, sizeof(key_rec)); return ret; } @@ -899,6 +900,7 @@ static int aq_update_rxsa(struct aq_nic_s *nic, const unsigned int sc_idx, ret = aq_mss_set_ingress_sakey_record(hw, &sa_key_record, sa_idx); + memzero_explicit(&sa_key_record, sizeof(sa_key_record)); return ret; } diff --git a/drivers/net/ethernet/aquantia/atlantic/macsec/macsec_api.c b/drivers/net/ethernet/aquantia/atlantic/macsec/macsec_api.c index 36c7cf05630a..431924959520 100644 --- a/drivers/net/ethernet/aquantia/atlantic/macsec/macsec_api.c +++ b/drivers/net/ethernet/aquantia/atlantic/macsec/macsec_api.c @@ -757,6 +757,7 @@ set_ingress_sakey_record(struct aq_hw_s *hw, u16 table_index) { u16 packed_record[18]; + int ret; if (table_index >= NUMROWS_INGRESSSAKEYRECORD) return -EINVAL; @@ -789,9 +790,12 @@ set_ingress_sakey_record(struct aq_hw_s *hw, packed_record[16] = rec->key_len & 0x3; - return set_raw_ingress_record(hw, packed_record, 18, 2, - ROWOFFSET_INGRESSSAKEYRECORD + - table_index); + ret = set_raw_ingress_record(hw, packed_record, 18, 2, + ROWOFFSET_INGRESSSAKEYRECORD + + table_index); + + memzero_explicit(packed_record, sizeof(packed_record)); + return ret; } int aq_mss_set_ingress_sakey_record(struct aq_hw_s *hw, @@ -1739,14 +1743,14 @@ static int set_egress_sakey_record(struct aq_hw_s *hw, ret = set_raw_egress_record(hw, packed_record, 8, 2, ROWOFFSET_EGRESSSAKEYRECORD + table_index); if (unlikely(ret)) - return ret; + goto clear_key; ret = set_raw_egress_record(hw, packed_record + 8, 8, 2, ROWOFFSET_EGRESSSAKEYRECORD + table_index - 32); - if (unlikely(ret)) - return ret; - return 0; +clear_key: + memzero_explicit(packed_record, sizeof(packed_record)); + return ret; } int aq_mss_set_egress_sakey_record(struct aq_hw_s *hw, -- cgit v1.2.3 From 91d5c5060ee24fe8da88cd585bb43b843d2f0dce Mon Sep 17 00:00:00 2001 From: Zeng Heng Date: Thu, 10 Nov 2022 16:20:56 +0800 Subject: pinctrl: devicetree: fix null pointer dereferencing in pinctrl_dt_to_map Here is the BUG report by KASAN about null pointer dereference: BUG: KASAN: null-ptr-deref in strcmp+0x2e/0x50 Read of size 1 at addr 0000000000000000 by task python3/2640 Call Trace: strcmp __of_find_property of_find_property pinctrl_dt_to_map kasprintf() would return NULL pointer when kmalloc() fail to allocate. So directly return ENOMEM, if kasprintf() return NULL pointer. Fixes: 57291ce295c0 ("pinctrl: core device tree mapping table parsing support") Signed-off-by: Zeng Heng Link: https://lore.kernel.org/r/20221110082056.2014898-1-zengheng4@huawei.com Signed-off-by: Linus Walleij --- drivers/pinctrl/devicetree.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index ef898ee8ca6b..6e0a40962f38 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -220,6 +220,8 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev) for (state = 0; ; state++) { /* Retrieve the pinctrl-* property */ propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state); + if (!propname) + return -ENOMEM; prop = of_find_property(np, propname, &size); kfree(propname); if (!prop) { -- cgit v1.2.3 From dba9e3467425800f9d3a14e8b6a0f85c731c1650 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Thu, 10 Nov 2022 17:44:45 +0800 Subject: drm/vc4: kms: Fix IS_ERR() vs NULL check for vc4_kms The drm_atomic_get_new_private_obj_state() function returns NULL on error path, drm_atomic_get_old_private_obj_state() function returns NULL on error path, too, they does not return error pointers. By the way, vc4_hvs_get_new/old_global_state() should return ERR_PTR(-EINVAL), otherwise there will be null-ptr-defer issue, such as follows: In function vc4_atomic_commit_tail(): |-- old_hvs_state = vc4_hvs_get_old_global_state(state); <-- return NULL |-- if (WARN_ON(IS_ERR(old_hvs_state))) <-- no return |-- unsigned long state_rate = max(old_hvs_state->core_clock_rate, new_hvs_state->core_clock_rate); <-- null-ptr-defer Fixes: 9ec03d7f1ed3 ("drm/vc4: kms: Wait on previous FIFO users before a commit") Signed-off-by: Gaosheng Cui Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20221110094445.2930509-6-cuigaosheng1@huawei.com --- drivers/gpu/drm/vc4/vc4_kms.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 4419e810103d..0a6347c05df4 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -197,8 +197,8 @@ vc4_hvs_get_new_global_state(struct drm_atomic_state *state) struct drm_private_state *priv_state; priv_state = drm_atomic_get_new_private_obj_state(state, &vc4->hvs_channels); - if (IS_ERR(priv_state)) - return ERR_CAST(priv_state); + if (!priv_state) + return ERR_PTR(-EINVAL); return to_vc4_hvs_state(priv_state); } @@ -210,8 +210,8 @@ vc4_hvs_get_old_global_state(struct drm_atomic_state *state) struct drm_private_state *priv_state; priv_state = drm_atomic_get_old_private_obj_state(state, &vc4->hvs_channels); - if (IS_ERR(priv_state)) - return ERR_CAST(priv_state); + if (!priv_state) + return ERR_PTR(-EINVAL); return to_vc4_hvs_state(priv_state); } -- cgit v1.2.3 From 0348c1ab980c1d43fb37b758d4b760990c066cb5 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 9 Nov 2022 10:37:41 +0800 Subject: ethernet: s2io: disable napi when start nic failed in s2io_card_up() When failed to start nic or add interrupt service routine in s2io_card_up() for opening device, napi isn't disabled. When open s2io device next time, it will trigger a BUG_ON()in napi_enable(). Compile tested only. Fixes: 5f490c968056 ("S2io: Fixed synchronization between scheduling of napi with card reset and close") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221109023741.131552-1-shaozhengchao@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/neterion/s2io.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index dcf8212119f9..1d3c4474b7cb 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -7128,9 +7128,8 @@ static int s2io_card_up(struct s2io_nic *sp) if (ret) { DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n", dev->name); - s2io_reset(sp); - free_rx_buffers(sp); - return -ENOMEM; + ret = -ENOMEM; + goto err_fill_buff; } DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i, ring->rx_bufs_left); @@ -7168,18 +7167,16 @@ static int s2io_card_up(struct s2io_nic *sp) /* Enable Rx Traffic and interrupts on the NIC */ if (start_nic(sp)) { DBG_PRINT(ERR_DBG, "%s: Starting NIC failed\n", dev->name); - s2io_reset(sp); - free_rx_buffers(sp); - return -ENODEV; + ret = -ENODEV; + goto err_out; } /* Add interrupt service routine */ if (s2io_add_isr(sp) != 0) { if (sp->config.intr_type == MSI_X) s2io_rem_isr(sp); - s2io_reset(sp); - free_rx_buffers(sp); - return -ENODEV; + ret = -ENODEV; + goto err_out; } timer_setup(&sp->alarm_timer, s2io_alarm_handle, 0); @@ -7199,6 +7196,20 @@ static int s2io_card_up(struct s2io_nic *sp) } return 0; + +err_out: + if (config->napi) { + if (config->intr_type == MSI_X) { + for (i = 0; i < sp->config.rx_ring_num; i++) + napi_disable(&sp->mac_control.rings[i].napi); + } else { + napi_disable(&sp->napi); + } + } +err_fill_buff: + s2io_reset(sp); + free_rx_buffers(sp); + return ret; } /** -- cgit v1.2.3 From f111606b63ff2282428ffbac0447c871eb957b6c Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 9 Nov 2022 10:54:32 +0800 Subject: net: mv643xx_eth: disable napi when init rxq or txq failed in mv643xx_eth_open() When failed to init rxq or txq in mv643xx_eth_open() for opening device, napi isn't disabled. When open mv643xx_eth device next time, it will trigger a BUG_ON() in napi_enable(). Compile tested only. Fixes: 2257e05c1705 ("mv643xx_eth: get rid of receive-side locking") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221109025432.80900-1-shaozhengchao@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/marvell/mv643xx_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 707993b445d1..8941f69d93e9 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2481,6 +2481,7 @@ out_free: for (i = 0; i < mp->rxq_count; i++) rxq_deinit(mp->rxq + i); out: + napi_disable(&mp->napi); free_irq(dev->irq, dev); return err; -- cgit v1.2.3 From a10234fda4664f9ffe9608abe1e99b51815113f5 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 9 Nov 2022 10:46:33 +0000 Subject: drm/i915: Partial abandonment of legacy DRM logging macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert some usages of legacy DRM logging macros into versions which tell us on which device have the events occurred. v2: * Don't have struct drm_device as local. (Jani, Ville) v3: * Store gt, not i915, in workaround list. (John) Signed-off-by: Tvrtko Ursulin Acked-by: Jani Nikula Cc: Jani Nikula Cc: John Harrison Cc: Ville Syrjälä Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/20221109104633.2579245-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 26 +++++++++----- .../gpu/drm/i915/gt/intel_execlists_submission.c | 13 ++++--- drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 4 +-- drivers/gpu/drm/i915/gt/intel_gt.c | 4 +-- drivers/gpu/drm/i915/gt/intel_gt_irq.c | 8 +++-- drivers/gpu/drm/i915/gt/intel_rps.c | 6 ++-- drivers/gpu/drm/i915/gt/intel_workarounds.c | 42 ++++++++++++---------- drivers/gpu/drm/i915/gt/intel_workarounds_types.h | 3 ++ drivers/gpu/drm/i915/gt/selftest_workarounds.c | 4 +-- drivers/gpu/drm/i915/i915_debugfs.c | 4 +-- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_getparam.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 12 ++++--- drivers/gpu/drm/i915/i915_perf.c | 14 ++++---- drivers/gpu/drm/i915/i915_query.c | 12 ++++--- drivers/gpu/drm/i915/i915_sysfs.c | 3 +- drivers/gpu/drm/i915/i915_vma.c | 16 +++++---- drivers/gpu/drm/i915/intel_uncore.c | 21 ++++++----- 19 files changed, 117 insertions(+), 81 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 01402f3c58f6..7f2831efc798 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -546,7 +546,7 @@ set_proto_ctx_engines_bond(struct i915_user_extension __user *base, void *data) } if (intel_engine_uses_guc(master)) { - DRM_DEBUG("bonding extension not supported with GuC submission"); + drm_dbg(&i915->drm, "bonding extension not supported with GuC submission"); return -ENODEV; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 1160723c9d2d..f65fd03f7cf2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2148,7 +2148,8 @@ err_skip: return err; } -static int i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) +static int i915_gem_check_execbuffer(struct drm_i915_private *i915, + struct drm_i915_gem_execbuffer2 *exec) { if (exec->flags & __I915_EXEC_ILLEGAL_FLAGS) return -EINVAL; @@ -2161,7 +2162,7 @@ static int i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) } if (exec->DR4 == 0xffffffff) { - DRM_DEBUG("UXA submitting garbage DR4, fixing up\n"); + drm_dbg(&i915->drm, "UXA submitting garbage DR4, fixing up\n"); exec->DR4 = 0; } if (exec->DR1 || exec->DR4) @@ -2799,7 +2800,8 @@ add_timeline_fence_array(struct i915_execbuffer *eb, syncobj = drm_syncobj_find(eb->file, user_fence.handle); if (!syncobj) { - DRM_DEBUG("Invalid syncobj handle provided\n"); + drm_dbg(&eb->i915->drm, + "Invalid syncobj handle provided\n"); return -ENOENT; } @@ -2807,7 +2809,8 @@ add_timeline_fence_array(struct i915_execbuffer *eb, if (!fence && user_fence.flags && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { - DRM_DEBUG("Syncobj handle has no fence\n"); + drm_dbg(&eb->i915->drm, + "Syncobj handle has no fence\n"); drm_syncobj_put(syncobj); return -EINVAL; } @@ -2816,7 +2819,9 @@ add_timeline_fence_array(struct i915_execbuffer *eb, err = dma_fence_chain_find_seqno(&fence, point); if (err && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { - DRM_DEBUG("Syncobj handle missing requested point %llu\n", point); + drm_dbg(&eb->i915->drm, + "Syncobj handle missing requested point %llu\n", + point); dma_fence_put(fence); drm_syncobj_put(syncobj); return err; @@ -2842,7 +2847,8 @@ add_timeline_fence_array(struct i915_execbuffer *eb, * 0) would break the timeline. */ if (user_fence.flags & I915_EXEC_FENCE_WAIT) { - DRM_DEBUG("Trying to wait & signal the same timeline point.\n"); + drm_dbg(&eb->i915->drm, + "Trying to wait & signal the same timeline point.\n"); dma_fence_put(fence); drm_syncobj_put(syncobj); return -EINVAL; @@ -2913,14 +2919,16 @@ static int add_fence_array(struct i915_execbuffer *eb) syncobj = drm_syncobj_find(eb->file, user_fence.handle); if (!syncobj) { - DRM_DEBUG("Invalid syncobj handle provided\n"); + drm_dbg(&eb->i915->drm, + "Invalid syncobj handle provided\n"); return -ENOENT; } if (user_fence.flags & I915_EXEC_FENCE_WAIT) { fence = drm_syncobj_fence_get(syncobj); if (!fence) { - DRM_DEBUG("Syncobj handle has no fence\n"); + drm_dbg(&eb->i915->drm, + "Syncobj handle has no fence\n"); drm_syncobj_put(syncobj); return -EINVAL; } @@ -3515,7 +3523,7 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, return -EINVAL; } - err = i915_gem_check_execbuffer(args); + err = i915_gem_check_execbuffer(i915, args); if (err) return err; diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 0187bc72310d..d92512780467 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -3921,6 +3921,7 @@ static struct intel_context * execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count, unsigned long flags) { + struct drm_i915_private *i915 = siblings[0]->i915; struct virtual_engine *ve; unsigned int n; int err; @@ -3929,7 +3930,7 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count, if (!ve) return ERR_PTR(-ENOMEM); - ve->base.i915 = siblings[0]->i915; + ve->base.i915 = i915; ve->base.gt = siblings[0]->gt; ve->base.uncore = siblings[0]->uncore; ve->base.id = -1; @@ -3988,8 +3989,9 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count, GEM_BUG_ON(!is_power_of_2(sibling->mask)); if (sibling->mask & ve->base.mask) { - DRM_DEBUG("duplicate %s entry in load balancer\n", - sibling->name); + drm_dbg(&i915->drm, + "duplicate %s entry in load balancer\n", + sibling->name); err = -EINVAL; goto err_put; } @@ -4023,8 +4025,9 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count, */ if (ve->base.class != OTHER_CLASS) { if (ve->base.class != sibling->class) { - DRM_DEBUG("invalid mixing of engine class, sibling %d, already %d\n", - sibling->class, ve->base.class); + drm_dbg(&i915->drm, + "invalid mixing of engine class, sibling %d, already %d\n", + sibling->class, ve->base.class); err = -EINVAL; goto err_put; } diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index ea775e601686..995082d45cb2 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -816,8 +816,8 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj, if (obj->bit_17 == NULL) { obj->bit_17 = bitmap_zalloc(page_count, GFP_KERNEL); if (obj->bit_17 == NULL) { - DRM_ERROR("Failed to allocate memory for bit 17 " - "record\n"); + drm_err(&to_i915(obj->base.dev)->drm, + "Failed to allocate memory for bit 17 record\n"); return; } } diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 8e914c4066ed..0ba7d6f36b28 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -190,7 +190,7 @@ int intel_gt_init_hw(struct intel_gt *gt) ret = i915_ppgtt_init_hw(gt); if (ret) { - DRM_ERROR("Enabling PPGTT failed (%d)\n", ret); + drm_err(&i915->drm, "Enabling PPGTT failed (%d)\n", ret); goto out; } @@ -262,7 +262,7 @@ intel_gt_clear_error_registers(struct intel_gt *gt, * some errors might have become stuck, * mask them. */ - DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir); + drm_dbg(>->i915->drm, "EIR stuck: 0x%08x, masking\n", eir); rmw_set(uncore, EMR, eir); intel_uncore_write(uncore, GEN2_IIR, I915_MASTER_ERROR_INTERRUPT); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index b197f0e9794f..4c8ddd074b78 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -44,8 +44,9 @@ gen11_gt_engine_identity(struct intel_gt *gt, !time_after32(local_clock() >> 10, timeout_ts)); if (unlikely(!(ident & GEN11_INTR_DATA_VALID))) { - DRM_ERROR("INTR_IDENTITY_REG%u:%u 0x%08x not valid!\n", - bank, bit, ident); + drm_err(>->i915->drm, + "INTR_IDENTITY_REG%u:%u 0x%08x not valid!\n", + bank, bit, ident); return 0; } @@ -364,7 +365,8 @@ void gen6_gt_irq_handler(struct intel_gt *gt, u32 gt_iir) if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | GT_BSD_CS_ERROR_INTERRUPT | GT_CS_MASTER_ERROR_INTERRUPT)) - DRM_DEBUG("Command parser error, gt_iir 0x%08x\n", gt_iir); + drm_dbg(>->i915->drm, "Command parser error, gt_iir 0x%08x\n", + gt_iir); if (gt_iir & GT_PARITY_ERROR(gt->i915)) gen7_parity_error_irq_handler(gt, gt_iir); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 6c34a83c24b3..effe60ac22cd 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -430,7 +430,8 @@ static int __gen5_rps_set(struct intel_rps *rps, u8 val) rgvswctl = intel_uncore_read16(uncore, MEMSWCTL); if (rgvswctl & MEMCTL_CMD_STS) { - DRM_DEBUG("gpu busy, RCS change rejected\n"); + drm_dbg(&rps_to_i915(rps)->drm, + "gpu busy, RCS change rejected\n"); return -EBUSY; /* still busy with another command */ } @@ -1953,7 +1954,8 @@ void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir) intel_engine_cs_irq(gt->engine[VECS0], pm_iir >> 10); if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) - DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); + drm_dbg(&rps_to_i915(rps)->drm, + "Command parser error, pm_iir 0x%08x\n", pm_iir); } void gen5_rps_irq_handler(struct intel_rps *rps) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 3cdf5c24dbc5..07bf115029a0 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -55,8 +55,10 @@ * - Public functions to init or apply the given workaround type. */ -static void wa_init_start(struct i915_wa_list *wal, const char *name, const char *engine_name) +static void wa_init_start(struct i915_wa_list *wal, struct intel_gt *gt, + const char *name, const char *engine_name) { + wal->gt = gt; wal->name = name; wal->engine_name = engine_name; } @@ -80,13 +82,14 @@ static void wa_init_finish(struct i915_wa_list *wal) if (!wal->count) return; - DRM_DEBUG_DRIVER("Initialized %u %s workarounds on %s\n", - wal->wa_count, wal->name, wal->engine_name); + drm_dbg(&wal->gt->i915->drm, "Initialized %u %s workarounds on %s\n", + wal->wa_count, wal->name, wal->engine_name); } static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) { unsigned int addr = i915_mmio_reg_offset(wa->reg); + struct drm_i915_private *i915 = wal->gt->i915; unsigned int start = 0, end = wal->count; const unsigned int grow = WA_LIST_CHUNK; struct i915_wa *wa_; @@ -99,7 +102,7 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa), GFP_KERNEL); if (!list) { - DRM_ERROR("No space for workaround init!\n"); + drm_err(&i915->drm, "No space for workaround init!\n"); return; } @@ -122,9 +125,10 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) wa_ = &wal->list[mid]; if ((wa->clr | wa_->clr) && !(wa->clr & ~wa_->clr)) { - DRM_ERROR("Discarding overwritten w/a for reg %04x (clear: %08x, set: %08x)\n", - i915_mmio_reg_offset(wa_->reg), - wa_->clr, wa_->set); + drm_err(&i915->drm, + "Discarding overwritten w/a for reg %04x (clear: %08x, set: %08x)\n", + i915_mmio_reg_offset(wa_->reg), + wa_->clr, wa_->set); wa_->set &= ~wa->clr; } @@ -826,7 +830,7 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine, { struct drm_i915_private *i915 = engine->i915; - wa_init_start(wal, name, engine->name); + wa_init_start(wal, engine->gt, name, engine->name); /* Applies to all engines */ /* @@ -1676,7 +1680,7 @@ void intel_gt_init_workarounds(struct intel_gt *gt) { struct i915_wa_list *wal = >->wa_list; - wa_init_start(wal, "GT", "global"); + wa_init_start(wal, gt, "GT", "global"); gt_init_workarounds(gt, wal); wa_init_finish(wal); } @@ -1698,12 +1702,14 @@ wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal) } static bool -wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char *from) +wa_verify(struct intel_gt *gt, const struct i915_wa *wa, u32 cur, + const char *name, const char *from) { if ((cur ^ wa->set) & wa->read) { - DRM_ERROR("%s workaround lost on %s! (reg[%x]=0x%x, relevant bits were 0x%x vs expected 0x%x)\n", - name, from, i915_mmio_reg_offset(wa->reg), - cur, cur & wa->read, wa->set & wa->read); + drm_err(>->i915->drm, + "%s workaround lost on %s! (reg[%x]=0x%x, relevant bits were 0x%x vs expected 0x%x)\n", + name, from, i915_mmio_reg_offset(wa->reg), + cur, cur & wa->read, wa->set & wa->read); return false; } @@ -1749,7 +1755,7 @@ wa_list_apply(struct intel_gt *gt, const struct i915_wa_list *wal) intel_gt_mcr_read_any_fw(gt, wa->mcr_reg) : intel_uncore_read_fw(uncore, wa->reg); - wa_verify(wa, val, wal->name, "application"); + wa_verify(wal->gt, wa, val, wal->name, "application"); } } @@ -1779,7 +1785,7 @@ static bool wa_list_verify(struct intel_gt *gt, intel_uncore_forcewake_get__locked(uncore, fw); for (i = 0, wa = wal->list; i < wal->count; i++, wa++) - ok &= wa_verify(wa, wa->is_mcr ? + ok &= wa_verify(wal->gt, wa, wa->is_mcr ? intel_gt_mcr_read_any_fw(gt, wa->mcr_reg) : intel_uncore_read_fw(uncore, wa->reg), wal->name, from); @@ -2127,7 +2133,7 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine) struct drm_i915_private *i915 = engine->i915; struct i915_wa_list *w = &engine->whitelist; - wa_init_start(w, "whitelist", engine->name); + wa_init_start(w, engine->gt, "whitelist", engine->name); if (IS_PONTEVECCHIO(i915)) pvc_whitelist_build(engine); @@ -3012,7 +3018,7 @@ void intel_engine_init_workarounds(struct intel_engine_cs *engine) if (GRAPHICS_VER(engine->i915) < 4) return; - wa_init_start(wal, "engine", engine->name); + wa_init_start(wal, engine->gt, "engine", engine->name); engine_init_workarounds(engine, wal); wa_init_finish(wal); } @@ -3193,7 +3199,7 @@ retry: if (mcr_range(rq->engine->i915, i915_mmio_reg_offset(wa->reg))) continue; - if (!wa_verify(wa, results[i], wal->name, from)) + if (!wa_verify(wal->gt, wa, results[i], wal->name, from)) err = -ENXIO; } diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h index 7c8b01d00043..e14188120e66 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h +++ b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h @@ -10,6 +10,8 @@ #include "i915_reg_defs.h" +struct intel_gt; + struct i915_wa { union { i915_reg_t reg; @@ -24,6 +26,7 @@ struct i915_wa { }; struct i915_wa_list { + struct intel_gt *gt; const char *name; const char *engine_name; struct i915_wa *list; diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c index 21b1edc052f8..711014bb53d9 100644 --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c @@ -66,14 +66,14 @@ reference_lists_init(struct intel_gt *gt, struct wa_lists *lists) memset(lists, 0, sizeof(*lists)); - wa_init_start(&lists->gt_wa_list, "GT_REF", "global"); + wa_init_start(&lists->gt_wa_list, gt, "GT_REF", "global"); gt_init_workarounds(gt, &lists->gt_wa_list); wa_init_finish(&lists->gt_wa_list); for_each_engine(engine, gt, id) { struct i915_wa_list *wal = &lists->engine[id].wa_list; - wa_init_start(wal, "REF", engine->name); + wa_init_start(wal, gt, "REF", engine->name); engine_init_workarounds(engine, wal); wa_init_finish(wal); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ae987e92251d..6c7ac73b69a5 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -688,8 +688,8 @@ i915_drop_caches_set(void *data, u64 val) unsigned int flags; int ret; - DRM_DEBUG("Dropping caches: 0x%08llx [0x%08llx]\n", - val, val & DROP_ALL); + drm_dbg(&i915->drm, "Dropping caches: 0x%08llx [0x%08llx]\n", + val, val & DROP_ALL); ret = gt_drop_caches(to_gt(i915), val); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 299f94a9fb87..8132743ca87e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1286,7 +1286,7 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) struct i915_drm_client *client; int ret = -ENOMEM; - DRM_DEBUG("\n"); + drm_dbg(&i915->drm, "\n"); file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); if (!file_priv) diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c index 3047e80e1163..61ef2d9cfa62 100644 --- a/drivers/gpu/drm/i915/i915_getparam.c +++ b/drivers/gpu/drm/i915/i915_getparam.c @@ -179,7 +179,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, value = i915_perf_oa_timestamp_frequency(i915); break; default: - DRM_DEBUG("Unknown parameter %d\n", param->param); + drm_dbg(&i915->drm, "Unknown parameter %d\n", param->param); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d68859866bf2..1efe5c19fac1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1086,8 +1086,9 @@ static void ivb_parity_work(struct work_struct *work) kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, KOBJ_CHANGE, parity_event); - DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", - slice, row, bank, subbank); + drm_dbg(&dev_priv->drm, + "Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", + slice, row, bank, subbank); kfree(parity_event[4]); kfree(parity_event[3]); @@ -2774,7 +2775,8 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl); } else { - DRM_ERROR("Tile not supported: 0x%08x\n", master_tile_ctl); + drm_err(&i915->drm, "Tile not supported: 0x%08x\n", + master_tile_ctl); dg1_master_intr_enable(regs); return IRQ_NONE; } @@ -3940,7 +3942,7 @@ static void i8xx_error_irq_ack(struct drm_i915_private *i915, static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, u16 eir, u16 eir_stuck) { - DRM_DEBUG("Master Error: EIR 0x%04x\n", eir); + drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir); if (eir_stuck) drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n", @@ -3975,7 +3977,7 @@ static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, u32 eir, u32 eir_stuck) { - DRM_DEBUG("Master Error, EIR 0x%08x\n", eir); + drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir); if (eir_stuck) drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n", diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 0dd597a7a11f..9e6f060592d8 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -530,9 +530,9 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream) if (OA_TAKEN(hw_tail, tail) > report_size && __ratelimit(&stream->perf->tail_pointer_race)) - DRM_NOTE("unlanded report(s) head=0x%x " - "tail=0x%x hw_tail=0x%x\n", - head, tail, hw_tail); + drm_notice(&stream->uncore->i915->drm, + "unlanded report(s) head=0x%x tail=0x%x hw_tail=0x%x\n", + head, tail, hw_tail); stream->oa_buffer.tail = gtt_offset + tail; stream->oa_buffer.aging_tail = gtt_offset + hw_tail; @@ -1015,7 +1015,8 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream, */ if (report32[0] == 0) { if (__ratelimit(&stream->perf->spurious_report_rs)) - DRM_NOTE("Skipping spurious, invalid OA report\n"); + drm_notice(&uncore->i915->drm, + "Skipping spurious, invalid OA report\n"); continue; } @@ -1602,8 +1603,9 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream) free_noa_wait(stream); if (perf->spurious_report_rs.missed) { - DRM_NOTE("%d spurious OA report notices suppressed due to ratelimiting\n", - perf->spurious_report_rs.missed); + drm_notice(>->i915->drm, + "%d spurious OA report notices suppressed due to ratelimiting\n", + perf->spurious_report_rs.missed); } } diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index 6ec9c9fb7b0d..00871ef99792 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -250,8 +250,9 @@ static int query_perf_config_data(struct drm_i915_private *i915, return total_size; if (query_item->length < total_size) { - DRM_DEBUG("Invalid query config data item size=%u expected=%u\n", - query_item->length, total_size); + drm_dbg(&i915->drm, + "Invalid query config data item size=%u expected=%u\n", + query_item->length, total_size); return -EINVAL; } @@ -418,9 +419,10 @@ static int query_perf_config_list(struct drm_i915_private *i915, } while (n_configs > alloc); if (query_item->length < sizeof_perf_config_list(n_configs)) { - DRM_DEBUG("Invalid query config list item size=%u expected=%zu\n", - query_item->length, - sizeof_perf_config_list(n_configs)); + drm_dbg(&i915->drm, + "Invalid query config list item size=%u expected=%zu\n", + query_item->length, + sizeof_perf_config_list(n_configs)); kfree(oa_config_ids); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 1e2750210831..595e8b574990 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -218,7 +218,8 @@ static const struct bin_attribute error_state_attr = { static void i915_setup_error_capture(struct device *kdev) { if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr)) - DRM_ERROR("error_state sysfs setup failed\n"); + drm_err(&kdev_minor_to_i915(kdev)->drm, + "error_state sysfs setup failed\n"); } static void i915_teardown_error_capture(struct device *kdev) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index c39488eb9eeb..3b969d679c1e 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -73,14 +73,16 @@ static void vma_print_allocator(struct i915_vma *vma, const char *reason) char buf[512]; if (!vma->node.stack) { - DRM_DEBUG_DRIVER("vma.node [%08llx + %08llx] %s: unknown owner\n", - vma->node.start, vma->node.size, reason); + drm_dbg(&to_i915(vma->obj->base.dev)->drm + "vma.node [%08llx + %08llx] %s: unknown owner\n", + vma->node.start, vma->node.size, reason); return; } stack_depot_snprint(vma->node.stack, buf, sizeof(buf), 0); - DRM_DEBUG_DRIVER("vma.node [%08llx + %08llx] %s: inserted at %s\n", - vma->node.start, vma->node.size, reason, buf); + drm_dbg(&to_i915(vma->obj->base.dev)->drm, + "vma.node [%08llx + %08llx] %s: inserted at %s\n", + vma->node.start, vma->node.size, reason, buf); } #else @@ -782,9 +784,9 @@ i915_vma_insert(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, * attempt to find space. */ if (size > end) { - DRM_DEBUG("Attempting to bind an object larger than the aperture: request=%llu > %s aperture=%llu\n", - size, flags & PIN_MAPPABLE ? "mappable" : "total", - end); + drm_dbg(&to_i915(vma->obj->base.dev)->drm, + "Attempting to bind an object larger than the aperture: request=%llu > %s aperture=%llu\n", + size, flags & PIN_MAPPABLE ? "mappable" : "total", end); return -ENOSPC; } diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 2a3e2869fe71..6c25c9e7090a 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -178,8 +178,9 @@ static inline void fw_domain_wait_ack_clear(const struct intel_uncore_forcewake_domain *d) { if (wait_ack_clear(d, FORCEWAKE_KERNEL)) { - DRM_ERROR("%s: timed out waiting for forcewake ack to clear.\n", - intel_uncore_forcewake_domain_to_str(d->id)); + drm_err(&d->uncore->i915->drm, + "%s: timed out waiting for forcewake ack to clear.\n", + intel_uncore_forcewake_domain_to_str(d->id)); add_taint_for_CI(d->uncore->i915, TAINT_WARN); /* CI now unreliable */ } } @@ -226,11 +227,12 @@ fw_domain_wait_ack_with_fallback(const struct intel_uncore_forcewake_domain *d, fw_clear(d, FORCEWAKE_KERNEL_FALLBACK); } while (!ack_detected && pass++ < 10); - DRM_DEBUG_DRIVER("%s had to use fallback to %s ack, 0x%x (passes %u)\n", - intel_uncore_forcewake_domain_to_str(d->id), - type == ACK_SET ? "set" : "clear", - fw_ack(d), - pass); + drm_dbg(&d->uncore->i915->drm, + "%s had to use fallback to %s ack, 0x%x (passes %u)\n", + intel_uncore_forcewake_domain_to_str(d->id), + type == ACK_SET ? "set" : "clear", + fw_ack(d), + pass); return ack_detected ? 0 : -ETIMEDOUT; } @@ -255,8 +257,9 @@ static inline void fw_domain_wait_ack_set(const struct intel_uncore_forcewake_domain *d) { if (wait_ack_set(d, FORCEWAKE_KERNEL)) { - DRM_ERROR("%s: timed out waiting for forcewake ack request.\n", - intel_uncore_forcewake_domain_to_str(d->id)); + drm_err(&d->uncore->i915->drm, + "%s: timed out waiting for forcewake ack request.\n", + intel_uncore_forcewake_domain_to_str(d->id)); add_taint_for_CI(d->uncore->i915, TAINT_WARN); /* CI now unreliable */ } } -- cgit v1.2.3 From acce40037041f97baad18142bb253064491ebde3 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 9 Nov 2022 12:40:16 +0800 Subject: ethernet: tundra: free irq when alloc ring failed in tsi108_open() When alloc tx/rx ring failed in tsi108_open(), it doesn't free irq. Fix it. Fixes: 5e123b844a1c ("[PATCH] Add tsi108/9 On Chip Ethernet device driver support") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221109044016.126866-1-shaozhengchao@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/tundra/tsi108_eth.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index 2cd2afc3fff0..d09d352e1c0a 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -1290,12 +1290,15 @@ static int tsi108_open(struct net_device *dev) data->rxring = dma_alloc_coherent(&data->pdev->dev, rxring_size, &data->rxdma, GFP_KERNEL); - if (!data->rxring) + if (!data->rxring) { + free_irq(data->irq_num, dev); return -ENOMEM; + } data->txring = dma_alloc_coherent(&data->pdev->dev, txring_size, &data->txdma, GFP_KERNEL); if (!data->txring) { + free_irq(data->irq_num, dev); dma_free_coherent(&data->pdev->dev, rxring_size, data->rxring, data->rxdma); return -ENOMEM; -- cgit v1.2.3 From 23569b5652ee8e8e55a12f7835f59af6f3cefc30 Mon Sep 17 00:00:00 2001 From: Chuang Wang Date: Wed, 9 Nov 2022 17:07:34 +0800 Subject: net: macvlan: fix memory leaks of macvlan_common_newlink kmemleak reports memory leaks in macvlan_common_newlink, as follows: ip link add link eth0 name .. type macvlan mode source macaddr add kmemleak reports: unreferenced object 0xffff8880109bb140 (size 64): comm "ip", pid 284, jiffies 4294986150 (age 430.108s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 b8 aa 5a 12 80 88 ff ff ..........Z..... 80 1b fa 0d 80 88 ff ff 1e ff ac af c7 c1 6b 6b ..............kk backtrace: [] kmem_cache_alloc_trace+0x1c7/0x300 [] macvlan_hash_add_source+0x45/0xc0 [] macvlan_changelink_sources+0xd7/0x170 [] macvlan_common_newlink+0x38c/0x5a0 [] macvlan_newlink+0xe/0x20 [] __rtnl_newlink+0x7af/0xa50 [] rtnl_newlink+0x48/0x70 ... In the scenario where the macvlan mode is configured as 'source', macvlan_changelink_sources() will be execured to reconfigure list of remote source mac addresses, at the same time, if register_netdevice() return an error, the resource generated by macvlan_changelink_sources() is not cleaned up. Using this patch, in the case of an error, it will execute macvlan_flush_sources() to ensure that the resource is cleaned up. Fixes: aa5fd0fb7748 ("driver: macvlan: Destroy new macvlan port if macvlan_common_newlink failed.") Signed-off-by: Chuang Wang Link: https://lore.kernel.org/r/20221109090735.690500-1-nashuiliang@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/macvlan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index c5cfe8555199..578897aaada0 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1533,8 +1533,10 @@ destroy_macvlan_port: /* the macvlan port may be freed by macvlan_uninit when fail to register. * so we destroy the macvlan port only when it's valid. */ - if (create && macvlan_port_get_rtnl(lowerdev)) + if (create && macvlan_port_get_rtnl(lowerdev)) { + macvlan_flush_sources(port, vlan); macvlan_port_destroy(port->dev); + } return err; } EXPORT_SYMBOL_GPL(macvlan_common_newlink); -- cgit v1.2.3 From 876153ab068b2507a19aa3ef481f5b00a2cc780f Mon Sep 17 00:00:00 2001 From: Aishwarya Kothari Date: Wed, 31 Aug 2022 16:16:22 +0200 Subject: drm/panel: simple: set bpc field for logic technologies displays In case bpc is not set for a panel it then throws a WARN(). Add bpc to the panels logictechno_lt170410_2whc and logictechno_lt161010_2nh. Fixes: 5728fe7fa539 ("drm/panel: simple: add display timings for logic technologies displays") Signed-off-by: Aishwarya Kothari Signed-off-by: Francesco Dolcini Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20220831141622.39605-1-francesco.dolcini@toradex.com --- drivers/gpu/drm/panel/panel-simple.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 2944228a8e2c..8a3b685c2fcc 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -2500,6 +2500,7 @@ static const struct display_timing logictechno_lt161010_2nh_timing = { static const struct panel_desc logictechno_lt161010_2nh = { .timings = &logictechno_lt161010_2nh_timing, .num_timings = 1, + .bpc = 6, .size = { .width = 154, .height = 86, @@ -2529,6 +2530,7 @@ static const struct display_timing logictechno_lt170410_2whc_timing = { static const struct panel_desc logictechno_lt170410_2whc = { .timings = &logictechno_lt170410_2whc_timing, .num_timings = 1, + .bpc = 8, .size = { .width = 217, .height = 136, -- cgit v1.2.3 From 1aeb122d214b92474c86fde00a03d6e2d69381b5 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Wed, 28 Sep 2022 21:51:12 +0200 Subject: nvmem: lan9662-otp: Fix compatible string The device tree bindings for lan9662-otp expects the compatible string to be one of following compatible strings: microchip,lan9662-otpc microchip,lan9668-otpc The problem is that the lan9662-otp driver contains the microchip,lan9662-otp compatible string instead of microchip,lan9662-otpc. Fix this by updating the compatible string in the driver. Fixes: 9e8f208ad5229d ("nvmem: lan9662-otp: add support") Signed-off-by: Horatiu Vultur Link: https://lore.kernel.org/r/20220928195112.630351-1-horatiu.vultur@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/lan9662-otpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/nvmem/lan9662-otpc.c b/drivers/nvmem/lan9662-otpc.c index f6732fd216d8..377bf34c2946 100644 --- a/drivers/nvmem/lan9662-otpc.c +++ b/drivers/nvmem/lan9662-otpc.c @@ -203,7 +203,7 @@ static int lan9662_otp_probe(struct platform_device *pdev) } static const struct of_device_id lan9662_otp_match[] = { - { .compatible = "microchip,lan9662-otp", }, + { .compatible = "microchip,lan9662-otpc", }, { }, }; MODULE_DEVICE_TABLE(of, lan9662_otp_match); -- cgit v1.2.3 From b9c1939627f8185dec8ba6d741e9573a4c7a5834 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 29 Sep 2022 18:52:02 +0200 Subject: slimbus: stream: correct presence rate frequencies Correct few frequencies in presence rate table - multiplied by 10 (110250 instead of 11025 Hz). Fixes: abb9c9b8b51b ("slimbus: stream: add stream support") Cc: Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220929165202.410937-1-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/slimbus/stream.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/slimbus/stream.c b/drivers/slimbus/stream.c index 75f87b3d8b95..73a2aa362957 100644 --- a/drivers/slimbus/stream.c +++ b/drivers/slimbus/stream.c @@ -67,10 +67,10 @@ static const int slim_presence_rate_table[] = { 384000, 768000, 0, /* Reserved */ - 110250, - 220500, - 441000, - 882000, + 11025, + 22050, + 44100, + 88200, 176400, 352800, 705600, -- cgit v1.2.3 From e54fad8044db18cc400df8d01bfb86cada08b7cb Mon Sep 17 00:00:00 2001 From: Zheng Bin Date: Thu, 27 Oct 2022 17:59:04 +0800 Subject: slimbus: qcom-ngd: Fix build error when CONFIG_SLIM_QCOM_NGD_CTRL=y && CONFIG_QCOM_RPROC_COMMON=m If CONFIG_SLIM_QCOM_NGD_CTRL=y, CONFIG_QCOM_RPROC_COMMON=m, COMPILE_TEST=y, bulding fails: drivers/slimbus/qcom-ngd-ctrl.o: In function `qcom_slim_ngd_ctrl_probe': qcom-ngd-ctrl.c:(.text+0x330): undefined reference to `qcom_register_ssr_notifier' qcom-ngd-ctrl.c:(.text+0x5fc): undefined reference to `qcom_unregister_ssr_notifier' drivers/slimbus/qcom-ngd-ctrl.o: In function `qcom_slim_ngd_remove': qcom-ngd-ctrl.c:(.text+0x90c): undefined reference to `qcom_unregister_ssr_notifier' Make SLIM_QCOM_NGD_CTRL depends on QCOM_RPROC_COMMON || (COMPILE_TEST && !QCOM_RPROC_COMMON) to fix this. Fixes: e291691c6977 ("slimbus: qcom-ngd-ctrl: allow compile testing without QCOM_RPROC_COMMON") Cc: stable Signed-off-by: Zheng Bin Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20221027095904.3388959-1-zhengbin13@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/slimbus/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/slimbus/Kconfig b/drivers/slimbus/Kconfig index 2ed821f75816..a0fdf9d792cb 100644 --- a/drivers/slimbus/Kconfig +++ b/drivers/slimbus/Kconfig @@ -23,7 +23,7 @@ config SLIM_QCOM_CTRL config SLIM_QCOM_NGD_CTRL tristate "Qualcomm SLIMbus Satellite Non-Generic Device Component" depends on HAS_IOMEM && DMA_ENGINE && NET - depends on QCOM_RPROC_COMMON || COMPILE_TEST + depends on QCOM_RPROC_COMMON || (COMPILE_TEST && !QCOM_RPROC_COMMON) depends on ARCH_QCOM || COMPILE_TEST select QCOM_QMI_HELPERS select QCOM_PDR_HELPERS -- cgit v1.2.3 From ee424f7d3960152f5f862bbb6943e59828dc7917 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 4 Nov 2022 17:52:03 +0100 Subject: nvmem: u-boot-env: fix crc32_data_offset on redundant u-boot-env The Western Digital MyBook Live (PowerPC 464/APM82181) has a set of redundant u-boot-env. Loading up the driver the following error: | u_boot_env: Invalid calculated CRC32: 0x4f8f2c86 (expected: 0x98b14514) | u_boot_env: probe of partition@1e000 failed with error -22 Looking up the userspace libubootenv utilities source [0], it looks like the "mark" or "flag" is not part of the crc32 sum... which is unfortunate :( |static int libuboot_load(struct uboot_ctx *ctx) |{ |[...] | if (ctx->redundant) { | [...] | offsetdata = offsetof(struct uboot_env_redund, data); | [...] //-----^^ | } | usable_envsize = ctx->size - offsetdata; | buf[0] = malloc(bufsize); |[...] | for (i = 0; i < copies; i++) { | data = (uint8_t *)(buf[i] + offsetdata); | uint32_t crc; | | ret = devread(ctx, i, buf[i]); | [...] | crc = *(uint32_t *)(buf[i] + offsetcrc); | dev->crc = crc32(0, (uint8_t *)data, usable_envsize); | [0] https://github.com/sbabic/libubootenv/blob/master/src/uboot_env.c#L951 Fixes: d5542923f200 ("nvmem: add driver handling U-Boot environment variables") Signed-off-by: Christian Lamparter Link: https://lore.kernel.org/r/70a16eae113e08db2390b76e174f4837caa135c3.1667580636.git.chunkeey@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/u-boot-env.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/nvmem/u-boot-env.c b/drivers/nvmem/u-boot-env.c index 8e72d1bbd649..4fdbdccebda1 100644 --- a/drivers/nvmem/u-boot-env.c +++ b/drivers/nvmem/u-boot-env.c @@ -135,7 +135,7 @@ static int u_boot_env_parse(struct u_boot_env *priv) break; case U_BOOT_FORMAT_REDUNDANT: crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); - crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark); + crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); data_offset = offsetof(struct u_boot_env_image_redundant, data); break; } -- cgit v1.2.3 From 65946690ed8d972fdb91a74ee75ac0f0f0d68321 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 19 Oct 2022 18:10:53 -0700 Subject: firmware: coreboot: Register bus in module init The coreboot_table driver registers a coreboot bus while probing a "coreboot_table" device representing the coreboot table memory region. Probing this device (i.e., registering the bus) is a dependency for the module_init() functions of any driver for this bus (e.g., memconsole-coreboot.c / memconsole_driver_init()). With synchronous probe, this dependency works OK, as the link order in the Makefile ensures coreboot_table_driver_init() (and thus, coreboot_table_probe()) completes before a coreboot device driver tries to add itself to the bus. With asynchronous probe, however, coreboot_table_probe() may race with memconsole_driver_init(), and so we're liable to hit one of these two: 1. coreboot_driver_register() eventually hits "[...] the bus was not initialized.", and the memconsole driver fails to register; or 2. coreboot_driver_register() gets past #1, but still races with bus_register() and hits some other undefined/crashing behavior (e.g., in driver_find() [1]) We can resolve this by registering the bus in our initcall, and only deferring "device" work (scanning the coreboot memory region and creating sub-devices) to probe(). [1] Example failure, using 'driver_async_probe=*' kernel command line: [ 0.114217] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 ... [ 0.114307] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc1 #63 [ 0.114316] Hardware name: Google Scarlet (DT) ... [ 0.114488] Call trace: [ 0.114494] _raw_spin_lock+0x34/0x60 [ 0.114502] kset_find_obj+0x28/0x84 [ 0.114511] driver_find+0x30/0x50 [ 0.114520] driver_register+0x64/0x10c [ 0.114528] coreboot_driver_register+0x30/0x3c [ 0.114540] memconsole_driver_init+0x24/0x30 [ 0.114550] do_one_initcall+0x154/0x2e0 [ 0.114560] do_initcall_level+0x134/0x160 [ 0.114571] do_initcalls+0x60/0xa0 [ 0.114579] do_basic_setup+0x28/0x34 [ 0.114588] kernel_init_freeable+0xf8/0x150 [ 0.114596] kernel_init+0x2c/0x12c [ 0.114607] ret_from_fork+0x10/0x20 [ 0.114624] Code: 5280002b 1100054a b900092a f9800011 (885ffc01) [ 0.114631] ---[ end trace 0000000000000000 ]--- Fixes: b81e3140e412 ("firmware: coreboot: Make bus registration symmetric") Cc: Signed-off-by: Brian Norris Reviewed-by: Guenter Roeck Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20221019180934.1.If29e167d8a4771b0bf4a39c89c6946ed764817b9@changeid Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/coreboot_table.c | 37 +++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index c52bcaa9def6..9ca21feb9d45 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -149,12 +149,8 @@ static int coreboot_table_probe(struct platform_device *pdev) if (!ptr) return -ENOMEM; - ret = bus_register(&coreboot_bus_type); - if (!ret) { - ret = coreboot_table_populate(dev, ptr); - if (ret) - bus_unregister(&coreboot_bus_type); - } + ret = coreboot_table_populate(dev, ptr); + memunmap(ptr); return ret; @@ -169,7 +165,6 @@ static int __cb_dev_unregister(struct device *dev, void *dummy) static int coreboot_table_remove(struct platform_device *pdev) { bus_for_each_dev(&coreboot_bus_type, NULL, NULL, __cb_dev_unregister); - bus_unregister(&coreboot_bus_type); return 0; } @@ -199,6 +194,32 @@ static struct platform_driver coreboot_table_driver = { .of_match_table = of_match_ptr(coreboot_of_match), }, }; -module_platform_driver(coreboot_table_driver); + +static int __init coreboot_table_driver_init(void) +{ + int ret; + + ret = bus_register(&coreboot_bus_type); + if (ret) + return ret; + + ret = platform_driver_register(&coreboot_table_driver); + if (ret) { + bus_unregister(&coreboot_bus_type); + return ret; + } + + return 0; +} + +static void __exit coreboot_table_driver_exit(void) +{ + platform_driver_unregister(&coreboot_table_driver); + bus_unregister(&coreboot_bus_type); +} + +module_init(coreboot_table_driver_init); +module_exit(coreboot_table_driver_exit); + MODULE_AUTHOR("Google, Inc."); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 7fdba0011157861892c470995ff586a1871e603f Mon Sep 17 00:00:00 2001 From: Anthony DeRossi Date: Wed, 9 Nov 2022 17:40:25 -0800 Subject: vfio: Fix container device registration life cycle In vfio_device_open(), vfio_device_container_register() is always called when open_count == 1. On error, vfio_device_container_unregister() is only called when open_count == 1 and close_device is set. This leaks a registration for devices without a close_device implementation. In vfio_device_fops_release(), vfio_device_container_unregister() is called unconditionally. This can cause a device to be unregistered multiple times. Treating container device registration/unregistration uniformly (always when open_count == 1) fixes both issues. Fixes: ce4b4657ff18 ("vfio: Replace the DMA unmapping notifier with a callback") Signed-off-by: Anthony DeRossi Reviewed-by: Jason Gunthorpe Reviewed-by: Kevin Tian Reviewed-by: Yi Liu Link: https://lore.kernel.org/r/20221110014027.28780-2-ajderossi@gmail.com Signed-off-by: Alex Williamson --- drivers/vfio/vfio_main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 2d168793d4e1..9a4af880e941 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -801,8 +801,9 @@ static struct file *vfio_device_open(struct vfio_device *device) err_close_device: mutex_lock(&device->dev_set->lock); mutex_lock(&device->group->group_lock); - if (device->open_count == 1 && device->ops->close_device) { - device->ops->close_device(device); + if (device->open_count == 1) { + if (device->ops->close_device) + device->ops->close_device(device); vfio_device_container_unregister(device); } @@ -1017,10 +1018,12 @@ static int vfio_device_fops_release(struct inode *inode, struct file *filep) mutex_lock(&device->dev_set->lock); vfio_assert_device_open(device); mutex_lock(&device->group->group_lock); - if (device->open_count == 1 && device->ops->close_device) - device->ops->close_device(device); + if (device->open_count == 1) { + if (device->ops->close_device) + device->ops->close_device(device); - vfio_device_container_unregister(device); + vfio_device_container_unregister(device); + } mutex_unlock(&device->group->group_lock); device->open_count--; if (device->open_count == 0) -- cgit v1.2.3 From 5cd189e410debedda416fecfc12f4716b5829845 Mon Sep 17 00:00:00 2001 From: Anthony DeRossi Date: Wed, 9 Nov 2022 17:40:26 -0800 Subject: vfio: Export the device set open count The open count of a device set is the sum of the open counts of all devices in the set. Drivers can use this value to determine whether shared resources are in use without tracking them manually or accessing the private open_count in vfio_device. Signed-off-by: Anthony DeRossi Reviewed-by: Jason Gunthorpe Reviewed-by: Kevin Tian Reviewed-by: Yi Liu Link: https://lore.kernel.org/r/20221110014027.28780-3-ajderossi@gmail.com Signed-off-by: Alex Williamson --- drivers/vfio/vfio_main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 9a4af880e941..6e8804fe0095 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -125,6 +125,19 @@ static void vfio_release_device_set(struct vfio_device *device) xa_unlock(&vfio_device_set_xa); } +unsigned int vfio_device_set_open_count(struct vfio_device_set *dev_set) +{ + struct vfio_device *cur; + unsigned int open_count = 0; + + lockdep_assert_held(&dev_set->lock); + + list_for_each_entry(cur, &dev_set->device_list, dev_set_list) + open_count += cur->open_count; + return open_count; +} +EXPORT_SYMBOL_GPL(vfio_device_set_open_count); + /* * Group objects - create, release, get, put, search */ -- cgit v1.2.3 From e806e223621e4f5105170df69d7311dc3fb4bbb4 Mon Sep 17 00:00:00 2001 From: Anthony DeRossi Date: Wed, 9 Nov 2022 17:40:27 -0800 Subject: vfio/pci: Check the device set open count on reset vfio_pci_dev_set_needs_reset() inspects the open_count of every device in the set to determine whether a reset is allowed. The current device always has open_count == 1 within vfio_pci_core_disable(), effectively disabling the reset logic. This field is also documented as private in vfio_device, so it should not be used to determine whether other devices in the set are open. Checking for vfio_device_set_open_count() > 1 on the device set fixes both issues. After commit 2cd8b14aaa66 ("vfio/pci: Move to the device set infrastructure"), failure to create a new file for a device would cause the reset to be skipped due to open_count being decremented after calling close_device() in the error path. After commit eadd86f835c6 ("vfio: Remove calls to vfio_group_add_container_user()"), releasing a device would always skip the reset due to an ordering change in vfio_device_fops_release(). Failing to reset the device leaves it in an unknown state, potentially causing errors when it is accessed later or bound to a different driver. This issue was observed with a Radeon RX Vega 56 [1002:687f] (rev c3) assigned to a Windows guest. After shutting down the guest, unbinding the device from vfio-pci, and binding the device to amdgpu: [ 548.007102] [drm:psp_hw_start [amdgpu]] *ERROR* PSP create ring failed! [ 548.027174] [drm:psp_hw_init [amdgpu]] *ERROR* PSP firmware loading failed [ 548.027242] [drm:amdgpu_device_fw_loading [amdgpu]] *ERROR* hw_init of IP block failed -22 [ 548.027306] amdgpu 0000:0a:00.0: amdgpu: amdgpu_device_ip_init failed [ 548.027308] amdgpu 0000:0a:00.0: amdgpu: Fatal error during GPU init Fixes: 2cd8b14aaa66 ("vfio/pci: Move to the device set infrastructure") Fixes: eadd86f835c6 ("vfio: Remove calls to vfio_group_add_container_user()") Signed-off-by: Anthony DeRossi Reviewed-by: Jason Gunthorpe Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20221110014027.28780-4-ajderossi@gmail.com Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci_core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index badc9d828cac..e030c2120183 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -2488,12 +2488,12 @@ static bool vfio_pci_dev_set_needs_reset(struct vfio_device_set *dev_set) struct vfio_pci_core_device *cur; bool needs_reset = false; - list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) { - /* No VFIO device in the set can have an open device FD */ - if (cur->vdev.open_count) - return false; + /* No other VFIO device in the set can be open. */ + if (vfio_device_set_open_count(dev_set) > 1) + return false; + + list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) needs_reset |= cur->needs_reset; - } return needs_reset; } -- cgit v1.2.3 From 20ea34710f7b20e218a42d457da618d99e3fc9d6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 24 Oct 2022 17:40:54 +0200 Subject: drm/radeon: Add HD-audio component notifier support (v6) This patch adds the support for the notification of HD-audio hotplug via the already existing drm_audio_component framework to radeon driver. This allows us more reliable hotplug notification and ELD transfer without accessing HD-audio bus; it's more efficient, and more importantly, it works without waking up the runtime PM. The implementation is rather simplistic: radeon driver provides the get_eld ops for HD-audio, and it notifies the audio hotplug via pin_eld_notify callback upon each radeon_audio_enable() call. The pin->id is referred as the port number passed to the notifier callback, and the corresponding connector is looked through the encoder list in the get_eld callback in turn. The bind and unbind callbacks handle the device-link so that it assures the PM call order. Also, as a gratis bonus, this patch "fixes" the regression by the recent change in HD-audio to be more strict for the HDMI/DP connection, too. Since the HD-audio HDMI/DP codec requires both the connection bit and the valid ELD to be provided, it started failing on some RADEON gfx boards where the ELD update performed instably. As this change switches the communication to a direct way between the audio and the graphics drivers, now the system receives the proper ELD, and the HDMI/DP hotplug starts working again. [ v2: fix the logic in radeon_audio_component_get_eld to walk the connector list since that is where the EDID lives and we can derive the encoder from the connector because the encoder has not been assigned at this point (i.e., during monitor probe). v3: the component binding is moved outside radeon_audio_init() and _fini(), as those are called from suspend/resume, too. Drop modeset lock calls that caused Oops. Moved Kconfig change so that it can be applied on older kernels. v4: revive drm_modeset_lock*() again, add the missing device_link_remove() call at unbinding v5: squash in mutex fix v6: squash in fix for audio get_eld callback ] Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1569 Signed-off-by: Takashi Iwai Signed-off-by: Alex Deucher --- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/radeon/radeon.h | 8 +++ drivers/gpu/drm/radeon/radeon_audio.c | 117 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_device.c | 4 ++ 4 files changed, 130 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 34f5a092c99e..fa986075e8fb 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -243,6 +243,7 @@ config DRM_RADEON select DRM_KMS_HELPER select DRM_TTM select DRM_TTM_HELPER + select SND_HDA_COMPONENT if SND_HDA_CORE select POWER_SUPPLY select HWMON select BACKLIGHT_CLASS_DEVICE diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 166c18d62f6d..2e7161acd443 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -79,6 +79,7 @@ #include #include +#include #include "radeon_family.h" #include "radeon_mode.h" @@ -1796,6 +1797,9 @@ struct r600_audio { struct radeon_audio_funcs *hdmi_funcs; struct radeon_audio_funcs *dp_funcs; struct radeon_audio_basic_funcs *funcs; + struct drm_audio_component *component; + bool component_registered; + struct mutex component_mutex; }; /* @@ -2994,6 +2998,10 @@ void radeon_irq_kms_set_irq_n_enabled(struct radeon_device *rdev, bool enable, const char *name, unsigned n); +/* Audio component binding */ +void radeon_audio_component_init(struct radeon_device *rdev); +void radeon_audio_component_fini(struct radeon_device *rdev); + #include "radeon_object.h" #endif diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 7c5e80d03fc9..d6ccaf24ee0c 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -23,6 +23,7 @@ */ #include +#include #include #include "dce6_afmt.h" @@ -180,6 +181,8 @@ static struct radeon_audio_funcs dce6_dp_funcs = { .dpms = evergreen_dp_enable, }; +static void radeon_audio_component_notify(struct radeon_device *rdev, int port); + static void radeon_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, u8 enable_mask) { @@ -207,6 +210,8 @@ static void radeon_audio_enable(struct radeon_device *rdev, if (rdev->audio.funcs->enable) rdev->audio.funcs->enable(rdev, pin, enable_mask); + + radeon_audio_component_notify(rdev, pin->id); } static void radeon_audio_interface_init(struct radeon_device *rdev) @@ -721,3 +726,115 @@ unsigned int radeon_audio_decode_dfs_div(unsigned int div) else return 0; } + +/* + * Audio component support + */ +static void radeon_audio_component_notify(struct radeon_device *rdev, int port) +{ + struct drm_audio_component *acomp; + + mutex_lock(&rdev->audio.component_mutex); + acomp = rdev->audio.component; + if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) + acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + port, -1); + mutex_unlock(&rdev->audio.component_mutex); +} + +static int radeon_audio_component_get_eld(struct device *kdev, int port, + int pipe, bool *enabled, + unsigned char *buf, int max_bytes) +{ + struct drm_device *dev = dev_get_drvdata(kdev); + struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + struct radeon_encoder_atom_dig *dig; + struct drm_connector *connector; + int ret = 0; + + *enabled = false; + if (!rdev->audio.enabled || !rdev->mode_info.mode_config_initialized) + return 0; + + list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) { + if (!radeon_encoder_is_digital(encoder)) + continue; + radeon_encoder = to_radeon_encoder(encoder); + dig = radeon_encoder->enc_priv; + if (!dig->pin || dig->pin->id != port) + continue; + connector = radeon_get_connector_for_encoder(encoder); + if (!connector) + continue; + *enabled = true; + ret = drm_eld_size(connector->eld); + memcpy(buf, connector->eld, min(max_bytes, ret)); + break; + } + + return ret; +} + +static const struct drm_audio_component_ops radeon_audio_component_ops = { + .get_eld = radeon_audio_component_get_eld, +}; + +static int radeon_audio_component_bind(struct device *kdev, + struct device *hda_kdev, void *data) +{ + struct drm_device *dev = dev_get_drvdata(kdev); + struct radeon_device *rdev = dev->dev_private; + struct drm_audio_component *acomp = data; + + if (WARN_ON(!device_link_add(hda_kdev, kdev, DL_FLAG_STATELESS))) + return -ENOMEM; + + mutex_lock(&rdev->audio.component_mutex); + acomp->ops = &radeon_audio_component_ops; + acomp->dev = kdev; + rdev->audio.component = acomp; + mutex_unlock(&rdev->audio.component_mutex); + + return 0; +} + +static void radeon_audio_component_unbind(struct device *kdev, + struct device *hda_kdev, void *data) +{ + struct drm_device *dev = dev_get_drvdata(kdev); + struct radeon_device *rdev = dev->dev_private; + struct drm_audio_component *acomp = data; + + device_link_remove(hda_kdev, kdev); + + mutex_lock(&rdev->audio.component_mutex); + rdev->audio.component = NULL; + acomp->ops = NULL; + acomp->dev = NULL; + mutex_unlock(&rdev->audio.component_mutex); +} + +static const struct component_ops radeon_audio_component_bind_ops = { + .bind = radeon_audio_component_bind, + .unbind = radeon_audio_component_unbind, +}; + +void radeon_audio_component_init(struct radeon_device *rdev) +{ + if (rdev->audio.component_registered || + !radeon_audio || !radeon_audio_chipset_supported(rdev)) + return; + + if (!component_add(rdev->dev, &radeon_audio_component_bind_ops)) + rdev->audio.component_registered = true; +} + +void radeon_audio_component_fini(struct radeon_device *rdev) +{ + if (rdev->audio.component_registered) { + component_del(rdev->dev, &radeon_audio_component_bind_ops); + rdev->audio.component_registered = false; + } +} diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 262e2bcb30c3..6344454a7721 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1312,6 +1312,7 @@ int radeon_device_init(struct radeon_device *rdev, mutex_init(&rdev->pm.mutex); mutex_init(&rdev->gpu_clock_mutex); mutex_init(&rdev->srbm_mutex); + mutex_init(&rdev->audio.component_mutex); init_rwsem(&rdev->pm.mclk_lock); init_rwsem(&rdev->exclusive_lock); init_waitqueue_head(&rdev->irq.vblank_queue); @@ -1451,6 +1452,8 @@ int radeon_device_init(struct radeon_device *rdev, goto failed; } + radeon_audio_component_init(rdev); + r = radeon_ib_ring_tests(rdev); if (r) DRM_ERROR("ib ring test failed (%d).\n", r); @@ -1513,6 +1516,7 @@ void radeon_device_fini(struct radeon_device *rdev) rdev->shutdown = true; /* evict vram memory */ radeon_bo_evict_vram(rdev); + radeon_audio_component_fini(rdev); radeon_fini(rdev); if (!pci_is_thunderbolt_attached(rdev->pdev)) vga_switcheroo_unregister_client(rdev->pdev); -- cgit v1.2.3 From cb20d6508bff89d85319dbe9a74c50983afc3390 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 26 Oct 2022 11:19:35 -0500 Subject: drm: Move radeon and amdgpu Kconfig options into their directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most Kconfig options to enable a driver are in the Kconfig file inside the relevant directory, move these two to the same. Signed-off-by: Andrew Davis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/Kconfig | 57 -------------------------------------- drivers/gpu/drm/amd/amdgpu/Kconfig | 29 +++++++++++++++++++ drivers/gpu/drm/radeon/Kconfig | 30 ++++++++++++++++++++ 3 files changed, 59 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index fa986075e8fb..9c2d9495cb3c 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -233,65 +233,8 @@ source "drivers/gpu/drm/i2c/Kconfig" source "drivers/gpu/drm/arm/Kconfig" -config DRM_RADEON - tristate "ATI Radeon" - depends on DRM && PCI && MMU - depends on AGP || !AGP - select FW_LOADER - select DRM_DISPLAY_DP_HELPER - select DRM_DISPLAY_HELPER - select DRM_KMS_HELPER - select DRM_TTM - select DRM_TTM_HELPER - select SND_HDA_COMPONENT if SND_HDA_CORE - select POWER_SUPPLY - select HWMON - select BACKLIGHT_CLASS_DEVICE - select INTERVAL_TREE - # radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work - # ACPI_VIDEO's dependencies must also be selected. - select INPUT if ACPI - select ACPI_VIDEO if ACPI - # On x86 ACPI_VIDEO also needs ACPI_WMI - select X86_PLATFORM_DEVICES if ACPI && X86 - select ACPI_WMI if ACPI && X86 - help - Choose this option if you have an ATI Radeon graphics card. There - are both PCI and AGP versions. You don't need to choose this to - run the Radeon in plain VGA mode. - - If M is selected, the module will be called radeon. - source "drivers/gpu/drm/radeon/Kconfig" -config DRM_AMDGPU - tristate "AMD GPU" - depends on DRM && PCI && MMU - select FW_LOADER - select DRM_DISPLAY_DP_HELPER - select DRM_DISPLAY_HDMI_HELPER - select DRM_DISPLAY_HELPER - select DRM_KMS_HELPER - select DRM_SCHED - select DRM_TTM - select DRM_TTM_HELPER - select POWER_SUPPLY - select HWMON - select BACKLIGHT_CLASS_DEVICE - select INTERVAL_TREE - select DRM_BUDDY - # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work - # ACPI_VIDEO's dependencies must also be selected. - select INPUT if ACPI - select ACPI_VIDEO if ACPI - # On x86 ACPI_VIDEO also needs ACPI_WMI - select X86_PLATFORM_DEVICES if ACPI && X86 - select ACPI_WMI if ACPI && X86 - help - Choose this option if you have a recent AMD Radeon graphics card. - - If M is selected, the module will be called amdgpu. - source "drivers/gpu/drm/amd/amdgpu/Kconfig" source "drivers/gpu/drm/nouveau/Kconfig" diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index 7777d55275de..5fcd510f1abb 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig @@ -1,4 +1,33 @@ # SPDX-License-Identifier: MIT + +config DRM_AMDGPU + tristate "AMD GPU" + depends on DRM && PCI && MMU + select FW_LOADER + select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDMI_HELPER + select DRM_DISPLAY_HELPER + select DRM_KMS_HELPER + select DRM_SCHED + select DRM_TTM + select DRM_TTM_HELPER + select POWER_SUPPLY + select HWMON + select BACKLIGHT_CLASS_DEVICE + select INTERVAL_TREE + select DRM_BUDDY + # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work + # ACPI_VIDEO's dependencies must also be selected. + select INPUT if ACPI + select ACPI_VIDEO if ACPI + # On x86 ACPI_VIDEO also needs ACPI_WMI + select X86_PLATFORM_DEVICES if ACPI && X86 + select ACPI_WMI if ACPI && X86 + help + Choose this option if you have a recent AMD Radeon graphics card. + + If M is selected, the module will be called amdgpu. + config DRM_AMDGPU_SI bool "Enable amdgpu support for SI parts" depends on DRM_AMDGPU diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig index 52819e7f1fca..97a277f9a25e 100644 --- a/drivers/gpu/drm/radeon/Kconfig +++ b/drivers/gpu/drm/radeon/Kconfig @@ -1,4 +1,34 @@ # SPDX-License-Identifier: MIT + +config DRM_RADEON + tristate "ATI Radeon" + depends on DRM && PCI && MMU + depends on AGP || !AGP + select FW_LOADER + select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HELPER + select DRM_KMS_HELPER + select DRM_TTM + select DRM_TTM_HELPER + select SND_HDA_COMPONENT if SND_HDA_CORE + select POWER_SUPPLY + select HWMON + select BACKLIGHT_CLASS_DEVICE + select INTERVAL_TREE + # radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work + # ACPI_VIDEO's dependencies must also be selected. + select INPUT if ACPI + select ACPI_VIDEO if ACPI + # On x86 ACPI_VIDEO also needs ACPI_WMI + select X86_PLATFORM_DEVICES if ACPI && X86 + select ACPI_WMI if ACPI && X86 + help + Choose this option if you have an ATI Radeon graphics card. There + are both PCI and AGP versions. You don't need to choose this to + run the Radeon in plain VGA mode. + + If M is selected, the module will be called radeon. + config DRM_RADEON_USERPTR bool "Always enable userptr support" depends on DRM_RADEON -- cgit v1.2.3 From 7701d10a1eb04025b594484975ee09eee11078b1 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Wed, 26 Oct 2022 10:55:10 +0800 Subject: drm/amdgpu: force read discovery file if set discovery=2 If discovery is set to 2 in module parameters explicitly, the intention is to use the discovery file in FW rather than the one in BIOS, usually because the latter is incorrect. This patch to force read discovery file if set discovery=2. Signed-off-by: Yifan Zhang Reviewed-by: Tim Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 3993e6134914..5ea9afaaf4f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -305,8 +305,13 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) goto out; } - if (!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) { - dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n"); + if (!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin) || amdgpu_discovery == 2) { + /* ignore the discovery binary from vram if discovery=2 in kernel module parameter */ + if (amdgpu_discovery == 2) + dev_info(adev->dev,"force read ip discovery binary from file"); + else + dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n"); + /* retry read ip discovery binary from file */ r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin); if (r) { -- cgit v1.2.3 From a1903b01b0997626a4f2a60accf92bff5d5379a6 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 10 Nov 2022 10:52:41 +0800 Subject: drm/amd/pm: skip disabling all smu features on smu_v13_0_10 in suspend skip disabling all smu features on smu_v13_0_10 in suspend Signed-off-by: Kenneth Feng Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 4fe75dd2b329..320cfce1fef5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1449,6 +1449,7 @@ static int smu_disable_dpms(struct smu_context *smu) switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(13, 0, 0): case IP_VERSION(13, 0, 7): + case IP_VERSION(13, 0, 10): return 0; default: break; -- cgit v1.2.3 From 3e931368091f7d5d7902cee9d410eb6db2eea419 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Thu, 10 Nov 2022 14:37:08 +0800 Subject: drm/amdgpu: remove the check of init status in psp_ras_initialize The initialized status indicates RAS TA is loaded, but in some cases (such as RAS fatal error) RAS TA could be destroyed although it's not unloaded. Hence we load RAS TA unconditionally here. Signed-off-by: Tao Zhou Reviewed-by: Candice Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 2fcb5bfbef89..0a8c30475dda 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1526,11 +1526,6 @@ int psp_ras_initialize(struct psp_context *psp) if (amdgpu_sriov_vf(adev)) return 0; - if (psp->ras_context.context.initialized) { - dev_warn(adev->dev, "RAS WARN: TA has already been loaded\n"); - return 0; - } - if (!adev->psp.ras_context.context.bin_desc.size_bytes || !adev->psp.ras_context.context.bin_desc.start_addr) { dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); @@ -1602,6 +1597,9 @@ int psp_ras_initialize(struct psp_context *psp) else { if (ras_cmd->ras_status) dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); + + /* fail to load RAS TA */ + psp->ras_context.context.initialized = false; } return ret; -- cgit v1.2.3 From 4864f2ee9ee2acf4a1009b58fbc62f17fa086d4e Mon Sep 17 00:00:00 2001 From: Tong Liu01 Date: Thu, 10 Nov 2022 17:31:36 +0800 Subject: drm/amdgpu: add vram reservation based on vram_usagebyfirmware_v2_2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move TMR region from top of FB to 2MB for FFBM, so we need to reserve TMR region firstly to make sure TMR can be allocated at 2MB Signed-off-by: Tong Liu01 Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 104 ++++++++++++++++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 51 +++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 5 ++ drivers/gpu/drm/amd/include/atomfirmware.h | 63 ++++++++++++-- 4 files changed, 191 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index b81b77a9efa6..9b97fa39d47a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -101,39 +101,97 @@ void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev) } } +static int amdgpu_atomfirmware_allocate_fb_v2_1(struct amdgpu_device *adev, + struct vram_usagebyfirmware_v2_1 *fw_usage, int *usage_bytes) +{ + uint32_t start_addr, fw_size, drv_size; + + start_addr = le32_to_cpu(fw_usage->start_address_in_kb); + fw_size = le16_to_cpu(fw_usage->used_by_firmware_in_kb); + drv_size = le16_to_cpu(fw_usage->used_by_driver_in_kb); + + DRM_DEBUG("atom firmware v2_1 requested %08x %dkb fw %dkb drv\n", + start_addr, + fw_size, + drv_size); + + if ((start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) == + (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << + ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { + /* Firmware request VRAM reservation for SR-IOV */ + adev->mman.fw_vram_usage_start_offset = (start_addr & + (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; + adev->mman.fw_vram_usage_size = fw_size << 10; + /* Use the default scratch size */ + *usage_bytes = 0; + } else { + *usage_bytes = drv_size << 10; + } + return 0; +} + +static int amdgpu_atomfirmware_allocate_fb_v2_2(struct amdgpu_device *adev, + struct vram_usagebyfirmware_v2_2 *fw_usage, int *usage_bytes) +{ + uint32_t fw_start_addr, fw_size, drv_start_addr, drv_size; + + fw_start_addr = le32_to_cpu(fw_usage->fw_region_start_address_in_kb); + fw_size = le16_to_cpu(fw_usage->used_by_firmware_in_kb); + + drv_start_addr = le32_to_cpu(fw_usage->driver_region0_start_address_in_kb); + drv_size = le32_to_cpu(fw_usage->used_by_driver_region0_in_kb); + + DRM_DEBUG("atom requested fw start at %08x %dkb and drv start at %08x %dkb\n", + fw_start_addr, + fw_size, + drv_start_addr, + drv_size); + + if ((fw_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION << 30)) == 0) { + /* Firmware request VRAM reservation for SR-IOV */ + adev->mman.fw_vram_usage_start_offset = (fw_start_addr & + (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; + adev->mman.fw_vram_usage_size = fw_size << 10; + } + + if ((drv_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION << 30)) == 0) { + /* driver request VRAM reservation for SR-IOV */ + adev->mman.drv_vram_usage_start_offset = (drv_start_addr & + (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; + adev->mman.drv_vram_usage_size = drv_size << 10; + } + + *usage_bytes = 0; + return 0; +} + int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev) { struct atom_context *ctx = adev->mode_info.atom_context; int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_usagebyfirmware); - struct vram_usagebyfirmware_v2_1 *firmware_usage; - uint32_t start_addr, size; + struct vram_usagebyfirmware_v2_1 *fw_usage_v2_1; + struct vram_usagebyfirmware_v2_2 *fw_usage_v2_2; uint16_t data_offset; + uint8_t frev, crev; int usage_bytes = 0; - if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { - firmware_usage = (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset); - DRM_DEBUG("atom firmware requested %08x %dkb fw %dkb drv\n", - le32_to_cpu(firmware_usage->start_address_in_kb), - le16_to_cpu(firmware_usage->used_by_firmware_in_kb), - le16_to_cpu(firmware_usage->used_by_driver_in_kb)); - - start_addr = le32_to_cpu(firmware_usage->start_address_in_kb); - size = le16_to_cpu(firmware_usage->used_by_firmware_in_kb); - - if ((uint32_t)(start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) == - (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << - ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { - /* Firmware request VRAM reservation for SR-IOV */ - adev->mman.fw_vram_usage_start_offset = (start_addr & - (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; - adev->mman.fw_vram_usage_size = size << 10; - /* Use the default scratch size */ - usage_bytes = 0; - } else { - usage_bytes = le16_to_cpu(firmware_usage->used_by_driver_in_kb) << 10; + if (amdgpu_atom_parse_data_header(ctx, index, NULL, &frev, &crev, &data_offset)) { + if (frev == 2 && crev == 1) { + fw_usage_v2_1 = + (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset); + amdgpu_atomfirmware_allocate_fb_v2_1(adev, + fw_usage_v2_1, + &usage_bytes); + } else if (frev >= 2 && crev >= 2) { + fw_usage_v2_2 = + (struct vram_usagebyfirmware_v2_2 *)(ctx->bios + data_offset); + amdgpu_atomfirmware_allocate_fb_v2_2(adev, + fw_usage_v2_2, + &usage_bytes); } } + ctx->scratch_size_bytes = 0; if (usage_bytes == 0) usage_bytes = 20 * 1024; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index c9ceea46711e..02a8f25ae134 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1561,6 +1561,23 @@ static void amdgpu_ttm_fw_reserve_vram_fini(struct amdgpu_device *adev) NULL, &adev->mman.fw_vram_usage_va); } +/* + * Driver Reservation functions + */ +/** + * amdgpu_ttm_drv_reserve_vram_fini - free drv reserved vram + * + * @adev: amdgpu_device pointer + * + * free drv reserved vram if it has been reserved. + */ +static void amdgpu_ttm_drv_reserve_vram_fini(struct amdgpu_device *adev) +{ + amdgpu_bo_free_kernel(&adev->mman.drv_vram_usage_reserved_bo, + NULL, + NULL); +} + /** * amdgpu_ttm_fw_reserve_vram_init - create bo vram reservation from fw * @@ -1587,6 +1604,31 @@ static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev) &adev->mman.fw_vram_usage_va); } +/** + * amdgpu_ttm_drv_reserve_vram_init - create bo vram reservation from driver + * + * @adev: amdgpu_device pointer + * + * create bo vram reservation from drv. + */ +static int amdgpu_ttm_drv_reserve_vram_init(struct amdgpu_device *adev) +{ + uint64_t vram_size = adev->gmc.visible_vram_size; + + adev->mman.drv_vram_usage_reserved_bo = NULL; + + if (adev->mman.drv_vram_usage_size == 0 || + adev->mman.drv_vram_usage_size > vram_size) + return 0; + + return amdgpu_bo_create_kernel_at(adev, + adev->mman.drv_vram_usage_start_offset, + adev->mman.drv_vram_usage_size, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->mman.drv_vram_usage_reserved_bo, + NULL); +} + /* * Memoy training reservation functions */ @@ -1754,6 +1796,14 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) return r; } + /* + *The reserved vram for driver must be pinned to the specified + *place on the VRAM, so reserve it early. + */ + r = amdgpu_ttm_drv_reserve_vram_init(adev); + if (r) + return r; + /* * only NAVI10 and onwards ASIC support for IP discovery. * If IP discovery enabled, a block of memory should be @@ -1879,6 +1929,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL, &adev->mman.sdma_access_ptr); amdgpu_ttm_fw_reserve_vram_fini(adev); + amdgpu_ttm_drv_reserve_vram_fini(adev); if (drm_dev_enter(adev_to_drm(adev), &idx)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 6a70818039dd..7c38843f411e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -84,6 +84,11 @@ struct amdgpu_mman { struct amdgpu_bo *fw_vram_usage_reserved_bo; void *fw_vram_usage_va; + /* driver VRAM reservation */ + u64 drv_vram_usage_start_offset; + u64 drv_vram_usage_size; + struct amdgpu_bo *drv_vram_usage_reserved_bo; + /* PAGE_SIZE'd BO for process memory r/w over SDMA. */ struct amdgpu_bo *sdma_access_bo; void *sdma_access_ptr; diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index ff855cb21d3f..bbe1337a8cee 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -705,20 +705,65 @@ struct atom_gpio_pin_lut_v2_1 }; -/* - *************************************************************************** - Data Table vram_usagebyfirmware structure - *************************************************************************** -*/ +/* + * VBIOS/PRE-OS always reserve a FB region at the top of frame buffer. driver should not write + * access that region. driver can allocate their own reservation region as long as it does not + * overlap firwmare's reservation region. + * if (pre-NV1X) atom data table firmwareInfoTable version < 3.3: + * in this case, atom data table vram_usagebyfirmwareTable version always <= 2.1 + * if VBIOS/UEFI GOP is posted: + * VBIOS/UEFIGOP update used_by_firmware_in_kb = total reserved size by VBIOS + * update start_address_in_kb = total_mem_size_in_kb - used_by_firmware_in_kb; + * ( total_mem_size_in_kb = reg(CONFIG_MEMSIZE)<<10) + * driver can allocate driver reservation region under firmware reservation, + * used_by_driver_in_kb = driver reservation size + * driver reservation start address = (start_address_in_kb - used_by_driver_in_kb) + * Comment1[hchan]: There is only one reservation at the beginning of the FB reserved by + * host driver. Host driver would overwrite the table with the following + * used_by_firmware_in_kb = total reserved size for pf-vf info exchange and + * set SRIOV_MSG_SHARE_RESERVATION mask start_address_in_kb = 0 + * else there is no VBIOS reservation region: + * driver must allocate driver reservation region at top of FB. + * driver set used_by_driver_in_kb = driver reservation size + * driver reservation start address = (total_mem_size_in_kb - used_by_driver_in_kb) + * same as Comment1 + * else (NV1X and after): + * if VBIOS/UEFI GOP is posted: + * VBIOS/UEFIGOP update: + * used_by_firmware_in_kb = atom_firmware_Info_v3_3.fw_reserved_size_in_kb; + * start_address_in_kb = total_mem_size_in_kb - used_by_firmware_in_kb; + * (total_mem_size_in_kb = reg(CONFIG_MEMSIZE)<<10) + * if vram_usagebyfirmwareTable version <= 2.1: + * driver can allocate driver reservation region under firmware reservation, + * driver set used_by_driver_in_kb = driver reservation size + * driver reservation start address = start_address_in_kb - used_by_driver_in_kb + * same as Comment1 + * else driver can: + * allocate it reservation any place as long as it does overlap pre-OS FW reservation area + * set used_by_driver_region0_in_kb = driver reservation size + * set driver_region0_start_address_in_kb = driver reservation region start address + * Comment2[hchan]: Host driver can set used_by_firmware_in_kb and start_address_in_kb to + * zero as the reservation for VF as it doesn’t exist. And Host driver should also + * update atom_firmware_Info table to remove the same VBIOS reservation as well. + */ struct vram_usagebyfirmware_v2_1 { - struct atom_common_table_header table_header; - uint32_t start_address_in_kb; - uint16_t used_by_firmware_in_kb; - uint16_t used_by_driver_in_kb; + struct atom_common_table_header table_header; + uint32_t start_address_in_kb; + uint16_t used_by_firmware_in_kb; + uint16_t used_by_driver_in_kb; }; +struct vram_usagebyfirmware_v2_2 { + struct atom_common_table_header table_header; + uint32_t fw_region_start_address_in_kb; + uint16_t used_by_firmware_in_kb; + uint16_t reserved; + uint32_t driver_region0_start_address_in_kb; + uint32_t used_by_driver_region0_in_kb; + uint32_t reserved32[7]; +}; /* *************************************************************************** -- cgit v1.2.3 From ecc9b6e15af2ffc8b9c0e6f15160eb8aaea36af5 Mon Sep 17 00:00:00 2001 From: Gavin Wan Date: Wed, 9 Nov 2022 13:12:42 -0500 Subject: drm/amdgpu: Ignore stop rlc on SRIOV environment. For SRIOV, the guest driver should not do stop rlc. The host handles programing RLC. On SRIOV, the stop rlc will be hang (RLC related registers are blocked by policy) when the RLCG interface is not enabled. Reviewed-by: Yang Wang Acked-by: Alex Deucher Signed-off-by: Gavin Wan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 320cfce1fef5..9492dd638aea 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1518,7 +1518,7 @@ static int smu_disable_dpms(struct smu_context *smu) } if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2) && - adev->gfx.rlc.funcs->stop) + !amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs->stop) adev->gfx.rlc.funcs->stop(adev); return ret; -- cgit v1.2.3 From 0a204ce0e698e5b94a064de6848b8c4641860f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 7 Nov 2022 21:25:39 +0200 Subject: drm/amdgpu: Use drm_mode_init() for on-stack modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize on-stack modes with drm_mode_init() to guarantee no stack garbage in the list head, or that we aren't copying over another mode's list head. Based on the following cocci script, with manual fixups: @decl@ identifier M; expression E; @@ - struct drm_display_mode M = E; + struct drm_display_mode M; @@ identifier decl.M; expression decl.E; statement S, S1; @@ struct drm_display_mode M; ... when != S + drm_mode_init(&M, &E); + S1 @@ expression decl.E; @@ - &*E + E Cc: Harry Wentland Cc: Leo Li Cc: Rodrigo Siqueira Cc: Alex Deucher Cc: amd-gfx@lists.freedesktop.org Reviewed-by: Harry Wentland Signed-off-by: Ville Syrjälä Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5114726dedf7..65715e6e3dd5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5684,7 +5684,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, const struct drm_connector_state *con_state = dm_state ? &dm_state->base : NULL; struct dc_stream_state *stream = NULL; - struct drm_display_mode mode = *drm_mode; + struct drm_display_mode mode; struct drm_display_mode saved_mode; struct drm_display_mode *freesync_mode = NULL; bool native_mode_found = false; @@ -5699,6 +5699,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, struct dc_sink *sink = NULL; + drm_mode_init(&mode, drm_mode); memset(&saved_mode, 0, sizeof(saved_mode)); if (aconnector == NULL) { -- cgit v1.2.3 From 7989d0b731858611289fbfd7c8fb1cdeda30cbc6 Mon Sep 17 00:00:00 2001 From: Paulo Miguel Almeida Date: Wed, 9 Nov 2022 20:33:34 +1300 Subject: drm/amdgpu: Replace one-element array with flex-array member One-element arrays are deprecated, and we are replacing them with flexible array members instead. So, replace one-element array with flexible-array member in structs _ATOM_CONNECTOR_DEVICE_TAG_RECORD, _ATOM_OBJECT_GPIO_CNTL_RECORD, _ATOM_BRACKET_LAYOUT_RECORD, _ATOM_BRACKET_LAYOUT_RECORD, _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3, _ATOM_FUSION_SYSTEM_INFO_V3, _ATOM_I2C_DATA_RECORD, _ATOM_I2C_DEVICE_SETUP_INFO, _ATOM_ASIC_MVDD_INFO and refactor the rest of the code accordingly. While at it, removed a redundant casting. Important to mention is that doing a build before/after this patch results in no binary output differences. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/79 Link: https://github.com/KSPP/linux/issues/238 Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101836 [1] Signed-off-by: Paulo Miguel Almeida Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 5 ++--- drivers/gpu/drm/amd/include/atombios.h | 16 ++++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 39dd8b2dc254..6b9e64cd4379 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -2606,8 +2606,7 @@ static enum bp_result update_slot_layout_info( for (;;) { - record_header = (ATOM_COMMON_RECORD_HEADER *) - GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset); + record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset); if (record_header == NULL) { result = BP_RESULT_BADBIOSTABLE; break; @@ -2621,7 +2620,7 @@ static enum bp_result update_slot_layout_info( if (record_header->ucRecordType == ATOM_BRACKET_LAYOUT_RECORD_TYPE && - sizeof(ATOM_BRACKET_LAYOUT_RECORD) + struct_size(record, asConnInfo, 1) <= record_header->ucRecordSize) { record = (ATOM_BRACKET_LAYOUT_RECORD *) (record_header); diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index 55ae93c1e365..60c44a8a067f 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -4733,7 +4733,7 @@ typedef struct _ATOM_CONNECTOR_DEVICE_TAG_RECORD ATOM_COMMON_RECORD_HEADER sheader; UCHAR ucNumberOfDevice; UCHAR ucReserved; - ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[1]; //This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation + ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[]; //This Id is same as "ATOM_DEVICE_XXX_SUPPORT" }ATOM_CONNECTOR_DEVICE_TAG_RECORD; @@ -4793,7 +4793,7 @@ typedef struct _ATOM_OBJECT_GPIO_CNTL_RECORD ATOM_COMMON_RECORD_HEADER sheader; UCHAR ucFlags; // Future expnadibility UCHAR ucNumberOfPins; // Number of GPIO pins used to control the object - ATOM_GPIO_PIN_CONTROL_PAIR asGpio[1]; // the real gpio pin pair determined by number of pins ucNumberOfPins + ATOM_GPIO_PIN_CONTROL_PAIR asGpio[]; // the real gpio pin pair determined by number of pins ucNumberOfPins }ATOM_OBJECT_GPIO_CNTL_RECORD; //Definitions for GPIO pin state @@ -4982,7 +4982,7 @@ typedef struct _ATOM_BRACKET_LAYOUT_RECORD UCHAR ucWidth; UCHAR ucConnNum; UCHAR ucReserved; - ATOM_CONNECTOR_LAYOUT_INFO asConnInfo[1]; + ATOM_CONNECTOR_LAYOUT_INFO asConnInfo[]; }ATOM_BRACKET_LAYOUT_RECORD; @@ -5161,7 +5161,7 @@ typedef struct _ATOM_GPIO_VOLTAGE_OBJECT_V3 UCHAR ucPhaseDelay; // phase delay in unit of micro second UCHAR ucReserved; ULONG ulGpioMaskVal; // GPIO Mask value - VOLTAGE_LUT_ENTRY_V2 asVolGpioLut[1]; + VOLTAGE_LUT_ENTRY_V2 asVolGpioLut[]; }ATOM_GPIO_VOLTAGE_OBJECT_V3; typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 @@ -5171,7 +5171,7 @@ typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 UCHAR ucLeakageEntryNum; // indicate the entry number of LeakageId/Voltage Lut table UCHAR ucReserved[2]; ULONG ulMaxVoltageLevel; - LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[1]; + LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[]; }ATOM_LEAKAGE_VOLTAGE_OBJECT_V3; @@ -6599,7 +6599,7 @@ typedef struct _ATOM_FUSION_SYSTEM_INFO_V3 typedef struct _ATOM_I2C_DATA_RECORD { UCHAR ucNunberOfBytes; //Indicates how many bytes SW needs to write to the external ASIC for one block, besides to "Start" and "Stop" - UCHAR ucI2CData[1]; //I2C data in bytes, should be less than 16 bytes usually + UCHAR ucI2CData[]; //I2C data in bytes, should be less than 16 bytes usually }ATOM_I2C_DATA_RECORD; @@ -6610,14 +6610,14 @@ typedef struct _ATOM_I2C_DEVICE_SETUP_INFO UCHAR ucSSChipID; //SS chip being used UCHAR ucSSChipSlaveAddr; //Slave Address to set up this SS chip UCHAR ucNumOfI2CDataRecords; //number of data block - ATOM_I2C_DATA_RECORD asI2CData[1]; + ATOM_I2C_DATA_RECORD asI2CData[]; }ATOM_I2C_DEVICE_SETUP_INFO; //========================================================================================== typedef struct _ATOM_ASIC_MVDD_INFO { ATOM_COMMON_TABLE_HEADER sHeader; - ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[1]; + ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[]; }ATOM_ASIC_MVDD_INFO; //========================================================================================== -- cgit v1.2.3 From fe6d2ca6f3f806f2f03e961d80cdbf27073868c8 Mon Sep 17 00:00:00 2001 From: Liu Jian Date: Wed, 9 Nov 2022 17:31:22 +0800 Subject: drm/amd/display: delete the duplicate .set_odm_bypass initialization in dcn314_tg_funcs Fix below sparse warning: drivers/gpu/drm/amd/amdgpu/../display/dc/dcn314/dcn314_optc.c:244:18: warning: Initializer entry defined twice drivers/gpu/drm/amd/amdgpu/../display/dc/dcn314/dcn314_optc.c:257:18: also defined here Fixes: 5ade1b951dec ("drm/amd/display: Add OTG/ODM functions") Signed-off-by: Liu Jian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c index 47eb162f1a75..58d38de6a0f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c @@ -241,7 +241,6 @@ static struct timing_generator_funcs dcn314_tg_funcs = { .set_dsc_config = optc3_set_dsc_config, .get_dsc_status = optc2_get_dsc_status, .set_dwb_source = NULL, - .set_odm_bypass = optc3_set_odm_bypass, .set_odm_combine = optc314_set_odm_combine, .get_optc_source = optc2_get_optc_source, .set_out_mux = optc3_set_out_mux, -- cgit v1.2.3 From 2ebf61f2cfb9a11bc17db30df3e675a4cd7418d3 Mon Sep 17 00:00:00 2001 From: Dong Chenchen Date: Thu, 10 Nov 2022 22:33:14 +0800 Subject: drm/amdgpu: Fix memory leak in amdgpu_cs_pass1 When p->gang_size equals 0, amdgpu_cs_pass1() will return directly without freeing chunk_array, which will cause a memory leak issue, this patch fixes it. Fixes: 4624459c84d7 ("drm/amdgpu: add gang submit frontend v6") Reviewed-by: Luben Tuikov Signed-off-by: Dong Chenchen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index d371000a5727..255d545e5524 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -287,8 +287,10 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p, } } - if (!p->gang_size) - return -EINVAL; + if (!p->gang_size) { + ret = -EINVAL; + goto free_partial_kdata; + } for (i = 0; i < p->gang_size; ++i) { ret = amdgpu_job_alloc(p->adev, num_ibs[i], &p->jobs[i], vm); -- cgit v1.2.3 From 550b33cfd445296868a478e8413ffb2e963eed32 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 10 Nov 2022 10:36:20 +0100 Subject: arm64: efi: Force the use of SetVirtualAddressMap() on Altra machines Ampere Altra machines are reported to misbehave when the SetTime() EFI runtime service is called after ExitBootServices() but before calling SetVirtualAddressMap(). Given that the latter is horrid, pointless and explicitly documented as optional by the EFI spec, we no longer invoke it at boot if the configured size of the VA space guarantees that the EFI runtime memory regions can remain mapped 1:1 like they are at boot time. On Ampere Altra machines, this results in SetTime() calls issued by the rtc-efi driver triggering synchronous exceptions during boot. We can now recover from those without bringing down the system entirely, due to commit 23715a26c8d81291 ("arm64: efi: Recover from synchronous exceptions occurring in firmware"). However, it would be better to avoid the issue entirely, given that the firmware appears to remain in a funny state after this. So attempt to identify these machines based on the 'family' field in the type #1 SMBIOS record, and call SetVirtualAddressMap() unconditionally in that case. Tested-by: Alexandru Elisei Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/arm64-stub.c | 17 ++++++++++- drivers/firmware/efi/libstub/efistub.h | 28 ++++++++++++++++++ drivers/firmware/efi/libstub/smbios.c | 48 +++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 drivers/firmware/efi/libstub/smbios.c (limited to 'drivers') diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index b1601aad7e1a..ef5045a53ce0 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -82,7 +82,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o lib-$(CONFIG_ARM) += arm32-stub.o -lib-$(CONFIG_ARM64) += arm64-stub.o +lib-$(CONFIG_ARM64) += arm64-stub.o smbios.o lib-$(CONFIG_X86) += x86-stub.o lib-$(CONFIG_RISCV) += riscv-stub.o lib-$(CONFIG_LOONGARCH) += loongarch-stub.o diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index 259e4b852d63..f9de5217ea65 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -15,6 +15,21 @@ #include "efistub.h" +static bool system_needs_vamap(void) +{ + const u8 *type1_family = efi_get_smbios_string(1, family); + + /* + * Ampere Altra machines crash in SetTime() if SetVirtualAddressMap() + * has not been called prior. + */ + if (!type1_family || strcmp(type1_family, "Altra")) + return false; + + efi_warn("Working around broken SetVirtualAddressMap()\n"); + return true; +} + efi_status_t check_platform_features(void) { u64 tg; @@ -24,7 +39,7 @@ efi_status_t check_platform_features(void) * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is * unnecessary. */ - if (VA_BITS_MIN >= 48) + if (VA_BITS_MIN >= 48 && !system_needs_vamap()) efi_novamap = true; /* UEFI mandates support for 4 KB granularity, no need to check */ diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index a30fb5d8ef05..eb03d5a9aac8 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -975,4 +975,32 @@ efi_enable_reset_attack_mitigation(void) { } void efi_retrieve_tpm2_eventlog(void); +struct efi_smbios_record { + u8 type; + u8 length; + u16 handle; +}; + +struct efi_smbios_type1_record { + struct efi_smbios_record header; + + u8 manufacturer; + u8 product_name; + u8 version; + u8 serial_number; + efi_guid_t uuid; + u8 wakeup_type; + u8 sku_number; + u8 family; +}; + +#define efi_get_smbios_string(__type, __name) ({ \ + int size = sizeof(struct efi_smbios_type ## __type ## _record); \ + int off = offsetof(struct efi_smbios_type ## __type ## _record, \ + __name); \ + __efi_get_smbios_string(__type, off, size); \ +}) + +const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize); + #endif diff --git a/drivers/firmware/efi/libstub/smbios.c b/drivers/firmware/efi/libstub/smbios.c new file mode 100644 index 000000000000..460418b7f5f5 --- /dev/null +++ b/drivers/firmware/efi/libstub/smbios.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright 2022 Google LLC +// Author: Ard Biesheuvel + +#include + +#include "efistub.h" + +typedef struct efi_smbios_protocol efi_smbios_protocol_t; + +struct efi_smbios_protocol { + efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t, + u16 *, struct efi_smbios_record *); + efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *, + unsigned long *, u8 *); + efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16); + efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *, + struct efi_smbios_record **, + efi_handle_t *); + + u8 major_version; + u8 minor_version; +}; + +const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize) +{ + struct efi_smbios_record *record; + efi_smbios_protocol_t *smbios; + efi_status_t status; + u16 handle = 0xfffe; + const u8 *strtable; + + status = efi_bs_call(locate_protocol, &EFI_SMBIOS_PROTOCOL_GUID, NULL, + (void **)&smbios) ?: + efi_call_proto(smbios, get_next, &handle, &type, &record, NULL); + if (status != EFI_SUCCESS) + return NULL; + + strtable = (u8 *)record + recsize; + for (int i = 1; i < ((u8 *)record)[offset]; i++) { + int len = strlen(strtable); + + if (!len) + return NULL; + strtable += len + 1; + } + return strtable; +} -- cgit v1.2.3 From 9bae30de136a645e29f632313c0ebb02fc00641b Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Mon, 7 Nov 2022 12:24:10 -0800 Subject: drm/i915/perf: Fix kernel-doc warning Fix kernel-doc issue from a previous commit. Signed-off-by: Umesh Nerlige Ramappa Fixes: 2db609c01495 ("drm/i915/perf: Replace gt->perf.lock with stream->lock for file ops") Reviewed-by: Ashutosh Dixit Signed-off-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20221107202410.1976895-1-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/i915/i915_perf_types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_perf_types.h b/drivers/gpu/drm/i915/i915_perf_types.h index e0c96b44eda8..ca150b7af3f2 100644 --- a/drivers/gpu/drm/i915/i915_perf_types.h +++ b/drivers/gpu/drm/i915/i915_perf_types.h @@ -146,8 +146,8 @@ struct i915_perf_stream { */ struct intel_engine_cs *engine; - /* - * Lock associated with operations on stream + /** + * @lock: Lock associated with operations on stream */ struct mutex lock; -- cgit v1.2.3 From ff963634f7b2e0dc011349abb3fb81a0d074f443 Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Tue, 1 Nov 2022 15:07:15 +0800 Subject: drm/drv: Fix potential memory leak in drm_dev_init() drm_dev_init() will add drm_dev_init_release() as a callback. When drmm_add_action() failed, the release function won't be added. As the result, the ref cnt added by device_get() in drm_dev_init() won't be put by drm_dev_init_release(), which leads to the memleak. Use drmm_add_action_or_reset() instead of drmm_add_action() to prevent memleak. unreferenced object 0xffff88810bc0c800 (size 2048): comm "modprobe", pid 8322, jiffies 4305809845 (age 15.292s) hex dump (first 32 bytes): e8 cc c0 0b 81 88 ff ff ff ff ff ff 00 00 00 00 ................ 20 24 3c 0c 81 88 ff ff 18 c8 c0 0b 81 88 ff ff $<............. backtrace: [<000000007251f72d>] __kmalloc+0x4b/0x1c0 [<0000000045f21f26>] platform_device_alloc+0x2d/0xe0 [<000000004452a479>] platform_device_register_full+0x24/0x1c0 [<0000000089f4ea61>] 0xffffffffa0736051 [<00000000235b2441>] do_one_initcall+0x7a/0x380 [<0000000001a4a177>] do_init_module+0x5c/0x230 [<000000002bf8a8e2>] load_module+0x227d/0x2420 [<00000000637d6d0a>] __do_sys_finit_module+0xd5/0x140 [<00000000c99fc324>] do_syscall_64+0x3f/0x90 [<000000004d85aa77>] entry_SYSCALL_64_after_hwframe+0x63/0xcd Fixes: 2cbf7fc6718b ("drm: Use drmm_ for drm_dev_init cleanup") Signed-off-by: Shang XiaoJing Reviewed-by: Lyude Paul Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20221101070716.9189-2-shangxiaojing@huawei.com --- drivers/gpu/drm/drm_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8214a0b1ab7f..203bf8d6c34c 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -615,7 +615,7 @@ static int drm_dev_init(struct drm_device *dev, mutex_init(&dev->clientlist_mutex); mutex_init(&dev->master_mutex); - ret = drmm_add_action(dev, drm_dev_init_release, NULL); + ret = drmm_add_action_or_reset(dev, drm_dev_init_release, NULL); if (ret) return ret; -- cgit v1.2.3 From 4979524f5a2a8210e87fde2f642b0dc060860821 Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Tue, 1 Nov 2022 15:07:16 +0800 Subject: drm: Fix potential null-ptr-deref in drm_vblank_destroy_worker() drm_vblank_init() call drmm_add_action_or_reset() with drm_vblank_init_release() as action. If __drmm_add_action() failed, will directly call drm_vblank_init_release() with the vblank whose worker is NULL. As the resule, a null-ptr-deref will happen in kthread_destroy_worker(). Add the NULL check before calling drm_vblank_destroy_worker(). BUG: null-ptr-deref KASAN: null-ptr-deref in range [0x0000000000000068-0x000000000000006f] CPU: 5 PID: 961 Comm: modprobe Not tainted 6.0.0-11331-gd465bff130bf-dirty RIP: 0010:kthread_destroy_worker+0x25/0xb0 Call Trace: drm_vblank_init_release+0x124/0x220 [drm] ? drm_crtc_vblank_restore+0x8b0/0x8b0 [drm] __drmm_add_action_or_reset+0x41/0x50 [drm] drm_vblank_init+0x282/0x310 [drm] vkms_init+0x35f/0x1000 [vkms] ? 0xffffffffc4508000 ? lock_is_held_type+0xd7/0x130 ? __kmem_cache_alloc_node+0x1c2/0x2b0 ? lock_is_held_type+0xd7/0x130 ? 0xffffffffc4508000 do_one_initcall+0xd0/0x4f0 ... do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 Fixes: 5e6c2b4f9161 ("drm/vblank: Add vblank works") Signed-off-by: Shang XiaoJing Reviewed-by: Lyude Paul Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20221101070716.9189-3-shangxiaojing@huawei.com --- drivers/gpu/drm/drm_internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 7bb98e6a446d..5ea5e260118c 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -104,7 +104,8 @@ static inline void drm_vblank_flush_worker(struct drm_vblank_crtc *vblank) static inline void drm_vblank_destroy_worker(struct drm_vblank_crtc *vblank) { - kthread_destroy_worker(vblank->worker); + if (vblank->worker) + kthread_destroy_worker(vblank->worker); } int drm_vblank_worker_init(struct drm_vblank_crtc *vblank); -- cgit v1.2.3 From de91b3197d15172407608b2c357aab7ac1451e2b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 9 Nov 2022 15:01:16 +0000 Subject: eth: sp7021: drop free_netdev() from spl2sw_init_netdev() It's not necessary to free netdev allocated with devm_alloc_etherdev() and using free_netdev() leads to double free. Fixes: fd3040b9394c ("net: ethernet: Add driver for Sunplus SP7021") Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20221109150116.2988194-1-weiyongjun@huaweicloud.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/sunplus/spl2sw_driver.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sunplus/spl2sw_driver.c b/drivers/net/ethernet/sunplus/spl2sw_driver.c index 9be585237277..c499a14314f1 100644 --- a/drivers/net/ethernet/sunplus/spl2sw_driver.c +++ b/drivers/net/ethernet/sunplus/spl2sw_driver.c @@ -287,7 +287,6 @@ static u32 spl2sw_init_netdev(struct platform_device *pdev, u8 *mac_addr, if (ret) { dev_err(&pdev->dev, "Failed to register net device \"%s\"!\n", ndev->name); - free_netdev(ndev); *r_ndev = NULL; return ret; } -- cgit v1.2.3 From 8c76310740807ade5ecdab5888f70ecb6d35732e Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 8 Nov 2022 21:40:01 +0800 Subject: ata: libata-transport: fix double ata_host_put() in ata_tport_add() In the error path in ata_tport_add(), when calling put_device(), ata_tport_release() is called, it will put the refcount of 'ap->host'. And then ata_host_put() is called again, the refcount is decreased to 0, ata_host_release() is called, all ports are freed and set to null. When unbinding the device after failure, ata_host_stop() is called to release the resources, it leads a null-ptr-deref(), because all the ports all freed and null. Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008 CPU: 7 PID: 18671 Comm: modprobe Kdump: loaded Tainted: G E 6.1.0-rc3+ #8 pstate: 80400009 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : ata_host_stop+0x3c/0x84 [libata] lr : release_nodes+0x64/0xd0 Call trace: ata_host_stop+0x3c/0x84 [libata] release_nodes+0x64/0xd0 devres_release_all+0xbc/0x1b0 device_unbind_cleanup+0x20/0x70 really_probe+0x158/0x320 __driver_probe_device+0x84/0x120 driver_probe_device+0x44/0x120 __driver_attach+0xb4/0x220 bus_for_each_dev+0x78/0xdc driver_attach+0x2c/0x40 bus_add_driver+0x184/0x240 driver_register+0x80/0x13c __pci_register_driver+0x4c/0x60 ahci_pci_driver_init+0x30/0x1000 [ahci] Fix this by removing redundant ata_host_put() in the error path. Fixes: 2623c7a5f279 ("libata: add refcounting to ata_host") Signed-off-by: Yang Yingliang Signed-off-by: Damien Le Moal --- drivers/ata/libata-transport.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index a7e9a75410a3..105da3ec5eaa 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -317,7 +317,6 @@ int ata_tport_add(struct device *parent, tport_err: transport_destroy_device(dev); put_device(dev); - ata_host_put(ap->host); return error; } -- cgit v1.2.3 From 3613dbe3909dcc637fe6be00e4dc43b4aa0470ee Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 8 Nov 2022 21:40:02 +0800 Subject: ata: libata-transport: fix error handling in ata_tport_add() In ata_tport_add(), the return value of transport_add_device() is not checked. As a result, it causes null-ptr-deref while removing the module, because transport_remove_device() is called to remove the device that was not added. Unable to handle kernel NULL pointer dereference at virtual address 00000000000000d0 CPU: 12 PID: 13605 Comm: rmmod Kdump: loaded Tainted: G W 6.1.0-rc3+ #8 pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : device_del+0x48/0x39c lr : device_del+0x44/0x39c Call trace: device_del+0x48/0x39c attribute_container_class_device_del+0x28/0x40 transport_remove_classdev+0x60/0x7c attribute_container_device_trigger+0x118/0x120 transport_remove_device+0x20/0x30 ata_tport_delete+0x34/0x60 [libata] ata_port_detach+0x148/0x1b0 [libata] ata_pci_remove_one+0x50/0x80 [libata] ahci_remove_one+0x4c/0x8c [ahci] Fix this by checking and handling return value of transport_add_device() in ata_tport_add(). Fixes: d9027470b886 ("[libata] Add ATA transport class") Signed-off-by: Yang Yingliang Signed-off-by: Damien Le Moal --- drivers/ata/libata-transport.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 105da3ec5eaa..ef53bdfbcbb2 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -301,7 +301,9 @@ int ata_tport_add(struct device *parent, pm_runtime_enable(dev); pm_runtime_forbid(dev); - transport_add_device(dev); + error = transport_add_device(dev); + if (error) + goto tport_transport_add_err; transport_configure_device(dev); error = ata_tlink_add(&ap->link); @@ -312,6 +314,7 @@ int ata_tport_add(struct device *parent, tport_link_err: transport_remove_device(dev); + tport_transport_add_err: device_del(dev); tport_err: -- cgit v1.2.3 From cf0816f6322c5c37ee52655f928e91ecf32da103 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 8 Nov 2022 21:40:03 +0800 Subject: ata: libata-transport: fix error handling in ata_tlink_add() In ata_tlink_add(), the return value of transport_add_device() is not checked. As a result, it causes null-ptr-deref while removing the module, because transport_remove_device() is called to remove the device that was not added. Unable to handle kernel NULL pointer dereference at virtual address 00000000000000d0 CPU: 33 PID: 13850 Comm: rmmod Kdump: loaded Tainted: G W 6.1.0-rc3+ #12 pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : device_del+0x48/0x39c lr : device_del+0x44/0x39c Call trace: device_del+0x48/0x39c attribute_container_class_device_del+0x28/0x40 transport_remove_classdev+0x60/0x7c attribute_container_device_trigger+0x118/0x120 transport_remove_device+0x20/0x30 ata_tlink_delete+0x88/0xb0 [libata] ata_tport_delete+0x2c/0x60 [libata] ata_port_detach+0x148/0x1b0 [libata] ata_pci_remove_one+0x50/0x80 [libata] ahci_remove_one+0x4c/0x8c [ahci] Fix this by checking and handling return value of transport_add_device() in ata_tlink_add(). Fixes: d9027470b886 ("[libata] Add ATA transport class") Signed-off-by: Yang Yingliang Signed-off-by: Damien Le Moal --- drivers/ata/libata-transport.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index ef53bdfbcbb2..aac9336e8153 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -458,7 +458,9 @@ int ata_tlink_add(struct ata_link *link) goto tlink_err; } - transport_add_device(dev); + error = transport_add_device(dev); + if (error) + goto tlink_transport_err; transport_configure_device(dev); ata_for_each_dev(ata_dev, link, ALL) { @@ -473,6 +475,7 @@ int ata_tlink_add(struct ata_link *link) ata_tdev_delete(ata_dev); } transport_remove_device(dev); + tlink_transport_err: device_del(dev); tlink_err: transport_destroy_device(dev); -- cgit v1.2.3 From 1ff36351309e3eadcff297480baf4785e726de9b Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 8 Nov 2022 21:40:04 +0800 Subject: ata: libata-transport: fix error handling in ata_tdev_add() In ata_tdev_add(), the return value of transport_add_device() is not checked. As a result, it causes null-ptr-deref while removing the module, because transport_remove_device() is called to remove the device that was not added. Unable to handle kernel NULL pointer dereference at virtual address 00000000000000d0 CPU: 13 PID: 13603 Comm: rmmod Kdump: loaded Tainted: G W 6.1.0-rc3+ #36 pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : device_del+0x48/0x3a0 lr : device_del+0x44/0x3a0 Call trace: device_del+0x48/0x3a0 attribute_container_class_device_del+0x28/0x40 transport_remove_classdev+0x60/0x7c attribute_container_device_trigger+0x118/0x120 transport_remove_device+0x20/0x30 ata_tdev_delete+0x24/0x50 [libata] ata_tlink_delete+0x40/0xa0 [libata] ata_tport_delete+0x2c/0x60 [libata] ata_port_detach+0x148/0x1b0 [libata] ata_pci_remove_one+0x50/0x80 [libata] ahci_remove_one+0x4c/0x8c [ahci] Fix this by checking and handling return value of transport_add_device() in ata_tdev_add(). In the error path, device_del() is called to delete the device which was added earlier in this function, and ata_tdev_free() is called to free ata_dev. Fixes: d9027470b886 ("[libata] Add ATA transport class") Signed-off-by: Yang Yingliang Signed-off-by: Damien Le Moal --- drivers/ata/libata-transport.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index aac9336e8153..e4fb9d1b9b39 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -713,7 +713,13 @@ static int ata_tdev_add(struct ata_device *ata_dev) return error; } - transport_add_device(dev); + error = transport_add_device(dev); + if (error) { + device_del(dev); + ata_tdev_free(ata_dev); + return error; + } + transport_configure_device(dev); return 0; } -- cgit v1.2.3 From da2549576b7be2b465908709dad50810a084cce4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 9 Nov 2022 17:35:19 +0200 Subject: drm/i915/reg: move masked field helpers to i915_reg_defs.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a more logical place for generic helpers. Cc: Lucas De Marchi Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/5161a0c6d98df206c6c4c1add3fc3f2f408020b1.1668008071.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 13 ------------- drivers/gpu/drm/i915/i915_reg_defs.h | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5a062ee46ed1..5955da91bec5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -171,19 +171,6 @@ INTEL_INFO(dev_priv)->display.cursor_offsets[PIPE_A] + \ DISPLAY_MMIO_BASE(dev_priv) + (reg)) -#define __MASKED_FIELD(mask, value) ((mask) << 16 | (value)) -#define _MASKED_FIELD(mask, value) ({ \ - if (__builtin_constant_p(mask)) \ - BUILD_BUG_ON_MSG(((mask) & 0xffff0000), "Incorrect mask"); \ - if (__builtin_constant_p(value)) \ - BUILD_BUG_ON_MSG((value) & 0xffff0000, "Incorrect value"); \ - if (__builtin_constant_p(mask) && __builtin_constant_p(value)) \ - BUILD_BUG_ON_MSG((value) & ~(mask), \ - "Incorrect value for mask"); \ - __MASKED_FIELD(mask, value); }) -#define _MASKED_BIT_ENABLE(a) ({ typeof(a) _a = (a); _MASKED_FIELD(_a, _a); }) -#define _MASKED_BIT_DISABLE(a) (_MASKED_FIELD((a), 0)) - #define GU_CNTL _MMIO(0x101010) #define LMEM_INIT REG_BIT(7) diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h b/drivers/gpu/drm/i915/i915_reg_defs.h index 8f486f77609f..7536f1b72778 100644 --- a/drivers/gpu/drm/i915/i915_reg_defs.h +++ b/drivers/gpu/drm/i915/i915_reg_defs.h @@ -98,6 +98,19 @@ */ #define REG_FIELD_GET64(__mask, __val) ((u64)FIELD_GET(__mask, __val)) +#define __MASKED_FIELD(mask, value) ((mask) << 16 | (value)) +#define _MASKED_FIELD(mask, value) ({ \ + if (__builtin_constant_p(mask)) \ + BUILD_BUG_ON_MSG(((mask) & 0xffff0000), "Incorrect mask"); \ + if (__builtin_constant_p(value)) \ + BUILD_BUG_ON_MSG((value) & 0xffff0000, "Incorrect value"); \ + if (__builtin_constant_p(mask) && __builtin_constant_p(value)) \ + BUILD_BUG_ON_MSG((value) & ~(mask), \ + "Incorrect value for mask"); \ + __MASKED_FIELD(mask, value); }) +#define _MASKED_BIT_ENABLE(a) ({ typeof(a) _a = (a); _MASKED_FIELD(_a, _a); }) +#define _MASKED_BIT_DISABLE(a) (_MASKED_FIELD((a), 0)) + typedef struct { u32 reg; } i915_reg_t; -- cgit v1.2.3 From 81e78b13bdf7829bed0ad1a1dfe51293a8f676f3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 9 Nov 2022 17:35:20 +0200 Subject: drm/i915/reg: move pick even and pick to reg defs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a more logical place for generic helpers. Cc: Lucas De Marchi Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/623327aee73a515300d99c8d65552ca92f3f0721.1668008071.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 15 --------------- drivers/gpu/drm/i915/i915_reg_defs.h | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5955da91bec5..f0e6da455d5b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -117,21 +117,6 @@ #define DISPLAY_MMIO_BASE(dev_priv) (INTEL_INFO(dev_priv)->display.mmio_offset) -/* - * Given the first two numbers __a and __b of arbitrarily many evenly spaced - * numbers, pick the 0-based __index'th value. - * - * Always prefer this over _PICK() if the numbers are evenly spaced. - */ -#define _PICK_EVEN(__index, __a, __b) ((__a) + (__index) * ((__b) - (__a))) - -/* - * Given the arbitrary numbers in varargs, pick the 0-based __index'th number. - * - * Always prefer _PICK_EVEN() over this if the numbers are evenly spaced. - */ -#define _PICK(__index, ...) (((const u32 []){ __VA_ARGS__ })[__index]) - /* * Named helper wrappers around _PICK_EVEN() and _PICK(). */ diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h b/drivers/gpu/drm/i915/i915_reg_defs.h index 7536f1b72778..344e5006650e 100644 --- a/drivers/gpu/drm/i915/i915_reg_defs.h +++ b/drivers/gpu/drm/i915/i915_reg_defs.h @@ -111,6 +111,21 @@ #define _MASKED_BIT_ENABLE(a) ({ typeof(a) _a = (a); _MASKED_FIELD(_a, _a); }) #define _MASKED_BIT_DISABLE(a) (_MASKED_FIELD((a), 0)) +/* + * Given the first two numbers __a and __b of arbitrarily many evenly spaced + * numbers, pick the 0-based __index'th value. + * + * Always prefer this over _PICK() if the numbers are evenly spaced. + */ +#define _PICK_EVEN(__index, __a, __b) ((__a) + (__index) * ((__b) - (__a))) + +/* + * Given the arbitrary numbers in varargs, pick the 0-based __index'th number. + * + * Always prefer _PICK_EVEN() over this if the numbers are evenly spaced. + */ +#define _PICK(__index, ...) (((const u32 []){ __VA_ARGS__ })[__index]) + typedef struct { u32 reg; } i915_reg_t; -- cgit v1.2.3 From e563531ace14c6920ff78794c1d9c35a03bc47b1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 9 Nov 2022 17:35:21 +0200 Subject: drm/i915: split out intel_display_reg_defs.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split out the display register helper macros to a separate file. For now, include it from i915_reg.h, but note that there are already files that don't need i915_reg.h, such as intel_audio.c. Cc: Lucas De Marchi Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/3af47193ff5219b6d2cfe353b752ec4bb44de4f1.1668008071.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi_regs.h | 2 +- drivers/gpu/drm/i915/display/intel_audio_regs.h | 2 +- .../gpu/drm/i915/display/intel_backlight_regs.h | 2 +- .../gpu/drm/i915/display/intel_display_reg_defs.h | 53 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_hdcp_regs.h | 2 +- drivers/gpu/drm/i915/display/intel_mg_phy_regs.h | 2 +- drivers/gpu/drm/i915/display/intel_snps_phy_regs.h | 2 +- drivers/gpu/drm/i915/display/vlv_dsi_regs.h | 2 +- drivers/gpu/drm/i915/gt/intel_gt_regs.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 42 +---------------- drivers/gpu/drm/i915/i915_reg_defs.h | 2 - 11 files changed, 62 insertions(+), 50 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_display_reg_defs.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/icl_dsi_regs.h b/drivers/gpu/drm/i915/display/icl_dsi_regs.h index f78f28b8dd94..d4845ac65acc 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi_regs.h +++ b/drivers/gpu/drm/i915/display/icl_dsi_regs.h @@ -6,7 +6,7 @@ #ifndef __ICL_DSI_REGS_H__ #define __ICL_DSI_REGS_H__ -#include "i915_reg_defs.h" +#include "intel_display_reg_defs.h" /* Gen11 DSI */ #define _MMIO_DSI(tc, dsi0, dsi1) _MMIO_TRANS((tc) - TRANSCODER_DSI_0, \ diff --git a/drivers/gpu/drm/i915/display/intel_audio_regs.h b/drivers/gpu/drm/i915/display/intel_audio_regs.h index 4f432c2eb543..616e7b1275c4 100644 --- a/drivers/gpu/drm/i915/display/intel_audio_regs.h +++ b/drivers/gpu/drm/i915/display/intel_audio_regs.h @@ -6,7 +6,7 @@ #ifndef __INTEL_AUDIO_REGS_H__ #define __INTEL_AUDIO_REGS_H__ -#include "i915_reg_defs.h" +#include "intel_display_reg_defs.h" #define G4X_AUD_CNTL_ST _MMIO(0x620B4) #define G4X_ELD_VALID REG_BIT(14) diff --git a/drivers/gpu/drm/i915/display/intel_backlight_regs.h b/drivers/gpu/drm/i915/display/intel_backlight_regs.h index 50c1210f6d5d..344eb8096bd2 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight_regs.h +++ b/drivers/gpu/drm/i915/display/intel_backlight_regs.h @@ -6,7 +6,7 @@ #ifndef __INTEL_BACKLIGHT_REGS_H__ #define __INTEL_BACKLIGHT_REGS_H__ -#include "i915_reg_defs.h" +#include "intel_display_reg_defs.h" #define _VLV_BLC_PWM_CTL2_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61250) #define _VLV_BLC_PWM_CTL2_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61350) diff --git a/drivers/gpu/drm/i915/display/intel_display_reg_defs.h b/drivers/gpu/drm/i915/display/intel_display_reg_defs.h new file mode 100644 index 000000000000..02605418ff08 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_reg_defs.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DISPLAY_REG_DEFS_H__ +#define __INTEL_DISPLAY_REG_DEFS_H__ + +#include "i915_reg_defs.h" + +#define DISPLAY_MMIO_BASE(dev_priv) (INTEL_INFO(dev_priv)->display.mmio_offset) + +#define VLV_DISPLAY_BASE 0x180000 + +/* + * Named helper wrappers around _PICK_EVEN() and _PICK(). + */ +#define _PIPE(pipe, a, b) _PICK_EVEN(pipe, a, b) +#define _PLANE(plane, a, b) _PICK_EVEN(plane, a, b) +#define _TRANS(tran, a, b) _PICK_EVEN(tran, a, b) +#define _PORT(port, a, b) _PICK_EVEN(port, a, b) +#define _PLL(pll, a, b) _PICK_EVEN(pll, a, b) +#define _PHY(phy, a, b) _PICK_EVEN(phy, a, b) + +#define _MMIO_PIPE(pipe, a, b) _MMIO(_PIPE(pipe, a, b)) +#define _MMIO_PLANE(plane, a, b) _MMIO(_PLANE(plane, a, b)) +#define _MMIO_TRANS(tran, a, b) _MMIO(_TRANS(tran, a, b)) +#define _MMIO_PORT(port, a, b) _MMIO(_PORT(port, a, b)) +#define _MMIO_PLL(pll, a, b) _MMIO(_PLL(pll, a, b)) +#define _MMIO_PHY(phy, a, b) _MMIO(_PHY(phy, a, b)) + +#define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__) + +#define _MMIO_PIPE3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c)) +#define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c)) +#define _MMIO_PHY3(phy, a, b, c) _MMIO(_PHY3(phy, a, b, c)) +#define _MMIO_PLL3(pll, ...) _MMIO(_PICK(pll, __VA_ARGS__)) + +/* + * Device info offset array based helpers for groups of registers with unevenly + * spaced base offsets. + */ +#define _MMIO_PIPE2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->display.pipe_offsets[(pipe)] - \ + INTEL_INFO(dev_priv)->display.pipe_offsets[PIPE_A] + \ + DISPLAY_MMIO_BASE(dev_priv) + (reg)) +#define _MMIO_TRANS2(tran, reg) _MMIO(INTEL_INFO(dev_priv)->display.trans_offsets[(tran)] - \ + INTEL_INFO(dev_priv)->display.trans_offsets[TRANSCODER_A] + \ + DISPLAY_MMIO_BASE(dev_priv) + (reg)) +#define _MMIO_CURSOR2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->display.cursor_offsets[(pipe)] - \ + INTEL_INFO(dev_priv)->display.cursor_offsets[PIPE_A] + \ + DISPLAY_MMIO_BASE(dev_priv) + (reg)) + +#endif /* __INTEL_DISPLAY_REG_DEFS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h index 2a3733e8966c..8023c85c7fa0 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h @@ -6,7 +6,7 @@ #ifndef __INTEL_HDCP_REGS_H__ #define __INTEL_HDCP_REGS_H__ -#include "i915_reg_defs.h" +#include "intel_display_reg_defs.h" /* HDCP Key Registers */ #define HDCP_KEY_CONF _MMIO(0x66c00) diff --git a/drivers/gpu/drm/i915/display/intel_mg_phy_regs.h b/drivers/gpu/drm/i915/display/intel_mg_phy_regs.h index 07978f8d5fb7..0e8248bce52d 100644 --- a/drivers/gpu/drm/i915/display/intel_mg_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_mg_phy_regs.h @@ -6,7 +6,7 @@ #ifndef __INTEL_MG_PHY_REGS__ #define __INTEL_MG_PHY_REGS__ -#include "i915_reg_defs.h" +#include "intel_display_reg_defs.h" #define MG_PHY_PORT_LN(ln, tc_port, ln0p1, ln0p2, ln1p1) \ _MMIO(_PORT(tc_port, ln0p1, ln0p2) + (ln) * ((ln1p1) - (ln0p1))) diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy_regs.h b/drivers/gpu/drm/i915/display/intel_snps_phy_regs.h index 0543465aaf14..a04d692169d4 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_snps_phy_regs.h @@ -6,7 +6,7 @@ #ifndef __INTEL_SNPS_PHY_REGS__ #define __INTEL_SNPS_PHY_REGS__ -#include "i915_reg_defs.h" +#include "intel_display_reg_defs.h" #define _SNPS_PHY_A_BASE 0x168000 #define _SNPS_PHY_B_BASE 0x169000 diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_regs.h b/drivers/gpu/drm/i915/display/vlv_dsi_regs.h index e065b8f2ee08..abbe427e462e 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_regs.h +++ b/drivers/gpu/drm/i915/display/vlv_dsi_regs.h @@ -6,7 +6,7 @@ #ifndef __VLV_DSI_REGS_H__ #define __VLV_DSI_REGS_H__ -#include "i915_reg_defs.h" +#include "intel_display_reg_defs.h" #define VLV_MIPI_BASE VLV_DISPLAY_BASE #define BXT_MIPI_BASE 0x60000 diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 94a060685922..fb0c61be350d 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -7,6 +7,7 @@ #define __INTEL_GT_REGS__ #include "i915_reg_defs.h" +#include "display/intel_display_reg_defs.h" /* VLV_DISPLAY_BASE */ /* RPM unit config (Gen8+) */ #define RPM_CONFIG0 _MMIO(0xd00) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f0e6da455d5b..93f3b7e702ab 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -26,6 +26,7 @@ #define _I915_REG_H_ #include "i915_reg_defs.h" +#include "display/intel_display_reg_defs.h" /** * DOC: The i915 register macro definition style guide @@ -115,47 +116,6 @@ * #define GEN8_BAR _MMIO(0xb888) */ -#define DISPLAY_MMIO_BASE(dev_priv) (INTEL_INFO(dev_priv)->display.mmio_offset) - -/* - * Named helper wrappers around _PICK_EVEN() and _PICK(). - */ -#define _PIPE(pipe, a, b) _PICK_EVEN(pipe, a, b) -#define _PLANE(plane, a, b) _PICK_EVEN(plane, a, b) -#define _TRANS(tran, a, b) _PICK_EVEN(tran, a, b) -#define _PORT(port, a, b) _PICK_EVEN(port, a, b) -#define _PLL(pll, a, b) _PICK_EVEN(pll, a, b) -#define _PHY(phy, a, b) _PICK_EVEN(phy, a, b) - -#define _MMIO_PIPE(pipe, a, b) _MMIO(_PIPE(pipe, a, b)) -#define _MMIO_PLANE(plane, a, b) _MMIO(_PLANE(plane, a, b)) -#define _MMIO_TRANS(tran, a, b) _MMIO(_TRANS(tran, a, b)) -#define _MMIO_PORT(port, a, b) _MMIO(_PORT(port, a, b)) -#define _MMIO_PLL(pll, a, b) _MMIO(_PLL(pll, a, b)) -#define _MMIO_PHY(phy, a, b) _MMIO(_PHY(phy, a, b)) - -#define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__) - -#define _MMIO_PIPE3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c)) -#define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c)) -#define _MMIO_PHY3(phy, a, b, c) _MMIO(_PHY3(phy, a, b, c)) -#define _MMIO_PLL3(pll, ...) _MMIO(_PICK(pll, __VA_ARGS__)) - - -/* - * Device info offset array based helpers for groups of registers with unevenly - * spaced base offsets. - */ -#define _MMIO_PIPE2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->display.pipe_offsets[(pipe)] - \ - INTEL_INFO(dev_priv)->display.pipe_offsets[PIPE_A] + \ - DISPLAY_MMIO_BASE(dev_priv) + (reg)) -#define _MMIO_TRANS2(tran, reg) _MMIO(INTEL_INFO(dev_priv)->display.trans_offsets[(tran)] - \ - INTEL_INFO(dev_priv)->display.trans_offsets[TRANSCODER_A] + \ - DISPLAY_MMIO_BASE(dev_priv) + (reg)) -#define _MMIO_CURSOR2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->display.cursor_offsets[(pipe)] - \ - INTEL_INFO(dev_priv)->display.cursor_offsets[PIPE_A] + \ - DISPLAY_MMIO_BASE(dev_priv) + (reg)) - #define GU_CNTL _MMIO(0x101010) #define LMEM_INIT REG_BIT(7) diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h b/drivers/gpu/drm/i915/i915_reg_defs.h index 344e5006650e..1564f2c72c2a 100644 --- a/drivers/gpu/drm/i915/i915_reg_defs.h +++ b/drivers/gpu/drm/i915/i915_reg_defs.h @@ -149,6 +149,4 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) return !i915_mmio_reg_equal(reg, INVALID_MMIO_REG); } -#define VLV_DISPLAY_BASE 0x180000 - #endif /* __I915_REG_DEFS__ */ -- cgit v1.2.3 From f3a72878a3de720661b7ed0d6b7f7c506ddb8a52 Mon Sep 17 00:00:00 2001 From: Jaco Coetzee Date: Wed, 9 Nov 2022 15:27:57 -0500 Subject: nfp: change eeprom length to max length enumerators Extend the size of QSFP EEPROM for types SSF8436 and SFF8636 from 256 to 640 bytes in order to expose all the EEPROM pages by ethtool. For SFF-8636 and SFF-8436 specifications, the driver exposes 256 bytes of EEPROM data for ethtool's get_module_eeprom() callback, resulting in "netlink error: Invalid argument" when an EEPROM read with an offset larger than 256 bytes is attempted. Changing the length enumerators to the _MAX_LEN variants exposes all 640 bytes of the EEPROM allowing upper pages 1, 2 and 3 to be read. Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command") Signed-off-by: Jaco Coetzee Reviewed-by: Louis Peens Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 22a5d2419084..1775997f9c69 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -1477,15 +1477,15 @@ nfp_port_get_module_info(struct net_device *netdev, if (data < 0x3) { modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; } else { modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; } break; case NFP_INTERFACE_QSFP28: modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; break; default: netdev_err(netdev, "Unsupported module 0x%x detected\n", -- cgit v1.2.3 From 801543b2593b04eef974a73d3ea03e7efbd5ffae Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 9 Nov 2022 17:35:22 +0200 Subject: drm/i915: stop including i915_irq.h from i915_trace.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out many of the files that need i915_reg.h get it implicitly via {display/intel_de.h, gt/intel_context.h} -> i915_trace.h -> i915_irq.h -> i915_reg.h. Since i915_trace.h doesn't actually need i915_irq.h, makes sense to drop it, but that requires adding quite a few new includes all over the place. Prefer including i915_reg.h where needed instead of adding another implicit include, because eventually we'll want to split up i915_reg.h and only include the specific registers at each place. Also some places actually needed i915_irq.h too. Cc: Lucas De Marchi Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/6e78a2e0ac1bffaf5af3b5ccc21dff05e6518cef.1668008071.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/g4x_dp.c | 1 + drivers/gpu/drm/i915/display/g4x_hdmi.c | 1 + drivers/gpu/drm/i915/display/i9xx_plane.c | 4 +++- drivers/gpu/drm/i915/display/icl_dsi.c | 1 + drivers/gpu/drm/i915/display/intel_backlight.c | 1 + drivers/gpu/drm/i915/display/intel_cdclk.c | 1 + drivers/gpu/drm/i915/display/intel_color.c | 1 + drivers/gpu/drm/i915/display/intel_combo_phy.c | 1 + drivers/gpu/drm/i915/display/intel_crt.c | 2 ++ drivers/gpu/drm/i915/display/intel_cursor.c | 3 ++- drivers/gpu/drm/i915/display/intel_ddi.c | 1 + drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 ++ drivers/gpu/drm/i915/display/intel_dp.c | 1 + drivers/gpu/drm/i915/display/intel_dp_aux.c | 1 + drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 1 + drivers/gpu/drm/i915/display/intel_dpio_phy.c | 1 + drivers/gpu/drm/i915/display/intel_dpll.c | 1 + drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + drivers/gpu/drm/i915/display/intel_drrs.c | 1 + drivers/gpu/drm/i915/display/intel_dsb.c | 1 + drivers/gpu/drm/i915/display/intel_dvo.c | 1 + drivers/gpu/drm/i915/display/intel_fdi.c | 1 + drivers/gpu/drm/i915/display/intel_gmbus.c | 2 ++ drivers/gpu/drm/i915/display/intel_hdmi.c | 1 + drivers/gpu/drm/i915/display/intel_lpe_audio.c | 2 ++ drivers/gpu/drm/i915/display/intel_lspcon.c | 1 + drivers/gpu/drm/i915/display/intel_lvds.c | 1 + drivers/gpu/drm/i915/display/intel_modeset_setup.c | 1 + drivers/gpu/drm/i915/display/intel_panel.c | 1 + drivers/gpu/drm/i915/display/intel_pch_display.c | 1 + drivers/gpu/drm/i915/display/intel_pch_refclk.c | 1 + drivers/gpu/drm/i915/display/intel_pipe_crc.c | 2 ++ drivers/gpu/drm/i915/display/intel_pps.c | 1 + drivers/gpu/drm/i915/display/intel_psr.c | 1 + drivers/gpu/drm/i915/display/intel_sdvo.c | 1 + drivers/gpu/drm/i915/display/intel_snps_phy.c | 1 + drivers/gpu/drm/i915/display/intel_sprite.c | 1 + drivers/gpu/drm/i915/display/intel_tv.c | 2 ++ drivers/gpu/drm/i915/display/intel_vdsc.c | 1 + drivers/gpu/drm/i915/display/intel_vga.c | 1 + drivers/gpu/drm/i915/display/intel_vrr.c | 1 + drivers/gpu/drm/i915/display/skl_scaler.c | 2 ++ drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 ++ drivers/gpu/drm/i915/display/vlv_dsi.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 1 + drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 1 + drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 ++ drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 1 + drivers/gpu/drm/i915/gt/intel_gt.c | 1 + drivers/gpu/drm/i915/gt/intel_gt_pm.c | 1 + drivers/gpu/drm/i915/gt/intel_gtt.c | 1 + drivers/gpu/drm/i915/gt/intel_ring_submission.c | 2 ++ drivers/gpu/drm/i915/gt/intel_workarounds.c | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 1 + drivers/gpu/drm/i915/gvt/cmd_parser.c | 1 + drivers/gpu/drm/i915/gvt/mmio_context.c | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 1 + drivers/gpu/drm/i915/i915_perf.c | 1 + drivers/gpu/drm/i915/i915_trace.h | 1 - drivers/gpu/drm/i915/intel_device_info.c | 3 ++- drivers/gpu/drm/i915/intel_uncore.c | 1 + 63 files changed, 76 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index e3e3d27ffb53..3593938dcd87 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -8,6 +8,7 @@ #include #include "g4x_dp.h" +#include "i915_reg.h" #include "intel_audio.h" #include "intel_backlight.h" #include "intel_connector.h" diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 8aadf96fa5e9..75ba24c9785f 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -6,6 +6,7 @@ */ #include "g4x_hdmi.h" +#include "i915_reg.h" #include "intel_audio.h" #include "intel_connector.h" #include "intel_crtc.h" diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 5afbe3e98ee8..ecaeb7dc196b 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -8,6 +8,9 @@ #include #include +#include "i915_irq.h" +#include "i915_reg.h" +#include "i9xx_plane.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_de.h" @@ -15,7 +18,6 @@ #include "intel_fb.h" #include "intel_fbc.h" #include "intel_sprite.h" -#include "i9xx_plane.h" /* Primary plane formats for gen <= 3 */ static const u32 i8xx_primary_formats[] = { diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index e05e7cd6c412..d16b30a2dded 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -29,6 +29,7 @@ #include #include +#include "i915_reg.h" #include "icl_dsi.h" #include "icl_dsi_regs.h" #include "intel_atomic.h" diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 11a1342d6d37..0438071f58cf 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -8,6 +8,7 @@ #include #include +#include "i915_reg.h" #include "intel_backlight.h" #include "intel_backlight_regs.h" #include "intel_connector.h" diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 8a9031012d74..b74e36d76013 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -24,6 +24,7 @@ #include #include "hsw_ips.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_audio.h" diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 93509cf7bbcc..12f5b976c795 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -22,6 +22,7 @@ * */ +#include "i915_reg.h" #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index 71d7aece1dc6..8b870b2dd4f9 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -3,6 +3,7 @@ * Copyright © 2018 Intel Corporation */ +#include "i915_reg.h" #include "intel_combo_phy.h" #include "intel_combo_phy_regs.h" #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 94d0a5e1dd03..797ad9489f7e 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -34,6 +34,8 @@ #include #include "i915_drv.h" +#include "i915_irq.h" +#include "i915_reg.h" #include "intel_connector.h" #include "intel_crt.h" #include "intel_crtc.h" diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 96422c98656a..d190fa0d393b 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -10,12 +10,13 @@ #include #include +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_cursor.h" #include "intel_de.h" -#include "intel_display_types.h" #include "intel_display.h" +#include "intel_display_types.h" #include "intel_fb.h" #include "intel_fb_pin.h" #include "intel_frontbuffer.h" diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index e95bde5cf060..477dd9b72ea3 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -31,6 +31,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "intel_audio.h" #include "intel_audio_regs.h" #include "intel_backlight.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c4d31db935fe..1f642ab42268 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -76,6 +76,7 @@ #include "g4x_hdmi.h" #include "hsw_ips.h" #include "i915_drv.h" +#include "i915_reg.h" #include "i915_utils.h" #include "icl_dsi.h" #include "intel_acpi.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index cfc056a05bbf..7bcd90384a46 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -9,6 +9,8 @@ #include #include "i915_debugfs.h" +#include "i915_irq.h" +#include "i915_reg.h" #include "intel_de.h" #include "intel_display_debugfs.h" #include "intel_display_power.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 7400d6b4c587..914161d7d122 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -46,6 +46,7 @@ #include "g4x_dp.h" #include "i915_debugfs.h" #include "i915_drv.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_audio.h" #include "intel_backlight.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index 48c375c65a41..664bebdecea7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -4,6 +4,7 @@ */ #include "i915_drv.h" +#include "i915_reg.h" #include "i915_trace.h" #include "intel_display_types.h" #include "intel_dp_aux.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 35360dd543ac..e0c177161407 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -11,6 +11,7 @@ #include #include +#include "i915_reg.h" #include "intel_ddi.h" #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index cd4e61026d98..4077a979a924 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -29,6 +29,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_audio.h" #include "intel_connector.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 6fc5b9e58152..7eb7440b3180 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include "i915_reg.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index fdc6fa4f2ed9..c236aafe9be0 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -6,6 +6,7 @@ #include #include +#include "i915_reg.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 7c6c094a0a01..79579dca3c7e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -23,6 +23,7 @@ #include +#include "i915_reg.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_dkl_phy.h" diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index e27408efaae2..5b9e44443814 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -4,6 +4,7 @@ */ #include "i915_drv.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index fc9c3e41c333..1e1c6107d51b 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -7,6 +7,7 @@ #include "gem/i915_gem_internal.h" #include "i915_drv.h" +#include "i915_reg.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_dsb.h" diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 595087288922..c86f9890754d 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -32,6 +32,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "intel_connector.h" #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 7f47e5c85c81..063f1da4f229 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -5,6 +5,7 @@ #include +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_crtc.h" #include "intel_ddi.h" diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 860e0f8b6b19..a5840a28a69d 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -34,6 +34,8 @@ #include #include "i915_drv.h" +#include "i915_irq.h" +#include "i915_reg.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_gmbus.h" diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 93519fb23d9d..28221e12c743 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -42,6 +42,7 @@ #include "i915_debugfs.h" #include "i915_drv.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_connector.h" #include "intel_ddi.h" diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index 6a7ac60e4f76..a482e94ba078 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -71,6 +71,8 @@ #include #include "i915_drv.h" +#include "i915_irq.h" +#include "i915_reg.h" #include "intel_de.h" #include "intel_lpe_audio.h" #include "intel_pci_config.h" diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 15d59de8810e..9ff1c0b223ad 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -28,6 +28,7 @@ #include #include +#include "i915_reg.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_dp.h" diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 246787bbf5ef..7bf1bdfd03ec 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -39,6 +39,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_backlight.h" #include "intel_connector.h" diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 9d8ca230be39..96395bfbd41d 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -10,6 +10,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_bw.h" #include "intel_color.h" diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 69ce77711b7c..1640726bfbf6 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -31,6 +31,7 @@ #include #include +#include "i915_reg.h" #include "intel_backlight.h" #include "intel_connector.h" #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 837152dca063..cecc0d007cf3 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -4,6 +4,7 @@ */ #include "g4x_dp.h" +#include "i915_reg.h" #include "intel_crt.h" #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index a66097cdc1e0..08a94365b7d1 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -3,6 +3,7 @@ * Copyright © 2021 Intel Corporation */ +#include "i915_reg.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_panel.h" diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index 1c74388c60d7..673454fbf784 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -29,6 +29,8 @@ #include #include +#include "i915_irq.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 22f5e08d396b..81ee7f3aadf6 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -5,6 +5,7 @@ #include "g4x_dp.h" #include "i915_drv.h" +#include "i915_reg.h" #include "intel_de.h" #include "intel_display_power_well.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index a75b37851504..5b678916e6db 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -27,6 +27,7 @@ #include "display/intel_dp.h" #include "i915_drv.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_crtc.h" #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 48b7b1aa37b2..329b9d9af667 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -37,6 +37,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "intel_atomic.h" #include "intel_connector.h" #include "intel_crtc.h" diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 937cefd6f78f..c799e891f8b5 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -5,6 +5,7 @@ #include +#include "i915_reg.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 7649c50b5445..e6b4d24b9cd0 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -42,6 +42,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "i915_vgpu.h" #include "i9xx_plane.h" #include "intel_atomic_plane.h" diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index cf7d5c1ab406..4d2101ca1692 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -35,6 +35,8 @@ #include #include "i915_drv.h" +#include "i915_reg.h" +#include "i915_irq.h" #include "intel_connector.h" #include "intel_crtc.h" #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 269f9792390d..9d3b77b41b5c 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -10,6 +10,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index b5d058404c14..a69bfcac9a94 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -10,6 +10,7 @@ #include