From: Changcheng Deng deng.changcheng@zte.com.cn
[ Upstream commit c1b6ad9a902539f9c037b6b3c35cb134c5724022 ]
do_div() does a 64-by-32 division. Here the divisor is an unsigned long which on some platforms is 64 bit wide. So use div64_ul instead of do_div to avoid a possible truncation.
Reported-by: Zeal Robot zealci@zte.com.cn Signed-off-by: Changcheng Deng deng.changcheng@zte.com.cn Reviewed-by: Abel Vesa abel.vesa@nxp.com Link: https://lore.kernel.org/r/20211118080634.165275-1-deng.changcheng@zte.com.cn Signed-off-by: Abel Vesa abel.vesa@nxp.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/imx/clk-pllv3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 20ee9611ba6e3..eea32f87c60aa 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -247,7 +247,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, div = rate / parent_rate; temp64 = (u64) (rate - div * parent_rate); temp64 *= mfd; - do_div(temp64, parent_rate); + temp64 = div64_ul(temp64, parent_rate); mfn = temp64;
temp64 = (u64)parent_rate; @@ -277,7 +277,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, div = rate / parent_rate; temp64 = (u64) (rate - div * parent_rate); temp64 *= mfd; - do_div(temp64, parent_rate); + temp64 = div64_ul(temp64, parent_rate); mfn = temp64;
val = readl_relaxed(pll->base); @@ -334,7 +334,7 @@ static struct clk_pllv3_vf610_mf clk_pllv3_vf610_rate_to_mf( /* rate = parent_rate * (mfi + mfn/mfd) */ temp64 = rate - parent_rate * mf.mfi; temp64 *= mf.mfd; - do_div(temp64, parent_rate); + temp64 = div64_ul(temp64, parent_rate); mf.mfn = temp64; }
From: Sam Protsenko semen.protsenko@linaro.org
[ Upstream commit bcda841f9bf2cddcf2f000cba96f2e27f6f2bdbf ]
Some clocks must be registered before init calls. For example MCT clock (from CMU_PERI) is needed for MCT timer driver, which is registered with TIMER_OF_DECLARE(). By the time we get to core_initcall() used for clk-exynos850 platform driver init, it's already too late. Inability to get "mct" clock in MCT driver leads to kernel panic, as functions registered with *_OF_DECLARE() can't do deferred calls. MCT timer driver can't be fixed either, as it's acting as a clock source and it's essential to register it in start_kernel() -> time_init().
Let's register CMU_PERI clocks early, using CLK_OF_DECLARE(). CMU_TOP generates clocks needed for CMU_PERI, but it's already registered early.
While at it, let's cleanup the code a bit, by extracting everything related to CMU initialization and registration to the separate function.
Similar issue was discussed at [1] and addressed in commit 1f7db7bbf031 ("clk: renesas: cpg-mssr: Add early clock support"), as well as in drivers/clk/mediatek/clk-mt2712.c.
[1] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20180829132954....
Signed-off-by: Sam Protsenko semen.protsenko@linaro.org Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Reviewed-by: Krzysztof Kozlowski krzysztof.kozlowski@canonical.com Link: https://lore.kernel.org/r/20211122144206.23134-1-semen.protsenko@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/samsung/clk-exynos850.c | 70 ++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 21 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c index 2294989e244c5..79cce8ba88831 100644 --- a/drivers/clk/samsung/clk-exynos850.c +++ b/drivers/clk/samsung/clk-exynos850.c @@ -60,6 +60,43 @@ static void __init exynos850_init_clocks(struct device_node *np, iounmap(reg_base); }
+/** + * exynos850_register_cmu - Register specified Exynos850 CMU domain + * @dev: Device object; may be NULL if this function is not being + * called from platform driver probe function + * @np: CMU device tree node + * @cmu: CMU data + * + * Register specified CMU domain, which includes next steps: + * + * 1. Enable parent clock of @cmu CMU + * 2. Set initial registers configuration for @cmu CMU clocks + * 3. Register @cmu CMU clocks using Samsung clock framework API + */ +static void __init exynos850_register_cmu(struct device *dev, + struct device_node *np, const struct samsung_cmu_info *cmu) +{ + /* Keep CMU parent clock running (needed for CMU registers access) */ + if (cmu->clk_name) { + struct clk *parent_clk; + + if (dev) + parent_clk = clk_get(dev, cmu->clk_name); + else + parent_clk = of_clk_get_by_name(np, cmu->clk_name); + + if (IS_ERR(parent_clk)) { + pr_err("%s: could not find bus clock %s; err = %ld\n", + __func__, cmu->clk_name, PTR_ERR(parent_clk)); + } else { + clk_prepare_enable(parent_clk); + } + } + + exynos850_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs); + samsung_cmu_register_one(np, cmu); +} + /* ---- CMU_TOP ------------------------------------------------------------- */
/* Register Offset definitions for CMU_TOP (0x120e0000) */ @@ -347,10 +384,10 @@ static const struct samsung_cmu_info top_cmu_info __initconst = {
static void __init exynos850_cmu_top_init(struct device_node *np) { - exynos850_init_clocks(np, top_clk_regs, ARRAY_SIZE(top_clk_regs)); - samsung_cmu_register_one(np, &top_cmu_info); + exynos850_register_cmu(NULL, np, &top_cmu_info); }
+/* Register CMU_TOP early, as it's a dependency for other early domains */ CLK_OF_DECLARE(exynos850_cmu_top, "samsung,exynos850-cmu-top", exynos850_cmu_top_init);
@@ -615,6 +652,15 @@ static const struct samsung_cmu_info peri_cmu_info __initconst = { .clk_name = "dout_peri_bus", };
+static void __init exynos850_cmu_peri_init(struct device_node *np) +{ + exynos850_register_cmu(NULL, np, &peri_cmu_info); +} + +/* Register CMU_PERI early, as it's needed for MCT timer */ +CLK_OF_DECLARE(exynos850_cmu_peri, "samsung,exynos850-cmu-peri", + exynos850_cmu_peri_init); + /* ---- CMU_CORE ------------------------------------------------------------ */
/* Register Offset definitions for CMU_CORE (0x12000000) */ @@ -779,24 +825,9 @@ static int __init exynos850_cmu_probe(struct platform_device *pdev) { const struct samsung_cmu_info *info; struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node;
info = of_device_get_match_data(dev); - exynos850_init_clocks(np, info->clk_regs, info->nr_clk_regs); - samsung_cmu_register_one(np, info); - - /* Keep bus clock running, so it's possible to access CMU registers */ - if (info->clk_name) { - struct clk *bus_clk; - - bus_clk = clk_get(dev, info->clk_name); - if (IS_ERR(bus_clk)) { - pr_err("%s: could not find bus clock %s; err = %ld\n", - __func__, info->clk_name, PTR_ERR(bus_clk)); - } else { - clk_prepare_enable(bus_clk); - } - } + exynos850_register_cmu(dev, dev->of_node, info);
return 0; } @@ -806,9 +837,6 @@ static const struct of_device_id exynos850_cmu_of_match[] = { { .compatible = "samsung,exynos850-cmu-hsi", .data = &hsi_cmu_info, - }, { - .compatible = "samsung,exynos850-cmu-peri", - .data = &peri_cmu_info, }, { .compatible = "samsung,exynos850-cmu-core", .data = &core_cmu_info,
On 17/01/2022 17:58, Sasha Levin wrote:
From: Sam Protsenko semen.protsenko@linaro.org
[ Upstream commit bcda841f9bf2cddcf2f000cba96f2e27f6f2bdbf ]
Some clocks must be registered before init calls. For example MCT clock (from CMU_PERI) is needed for MCT timer driver, which is registered with TIMER_OF_DECLARE(). By the time we get to core_initcall() used for clk-exynos850 platform driver init, it's already too late. Inability to get "mct" clock in MCT driver leads to kernel panic, as functions registered with *_OF_DECLARE() can't do deferred calls. MCT timer driver can't be fixed either, as it's acting as a clock source and it's essential to register it in start_kernel() -> time_init().
Let's register CMU_PERI clocks early, using CLK_OF_DECLARE(). CMU_TOP generates clocks needed for CMU_PERI, but it's already registered early.
While at it, let's cleanup the code a bit, by extracting everything related to CMU initialization and registration to the separate function.
Similar issue was discussed at [1] and addressed in commit 1f7db7bbf031 ("clk: renesas: cpg-mssr: Add early clock support"), as well as in drivers/clk/mediatek/clk-mt2712.c.
[1] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20180829132954....
Signed-off-by: Sam Protsenko semen.protsenko@linaro.org Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Reviewed-by: Krzysztof Kozlowski krzysztof.kozlowski@canonical.com Link: https://lore.kernel.org/r/20211122144206.23134-1-semen.protsenko@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org
drivers/clk/samsung/clk-exynos850.c | 70 ++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 21 deletions(-)
I propose to skip this one.
Backporting it to v5.16 does not hurt but also does not bring any benefits for the upstream kernel users. There is no support for mentioned Exynos850 in v5.16.
It could have only meaning for some downstream, out-of-tree kernels which apply Exynos850 support on top of v5.16, but then they can just take this patch as well.
Best regards, Krzysztof
On Mon, 17 Jan 2022 at 19:11, Krzysztof Kozlowski krzysztof.kozlowski@canonical.com wrote:
On 17/01/2022 17:58, Sasha Levin wrote:
From: Sam Protsenko semen.protsenko@linaro.org
[ Upstream commit bcda841f9bf2cddcf2f000cba96f2e27f6f2bdbf ]
Some clocks must be registered before init calls. For example MCT clock (from CMU_PERI) is needed for MCT timer driver, which is registered with TIMER_OF_DECLARE(). By the time we get to core_initcall() used for clk-exynos850 platform driver init, it's already too late. Inability to get "mct" clock in MCT driver leads to kernel panic, as functions registered with *_OF_DECLARE() can't do deferred calls. MCT timer driver can't be fixed either, as it's acting as a clock source and it's essential to register it in start_kernel() -> time_init().
Let's register CMU_PERI clocks early, using CLK_OF_DECLARE(). CMU_TOP generates clocks needed for CMU_PERI, but it's already registered early.
While at it, let's cleanup the code a bit, by extracting everything related to CMU initialization and registration to the separate function.
Similar issue was discussed at [1] and addressed in commit 1f7db7bbf031 ("clk: renesas: cpg-mssr: Add early clock support"), as well as in drivers/clk/mediatek/clk-mt2712.c.
[1] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20180829132954....
Signed-off-by: Sam Protsenko semen.protsenko@linaro.org Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Reviewed-by: Krzysztof Kozlowski krzysztof.kozlowski@canonical.com Link: https://lore.kernel.org/r/20211122144206.23134-1-semen.protsenko@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org
drivers/clk/samsung/clk-exynos850.c | 70 ++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 21 deletions(-)
I propose to skip this one.
Backporting it to v5.16 does not hurt but also does not bring any benefits for the upstream kernel users. There is no support for mentioned Exynos850 in v5.16.
It could have only meaning for some downstream, out-of-tree kernels which apply Exynos850 support on top of v5.16, but then they can just take this patch as well.
Agreed. DTS patches will be merged only in v5.17, hopefully. Till that time the whole clock driver is floating with no users. That's historical thing -- I didn't have "Ack" to submit board dts at the time, and SoC dts couldn't be applied without users (board dts). So I focused on driver work, isolated. Not much sense to backport something without having real users.
Best regards, Krzysztof
On Mon, Jan 17, 2022 at 09:18:43PM +0200, Sam Protsenko wrote:
On Mon, 17 Jan 2022 at 19:11, Krzysztof Kozlowski krzysztof.kozlowski@canonical.com wrote:
On 17/01/2022 17:58, Sasha Levin wrote:
From: Sam Protsenko semen.protsenko@linaro.org
[ Upstream commit bcda841f9bf2cddcf2f000cba96f2e27f6f2bdbf ]
Some clocks must be registered before init calls. For example MCT clock (from CMU_PERI) is needed for MCT timer driver, which is registered with TIMER_OF_DECLARE(). By the time we get to core_initcall() used for clk-exynos850 platform driver init, it's already too late. Inability to get "mct" clock in MCT driver leads to kernel panic, as functions registered with *_OF_DECLARE() can't do deferred calls. MCT timer driver can't be fixed either, as it's acting as a clock source and it's essential to register it in start_kernel() -> time_init().
Let's register CMU_PERI clocks early, using CLK_OF_DECLARE(). CMU_TOP generates clocks needed for CMU_PERI, but it's already registered early.
While at it, let's cleanup the code a bit, by extracting everything related to CMU initialization and registration to the separate function.
Similar issue was discussed at [1] and addressed in commit 1f7db7bbf031 ("clk: renesas: cpg-mssr: Add early clock support"), as well as in drivers/clk/mediatek/clk-mt2712.c.
[1] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20180829132954....
Signed-off-by: Sam Protsenko semen.protsenko@linaro.org Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Reviewed-by: Krzysztof Kozlowski krzysztof.kozlowski@canonical.com Link: https://lore.kernel.org/r/20211122144206.23134-1-semen.protsenko@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org
drivers/clk/samsung/clk-exynos850.c | 70 ++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 21 deletions(-)
I propose to skip this one.
Backporting it to v5.16 does not hurt but also does not bring any benefits for the upstream kernel users. There is no support for mentioned Exynos850 in v5.16.
It could have only meaning for some downstream, out-of-tree kernels which apply Exynos850 support on top of v5.16, but then they can just take this patch as well.
Agreed. DTS patches will be merged only in v5.17, hopefully. Till that time the whole clock driver is floating with no users. That's historical thing -- I didn't have "Ack" to submit board dts at the time, and SoC dts couldn't be applied without users (board dts). So I focused on driver work, isolated. Not much sense to backport something without having real users.
Dropped, thanks!
From: Julia Lawall Julia.Lawall@lip6.fr
[ Upstream commit f6e82647ff71d427d4148964b71f239fba9d7937 ]
for_each_compatible_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put.
A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr):
// <smpl> @@ expression e; local idexpression n; @@
@@ local idexpression n; expression e; @@
for_each_compatible_node(n,...) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // </smpl>
Signed-off-by: Julia Lawall Julia.Lawall@lip6.fr Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/1448051604-25256-2-git-send-email-Julia.Lawall@lip... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c index 15396333a90bd..a4b020e4b6af0 100644 --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c @@ -214,6 +214,7 @@ void hlwd_pic_probe(void) irq_set_chained_handler(cascade_virq, hlwd_pic_irq_cascade); hlwd_irq_host = host; + of_node_put(np); break; } }
From: Julia Lawall Julia.Lawall@lip6.fr
[ Upstream commit 7d405a939ca960162eb30c1475759cb2fdf38f8c ]
for_each_compatible_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put.
A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr):
// <smpl> @@ local idexpression n; expression e; @@
for_each_compatible_node(n,...) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // </smpl>
Signed-off-by: Julia Lawall Julia.Lawall@lip6.fr Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/1448051604-25256-4-git-send-email-Julia.Lawall@lip... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/platforms/powernv/opal-lpc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c index 1e5d51db40f84..5390c888db162 100644 --- a/arch/powerpc/platforms/powernv/opal-lpc.c +++ b/arch/powerpc/platforms/powernv/opal-lpc.c @@ -396,6 +396,7 @@ void __init opal_lpc_init(void) if (!of_get_property(np, "primary", NULL)) continue; opal_lpc_chip_id = of_get_ibm_chip_id(np); + of_node_put(np); break; } if (opal_lpc_chip_id < 0)
From: Julia Lawall Julia.Lawall@lip6.fr
[ Upstream commit a841fd009e51c8c0a8f07c942e9ab6bb48da8858 ]
for_each_node_by_name performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put.
A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr):
// <smpl> @@ expression e,e1; local idexpression n; @@
for_each_node_by_name(n, e1) { ... when != of_node_put(n) when != e = n ( return n; | + of_node_put(n); ? return ...; ) ... } // </smpl>
Signed-off-by: Julia Lawall Julia.Lawall@lip6.fr Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/1448051604-25256-7-git-send-email-Julia.Lawall@lip... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/platforms/cell/iommu.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index fa08699aedeb8..d32f24de84798 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -977,6 +977,7 @@ static int __init cell_iommu_fixed_mapping_init(void) if (hbase < dbase || (hend > (dbase + dsize))) { pr_debug("iommu: hash window doesn't fit in" "real DMA window\n"); + of_node_put(np); return -1; } }
From: Julia Lawall Julia.Lawall@lip6.fr
[ Upstream commit a1d2b210ffa52d60acabbf7b6af3ef7e1e69cda0 ]
for_each_node_by_type performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put.
A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr):
// <smpl> @@ local idexpression n; expression e; @@
for_each_node_by_type(n,...) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // </smpl>
Signed-off-by: Julia Lawall Julia.Lawall@lip6.fr Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/1448051604-25256-6-git-send-email-Julia.Lawall@lip... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/btext.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 803c2a45b22ac..1cffb5e7c38d6 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -241,8 +241,10 @@ int __init btext_find_display(int allow_nonstdout) rc = btext_initialize(np); printk("result: %d\n", rc); } - if (rc == 0) + if (rc == 0) { + of_node_put(np); break; + } } return rc; }
From: Nicholas Piggin npiggin@gmail.com
[ Upstream commit 5dad4ba68a2483fc80d70b9dc90bbe16e1f27263 ]
It is possible for all CPUs to miss the pending cpumask becoming clear, and then nobody resetting it, which will cause the lockup detector to stop working. It will eventually expire, but watchdog_smp_panic will avoid doing anything if the pending mask is clear and it will never be reset.
Order the cpumask clear vs the subsequent test to close this race.
Add an extra check for an empty pending mask when the watchdog fires and finds its bit still clear, to try to catch any other possible races or bugs here and keep the watchdog working. The extra test in arch_touch_nmi_watchdog is required to prevent the new warning from firing off.
Signed-off-by: Nicholas Piggin npiggin@gmail.com Reviewed-by: Laurent Dufour ldufour@linux.ibm.com Debugged-by: Laurent Dufour ldufour@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20211110025056.2084347-2-npiggin@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/watchdog.c | 41 +++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c index 3fa6d240bade2..ad94a2c6b7337 100644 --- a/arch/powerpc/kernel/watchdog.c +++ b/arch/powerpc/kernel/watchdog.c @@ -135,6 +135,10 @@ static void set_cpumask_stuck(const struct cpumask *cpumask, u64 tb) { cpumask_or(&wd_smp_cpus_stuck, &wd_smp_cpus_stuck, cpumask); cpumask_andnot(&wd_smp_cpus_pending, &wd_smp_cpus_pending, cpumask); + /* + * See wd_smp_clear_cpu_pending() + */ + smp_mb(); if (cpumask_empty(&wd_smp_cpus_pending)) { wd_smp_last_reset_tb = tb; cpumask_andnot(&wd_smp_cpus_pending, @@ -221,13 +225,44 @@ static void wd_smp_clear_cpu_pending(int cpu, u64 tb)
cpumask_clear_cpu(cpu, &wd_smp_cpus_stuck); wd_smp_unlock(&flags); + } else { + /* + * The last CPU to clear pending should have reset the + * watchdog so we generally should not find it empty + * here if our CPU was clear. However it could happen + * due to a rare race with another CPU taking the + * last CPU out of the mask concurrently. + * + * We can't add a warning for it. But just in case + * there is a problem with the watchdog that is causing + * the mask to not be reset, try to kick it along here. + */ + if (unlikely(cpumask_empty(&wd_smp_cpus_pending))) + goto none_pending; } return; } + cpumask_clear_cpu(cpu, &wd_smp_cpus_pending); + + /* + * Order the store to clear pending with the load(s) to check all + * words in the pending mask to check they are all empty. This orders + * with the same barrier on another CPU. This prevents two CPUs + * clearing the last 2 pending bits, but neither seeing the other's + * store when checking if the mask is empty, and missing an empty + * mask, which ends with a false positive. + */ + smp_mb(); if (cpumask_empty(&wd_smp_cpus_pending)) { unsigned long flags;
+none_pending: + /* + * Double check under lock because more than one CPU could see + * a clear mask with the lockless check after clearing their + * pending bits. + */ wd_smp_lock(&flags); if (cpumask_empty(&wd_smp_cpus_pending)) { wd_smp_last_reset_tb = tb; @@ -318,8 +353,12 @@ void arch_touch_nmi_watchdog(void) { unsigned long ticks = tb_ticks_per_usec * wd_timer_period_ms * 1000; int cpu = smp_processor_id(); - u64 tb = get_tb(); + u64 tb;
+ if (!cpumask_test_cpu(cpu, &watchdog_cpumask)) + return; + + tb = get_tb(); if (tb - per_cpu(wd_timer_tb, cpu) >= ticks) { per_cpu(wd_timer_tb, cpu) = tb; wd_smp_clear_cpu_pending(cpu, tb);
From: Ye Guojin ye.guojin@zte.com.cn
[ Upstream commit f670b274f7f6f4b2722d7f08d0fddf606a727e92 ]
This was found by coccicheck: ./sound/soc/fsl/imx-hdmi.c,209,1-7,ERROR missing put_device; call of_find_device_by_node on line 119, but without a corresponding object release within this function.
Reported-by: Zeal Robot zealci@zte.com.cn Signed-off-by: Ye Guojin ye.guojin@zte.com.cn Link: https://lore.kernel.org/r/20211110002910.134915-1-ye.guojin@zte.com.cn Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/fsl/imx-hdmi.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c index f10359a288005..929f69b758af4 100644 --- a/sound/soc/fsl/imx-hdmi.c +++ b/sound/soc/fsl/imx-hdmi.c @@ -145,6 +145,8 @@ static int imx_hdmi_probe(struct platform_device *pdev) data->dai.capture_only = false; data->dai.init = imx_hdmi_init;
+ put_device(&cpu_pdev->dev); + if (of_node_name_eq(cpu_np, "sai")) { data->cpu_priv.sysclk_id[1] = FSL_SAI_CLK_MAST1; data->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1;
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit effa453168a7eeb8a562ff4edc1dbf9067360a61 ]
If an invalid block size is provided, reject it instead of silently changing it to a supported value. Especially critical I see the case of a write transfer with block length 0. In this case we have no guarantee that the byte we would write is valid. When silently reducing a read to 32 bytes then we don't return an error and the caller may falsely assume that we returned the full requested data.
If this change should break any (broken) caller, then I think we should fix the caller.
Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Reviewed-by: Jean Delvare jdelvare@suse.de Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-i801.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 41446f9cc52da..c87ea470eba98 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -775,6 +775,11 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data * int result = 0; unsigned char hostc;
+ if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA) + data->block[0] = I2C_SMBUS_BLOCK_MAX; + else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) + return -EPROTO; + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { if (read_write == I2C_SMBUS_WRITE) { /* set I2C_EN bit in configuration register */ @@ -788,16 +793,6 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data * } }
- if (read_write == I2C_SMBUS_WRITE - || command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (data->block[0] < 1) - data->block[0] = 1; - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) - data->block[0] = I2C_SMBUS_BLOCK_MAX; - } else { - data->block[0] = 32; /* max for SMBus block reads */ - } - /* Experience has shown that the block buffer can only be used for SMBus (not I2C) block transactions, even though the datasheet doesn't mention this limitation. */
From: Michael Ellerman mpe@ellerman.id.au
[ Upstream commit a4ac0d249a5db80e79d573db9e4ad29354b643a8 ]
setup_profiling_timer() is only needed when CONFIG_PROFILING is enabled.
Fixes the following W=1 warning when CONFIG_PROFILING=n: linux/arch/powerpc/kernel/smp.c:1638:5: error: no previous prototype for ‘setup_profiling_timer’
Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20211124093254.1054750-5-mpe@ellerman.id.au Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/smp.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index c23ee842c4c33..aee3a7119f977 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -1635,10 +1635,12 @@ void start_secondary(void *unused) BUG(); }
+#ifdef CONFIG_PROFILING int setup_profiling_timer(unsigned int multiplier) { return 0; } +#endif
static void fixup_topology(void) {
From: Joakim Tjernlund joakim.tjernlund@infinera.com
[ Upstream commit ebe82cf92cd4825c3029434cabfcd2f1780e64be ]
Current I2C reset procedure is broken in two ways: 1) It only generate 1 START instead of 9 STARTs and STOP. 2) It leaves the bus Busy so every I2C xfer after the first fixup calls the reset routine again, for every xfer there after.
This fixes both errors.
Signed-off-by: Joakim Tjernlund joakim.tjernlund@infinera.com Acked-by: Scott Wood oss@buserror.net Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-mpc.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index db26cc36e13fe..6c698c10d3cdb 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -119,23 +119,30 @@ static inline void writeccr(struct mpc_i2c *i2c, u32 x) /* Sometimes 9th clock pulse isn't generated, and slave doesn't release * the bus, because it wants to send ACK. * Following sequence of enabling/disabling and sending start/stop generates - * the 9 pulses, so it's all OK. + * the 9 pulses, each with a START then ending with STOP, so it's all OK. */ static void mpc_i2c_fixup(struct mpc_i2c *i2c) { int k; - u32 delay_val = 1000000 / i2c->real_clk + 1; - - if (delay_val < 2) - delay_val = 2; + unsigned long flags;
for (k = 9; k; k--) { writeccr(i2c, 0); - writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); + writeb(0, i2c->base + MPC_I2C_SR); /* clear any status bits */ + writeccr(i2c, CCR_MEN | CCR_MSTA); /* START */ + readb(i2c->base + MPC_I2C_DR); /* init xfer */ + udelay(15); /* let it hit the bus */ + local_irq_save(flags); /* should not be delayed further */ + writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSTA); /* delay SDA */ readb(i2c->base + MPC_I2C_DR); - writeccr(i2c, CCR_MEN); - udelay(delay_val << 1); + if (k != 1) + udelay(5); + local_irq_restore(flags); } + writeccr(i2c, CCR_MEN); /* Initiate STOP */ + readb(i2c->base + MPC_I2C_DR); + udelay(15); /* Let STOP propagate */ + writeccr(i2c, 0); }
static int i2c_mpc_wait_sr(struct mpc_i2c *i2c, int mask)
From: Martin Blumenstingl martin.blumenstingl@googlemail.com
[ Upstream commit ff54938dd190d85f740b9bf9dde59b550936b621 ]
There are reports that 48kHz audio does not work on the WeTek Play 2 (which uses a GXBB SoC), while 44.1kHz audio works fine on the same board. There are also reports of 48kHz audio working fine on GXL and GXM SoCs, which are using an (almost) identical AIU (audio controller).
Experimenting has shown that MPLL0 is causing this problem. In the .dts we have by default: assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; assigned-clock-rates = <294912000>, <270950400>, <393216000>; The MPLL0 rate is divisible by 48kHz without remainder and the MPLL1 rate is divisible by 44.1kHz without remainder. Swapping these two clock rates "fixes" 48kHz audio but breaks 44.1kHz audio.
Everything looks normal when looking at the info provided by the common clock framework while playing 48kHz audio (via I2S with mclk-fs = 256): mpll_prediv 1 1 0 2000000000 mpll0_div 1 1 0 294909641 mpll0 1 1 0 294909641 cts_amclk_sel 1 1 0 294909641 cts_amclk_div 1 1 0 12287902 cts_amclk 1 1 0 12287902
meson-clk-msr however shows that the actual MPLL0 clock is off by more than 38MHz: mp0_out 333322917 +/-10416Hz
The rate seen by meson-clk-msr is very close to what we would get when SDM (the fractional part) was ignored: (2000000000Hz * 16384) / ((16384 * 6) = 333.33MHz If SDM was considered the we should get close to: (2000000000Hz * 16384) / ((16384 * 6) + 12808) = 294.9MHz
Further experimenting shows that HHI_MPLL_CNTL7[15] does not have any effect on the rate of MPLL0 as seen my meson-clk-msr (regardless of whether that bit is zero or one the rate is always the same according to meson-clk-msr). Using HHI_MPLL_CNTL[25] on the other hand as SDM_EN results in SDM being considered for the rate output by the hardware. The rate - as seen by meson-clk-msr - matches with what we expect when SDM_EN is enabled (fractional part is being considered, resulting in a 294.9MHz output) or disable (fractional part being ignored, resulting in a 333.33MHz output).
Reported-by: Christian Hewitt christianshewitt@gmail.com Tested-by: Christian Hewitt christianshewitt@gmail.com Signed-off-by: Martin Blumenstingl martin.blumenstingl@googlemail.com Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20211031135006.1508796-1-martin.blumenstingl@googl... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/meson/gxbb.c | 44 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index d6eed760327d0..608e0e8ca49a8 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -713,6 +713,35 @@ static struct clk_regmap gxbb_mpll_prediv = { };
static struct clk_regmap gxbb_mpll0_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL, + .shift = 25, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 16, + .width = 9, + }, + .lock = &meson_clk_lock, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll0_div", + .ops = &meson_clk_mpll_ops, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mpll_prediv.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap gxl_mpll0_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL7, @@ -749,7 +778,16 @@ static struct clk_regmap gxbb_mpll0 = { .hw.init = &(struct clk_init_data){ .name = "mpll0", .ops = &clk_regmap_gate_ops, - .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw }, + .parent_data = &(const struct clk_parent_data) { + /* + * Note: + * GXL and GXBB have different SDM_EN registers. We + * fallback to the global naming string mechanism so + * mpll0_div picks up the appropriate one. + */ + .name = "mpll0_div", + .index = -1, + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -3044,7 +3082,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { [CLKID_VAPB_1] = &gxbb_vapb_1.hw, [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, [CLKID_VAPB] = &gxbb_vapb.hw, - [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw, + [CLKID_MPLL0_DIV] = &gxl_mpll0_div.hw, [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw, @@ -3439,7 +3477,7 @@ static struct clk_regmap *const gxl_clk_regmaps[] = { &gxbb_mpll0, &gxbb_mpll1, &gxbb_mpll2, - &gxbb_mpll0_div, + &gxl_mpll0_div, &gxbb_mpll1_div, &gxbb_mpll2_div, &gxbb_cts_amclk_div,
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit df1f679d19edb9eeb67cc2f96b29375f21991945 ]
KeyWest i2c @0xf8001003 irq 42 /uni-n@f8000000/i2c@f8001000 BUG: key c2d00cbc has not been registered! ------------[ cut here ]------------ DEBUG_LOCKS_WARN_ON(1) WARNING: CPU: 0 PID: 1 at kernel/locking/lockdep.c:4801 lockdep_init_map_type+0x4c0/0xb4c Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.15.5-gentoo-PowerMacG4 #9 NIP: c01a9428 LR: c01a9428 CTR: 00000000 REGS: e1033cf0 TRAP: 0700 Not tainted (5.15.5-gentoo-PowerMacG4) MSR: 00029032 <EE,ME,IR,DR,RI> CR: 24002002 XER: 00000000
GPR00: c01a9428 e1033db0 c2d1cf20 00000016 00000004 00000001 c01c0630 e1033a73 GPR08: 00000000 00000000 00000000 e1033db0 24002004 00000000 f8729377 00000003 GPR16: c1829a9c 00000000 18305357 c1416fc0 c1416f80 c006ac60 c2d00ca8 c1416f00 GPR24: 00000000 c21586f0 c2160000 00000000 c2d00cbc c2170000 c216e1a0 c2160000 NIP [c01a9428] lockdep_init_map_type+0x4c0/0xb4c LR [c01a9428] lockdep_init_map_type+0x4c0/0xb4c Call Trace: [e1033db0] [c01a9428] lockdep_init_map_type+0x4c0/0xb4c (unreliable) [e1033df0] [c1c177b8] kw_i2c_add+0x334/0x424 [e1033e20] [c1c18294] pmac_i2c_init+0x9ec/0xa9c [e1033e80] [c1c1a790] smp_core99_probe+0xbc/0x35c [e1033eb0] [c1c03cb0] kernel_init_freeable+0x190/0x5a4 [e1033f10] [c000946c] kernel_init+0x28/0x154 [e1033f30] [c0035148] ret_from_kernel_thread+0x14/0x1c
Add missing lockdep_register_key()
Reported-by: Erhard Furtner erhard_f@mailbox.org Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/69e4f55565bb45ebb0843977801b245af0c666fe.163826474... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/platforms/powermac/low_i2c.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index f77a59b5c2e1a..de34fa34c42d8 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -582,6 +582,7 @@ static void __init kw_i2c_add(struct pmac_i2c_host_kw *host, bus->close = kw_i2c_close; bus->xfer = kw_i2c_xfer; mutex_init(&bus->mutex); + lockdep_register_key(&bus->lock_key); lockdep_set_class(&bus->mutex, &bus->lock_key); if (controller == busnode) bus->flags = pmac_i2c_multibus;
From: Alexey Kardashevskiy aik@ozlabs.ru
[ Upstream commit 511d25d6b789fffcb20a3eb71899cf974a31bd9d ]
The userspace can trigger "vmalloc size %lu allocation failure: exceeds total pages" via the KVM_SET_USER_MEMORY_REGION ioctl.
This silences the warning by checking the limit before calling vzalloc() and returns ENOMEM if failed.
This does not call underlying valloc helpers as __vmalloc_node() is only exported when CONFIG_TEST_VMALLOC_MODULE and __vmalloc_node_range() is not exported at all.
Spotted by syzkaller.
Signed-off-by: Alexey Kardashevskiy aik@ozlabs.ru [mpe: Use 'size' for the variable rather than 'cb'] Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210901084512.1658628-1-aik@ozlabs.ru Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kvm/book3s_hv.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 7b74fc0a986b8..94da0d25eb125 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -4861,8 +4861,12 @@ static int kvmppc_core_prepare_memory_region_hv(struct kvm *kvm, unsigned long npages = mem->memory_size >> PAGE_SHIFT;
if (change == KVM_MR_CREATE) { - slot->arch.rmap = vzalloc(array_size(npages, - sizeof(*slot->arch.rmap))); + unsigned long size = array_size(npages, sizeof(*slot->arch.rmap)); + + if ((size >> PAGE_SHIFT) > totalram_pages()) + return -ENOMEM; + + slot->arch.rmap = vzalloc(size); if (!slot->arch.rmap) return -ENOMEM; }
From: Alexey Kardashevskiy aik@ozlabs.ru
[ Upstream commit 792020907b11c6f9246c21977cab3bad985ae4b6 ]
H_COPY_TOFROM_GUEST is an hcall for an upper level VM to access its nested VMs memory. The userspace can trigger WARN_ON_ONCE(!(gfp & __GFP_NOWARN)) in __alloc_pages() by constructing a tiny VM which only does H_COPY_TOFROM_GUEST with a too big GPR9 (number of bytes to copy).
This silences the warning by adding __GFP_NOWARN.
Spotted by syzkaller.
Signed-off-by: Alexey Kardashevskiy aik@ozlabs.ru Reviewed-by: Fabiano Rosas farosas@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210901084550.1658699-1-aik@ozlabs.ru Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kvm/book3s_hv_nested.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c index ed8a2c9f56299..89295b52a97c3 100644 --- a/arch/powerpc/kvm/book3s_hv_nested.c +++ b/arch/powerpc/kvm/book3s_hv_nested.c @@ -582,7 +582,7 @@ long kvmhv_copy_tofrom_guest_nested(struct kvm_vcpu *vcpu) if (eaddr & (0xFFFUL << 52)) return H_PARAMETER;
- buf = kzalloc(n, GFP_KERNEL); + buf = kzalloc(n, GFP_KERNEL | __GFP_NOWARN); if (!buf) return H_NO_MEM;
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit 33dc3e3e99e626ce51f462d883b05856c6c30b1d ]
sparse warnings: (new ones prefixed by >>)
drivers/w1/slaves/w1_ds28e04.c:342:13: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected char [noderef] __user *_pu_addr @@ got char *buf @@
drivers/w1/slaves/w1_ds28e04.c:342:13: sparse: expected char [noderef] __user *_pu_addr drivers/w1/slaves/w1_ds28e04.c:342:13: sparse: got char *buf
drivers/w1/slaves/w1_ds28e04.c:356:13: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected char const [noderef] __user *_gu_addr @@ got char const *buf @@
drivers/w1/slaves/w1_ds28e04.c:356:13: sparse: expected char const [noderef] __user *_gu_addr drivers/w1/slaves/w1_ds28e04.c:356:13: sparse: got char const *buf
The buffer buf is a failsafe buffer in kernel space, it's not user memory hence doesn't deserve the use of get_user() or put_user().
Access 'buf' content directly.
Link: https://lore.kernel.org/lkml/202111190526.K5vb7NWC-lkp@intel.com/T/ Reported-by: kernel test robot lkp@intel.com Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Link: https://lore.kernel.org/r/d14ed8d71ad4372e6839ae427f91441d3ba0e94d.163794631... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/w1/slaves/w1_ds28e04.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-)
diff --git a/drivers/w1/slaves/w1_ds28e04.c b/drivers/w1/slaves/w1_ds28e04.c index e4f336111edc6..6cef6e2edb892 100644 --- a/drivers/w1/slaves/w1_ds28e04.c +++ b/drivers/w1/slaves/w1_ds28e04.c @@ -32,7 +32,7 @@ static int w1_strong_pullup = 1; module_param_named(strong_pullup, w1_strong_pullup, int, 0);
/* enable/disable CRC checking on DS28E04-100 memory accesses */ -static char w1_enable_crccheck = 1; +static bool w1_enable_crccheck = true;
#define W1_EEPROM_SIZE 512 #define W1_PAGE_COUNT 16 @@ -339,32 +339,18 @@ static BIN_ATTR_RW(pio, 1); static ssize_t crccheck_show(struct device *dev, struct device_attribute *attr, char *buf) { - if (put_user(w1_enable_crccheck + 0x30, buf)) - return -EFAULT; - - return sizeof(w1_enable_crccheck); + return sysfs_emit(buf, "%d\n", w1_enable_crccheck); }
static ssize_t crccheck_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - char val; - - if (count != 1 || !buf) - return -EINVAL; + int err = kstrtobool(buf, &w1_enable_crccheck);
- if (get_user(val, buf)) - return -EFAULT; + if (err) + return err;
- /* convert to decimal */ - val = val - 0x30; - if (val != 0 && val != 1) - return -EINVAL; - - /* set the new value */ - w1_enable_crccheck = val; - - return sizeof(w1_enable_crccheck); + return count; }
static DEVICE_ATTR_RW(crccheck);
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org
[ Upstream commit 86192251033308bb42f1e9813c962989d8ed07ec ]
For some reason we never set the size for nvmem sysfs binary file. Set this.
Reported-by: Gilles BULOZ gilles.buloz@kontron.com Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Link: https://lore.kernel.org/r/20211130133909.6154-1-srinivas.kandagatla@linaro.o... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvmem/core.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index e765d3d0542e5..23a38dcf0fc4d 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -312,6 +312,8 @@ static umode_t nvmem_bin_attr_is_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct nvmem_device *nvmem = to_nvmem_device(dev);
+ attr->size = nvmem->size; + return nvmem_bin_attr_get_umode(nvmem); }
From: Christoph Hellwig hch@lst.de
[ Upstream commit d751939235b9b7bc4af15f90a3e99288a8b844a7 ]
Make sure ->dax_dev is NULL on error so that the cleanup path doesn't trip over an ERR_PTR.
Reported-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20211129102203.2243509-2-hch@lst.de Signed-off-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/dm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 662742a310cbb..acc84dc1bded5 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1786,8 +1786,10 @@ static struct mapped_device *alloc_dev(int minor) if (IS_ENABLED(CONFIG_DAX_DRIVER)) { md->dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops, 0); - if (IS_ERR(md->dax_dev)) + if (IS_ERR(md->dax_dev)) { + md->dax_dev = NULL; goto bad; + } }
format_dev_t(md->name, MKDEV(_major, minor));
From: Christoph Hellwig hch@lst.de
[ Upstream commit 5d2a228b9e1319ff188f9ea89006fbe575561921 ]
The device mapper DAX support is all hanging off a block device and thus can't be used with device dax. Make it depend on CONFIG_FS_DAX instead of CONFIG_DAX_DRIVER. This also means that bdev_dax_pgoff only needs to be built under CONFIG_FS_DAX now.
Signed-off-by: Christoph Hellwig hch@lst.de Acked-by: Mike Snitzer snitzer@redhat.com Link: https://lore.kernel.org/r/20211129102203.2243509-3-hch@lst.de Signed-off-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dax/super.c | 6 ++---- drivers/md/dm-linear.c | 2 +- drivers/md/dm-log-writes.c | 2 +- drivers/md/dm-stripe.c | 2 +- drivers/md/dm-writecache.c | 2 +- drivers/md/dm.c | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/drivers/dax/super.c b/drivers/dax/super.c index b882cf8106ea3..e20d0cef10a18 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -63,7 +63,7 @@ static int dax_host_hash(const char *host) return hashlen_hash(hashlen_string("DAX", host)) % DAX_HASH_SIZE; }
-#ifdef CONFIG_BLOCK +#if defined(CONFIG_BLOCK) && defined(CONFIG_FS_DAX) #include <linux/blkdev.h>
int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size, @@ -80,7 +80,6 @@ int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size, } EXPORT_SYMBOL(bdev_dax_pgoff);
-#if IS_ENABLED(CONFIG_FS_DAX) /** * dax_get_by_host() - temporary lookup mechanism for filesystem-dax * @host: alternate name for the device registered by a dax driver @@ -219,8 +218,7 @@ bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev, return ret; } EXPORT_SYMBOL_GPL(dax_supported); -#endif /* CONFIG_FS_DAX */ -#endif /* CONFIG_BLOCK */ +#endif /* CONFIG_BLOCK && CONFIG_FS_DAX */
enum dax_device_flags { /* !alive + rcu grace period == no new operations / mappings */ diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 66ba16713f696..0a260c35aeeed 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -162,7 +162,7 @@ static int linear_iterate_devices(struct dm_target *ti, return fn(ti, lc->dev, lc->start, ti->len, data); }
-#if IS_ENABLED(CONFIG_DAX_DRIVER) +#if IS_ENABLED(CONFIG_FS_DAX) static long linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) { diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index 0b3ef977ceeba..3155875d4e5b0 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c @@ -901,7 +901,7 @@ static void log_writes_io_hints(struct dm_target *ti, struct queue_limits *limit limits->io_min = limits->physical_block_size; }
-#if IS_ENABLED(CONFIG_DAX_DRIVER) +#if IS_ENABLED(CONFIG_FS_DAX) static int log_dax(struct log_writes_c *lc, sector_t sector, size_t bytes, struct iov_iter *i) { diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 6660b6b53d5bf..f084607220293 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -300,7 +300,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_REMAPPED; }
-#if IS_ENABLED(CONFIG_DAX_DRIVER) +#if IS_ENABLED(CONFIG_FS_DAX) static long stripe_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) { diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c index 4b8991cde223d..4f31591d2d25e 100644 --- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -38,7 +38,7 @@ #define BITMAP_GRANULARITY PAGE_SIZE #endif
-#if IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API) && IS_ENABLED(CONFIG_DAX_DRIVER) +#if IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API) && IS_ENABLED(CONFIG_FS_DAX) #define DM_WRITECACHE_HAS_PMEM #endif
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index acc84dc1bded5..b93fcc91176e5 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1783,7 +1783,7 @@ static struct mapped_device *alloc_dev(int minor) md->disk->private_data = md; sprintf(md->disk->disk_name, "dm-%d", minor);
- if (IS_ENABLED(CONFIG_DAX_DRIVER)) { + if (IS_ENABLED(CONFIG_FS_DAX)) { md->dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops, 0); if (IS_ERR(md->dax_dev)) {
From: Ameer Hamza amhamza.mgc@gmail.com
[ Upstream commit c686316ec1210d43653c91e104c1e4cd0156dc89 ]
Dereferncing of_id pointer will result in exception in current implementation since of_match_device() will assign it to NULL. Adding NULL check for protection.
Signed-off-by: Ameer Hamza amhamza.mgc@gmail.com Link: https://lore.kernel.org/r/20211205204200.7852-1-amhamza.mgc@gmail.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/generic/test-component.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index 85385a771d807..8fc97d3ff0110 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -532,13 +532,16 @@ static int test_driver_probe(struct platform_device *pdev) struct device_node *node = dev->of_node; struct device_node *ep; const struct of_device_id *of_id = of_match_device(test_of_match, &pdev->dev); - const struct test_adata *adata = of_id->data; + const struct test_adata *adata; struct snd_soc_component_driver *cdriv; struct snd_soc_dai_driver *ddriv; struct test_dai_name *dname; struct test_priv *priv; int num, ret, i;
+ if (!of_id) + return -EINVAL; + adata = of_id->data; num = of_graph_get_endpoint_count(node); if (!num) { dev_err(dev, "no port exits\n");
From: Stephan Gerhold stephan@gerhold.net
[ Upstream commit a7d9436a6c85fcb8843c910fd323dcd7f839bf63 ]
Using icc-rpm on ARM32 currently results in clk_set_rate() errors during boot, e.g. "bus clk_set_rate error: -22". This is very similar to commit 7381e27b1e56 ("interconnect: qcom: msm8974: Prevent integer overflow in rate") where the u64 is converted to a signed long during clock rate rounding, resulting in an overflow on 32-bit platforms.
Let's fix it similarly by making sure that the rate does not exceed LONG_MAX. Such high clock rates will surely result in the maximum frequency of the bus anyway.
Signed-off-by: Stephan Gerhold stephan@gerhold.net Link: https://lore.kernel.org/r/20211206114542.45325-1-stephan@gerhold.net Signed-off-by: Georgi Djakov djakov@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/interconnect/qcom/icc-rpm.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c index ef7999a08c8bf..8114295a83129 100644 --- a/drivers/interconnect/qcom/icc-rpm.c +++ b/drivers/interconnect/qcom/icc-rpm.c @@ -239,6 +239,7 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) rate = max(sum_bw, max_peak_bw);
do_div(rate, qn->buswidth); + rate = min_t(u64, rate, LONG_MAX);
if (qn->rate == rate) return 0;
From: Bart Van Assche bvanassche@acm.org
[ Upstream commit 3489c34bd02b73a72646037d673a122a53cee174 ]
Fix the following kernel crash:
Unable to handle kernel paging request at virtual address ffffffc91e735000 Call trace: __queue_work+0x26c/0x624 queue_work_on+0x6c/0xf0 ufshcd_hold+0x12c/0x210 __ufshcd_wl_suspend+0xc0/0x400 ufshcd_wl_shutdown+0xb8/0xcc device_shutdown+0x184/0x224 kernel_restart+0x4c/0x124 __arm64_sys_reboot+0x194/0x264 el0_svc_common+0xc8/0x1d4 do_el0_svc+0x30/0x8c el0_svc+0x20/0x30 el0_sync_handler+0x84/0xe4 el0_sync+0x1bc/0x1c0
Fix this crash by ungating the clock before destroying the work queue on which clock gating work is queued.
Link: https://lore.kernel.org/r/20211203231950.193369-15-bvanassche@acm.org Tested-by: Bean Huo beanhuo@micron.com Reviewed-by: Bean Huo beanhuo@micron.com Signed-off-by: Bart Van Assche bvanassche@acm.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 13c09dbd99b92..52e92fae63cee 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1666,7 +1666,8 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) bool flush_result; unsigned long flags;
- if (!ufshcd_is_clkgating_allowed(hba)) + if (!ufshcd_is_clkgating_allowed(hba) || + !hba->clk_gating.is_initialized) goto out; spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.active_reqs++; @@ -1826,7 +1827,7 @@ static void __ufshcd_release(struct ufs_hba *hba)
if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL || - hba->outstanding_tasks || + hba->outstanding_tasks || !hba->clk_gating.is_initialized || hba->active_uic_cmd || hba->uic_async_done || hba->clk_gating.state == CLKS_OFF) return; @@ -1961,11 +1962,15 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) { if (!hba->clk_gating.is_initialized) return; + ufshcd_remove_clk_gating_sysfs(hba); - cancel_work_sync(&hba->clk_gating.ungate_work); - cancel_delayed_work_sync(&hba->clk_gating.gate_work); - destroy_workqueue(hba->clk_gating.clk_gating_workq); + + /* Ungate the clock if necessary. */ + ufshcd_hold(hba, false); hba->clk_gating.is_initialized = false; + ufshcd_release(hba); + + destroy_workqueue(hba->clk_gating.clk_gating_workq); }
/* Must be called with host lock acquired */
From: James Smart jsmart2021@gmail.com
[ Upstream commit f0d3919697492950f57a26a1093aee53880d669d ]
During rmmod testing, messages appeared indicating lpfc_mbuf_pool entries were still busy. This situation was only seen doing rmmod after at least 1 vport (NPIV) instance was created and destroyed. The number of messages scaled with the number of vports created.
When a vport is created, it can receive a PLOGI from another initiator Nport. When this happens, the driver prepares to ack the PLOGI and prepares an RPI for registration (via mbx cmd) which includes an mbuf allocation. During the unsolicited PLOGI processing and after the RPI preparation, the driver recognizes it is one of the vport instances and decides to reject the PLOGI. During the LS_RJT preparation for the PLOGI, the mailbox struct allocated for RPI registration is freed, but the mbuf that was also allocated is not released.
Fix by freeing the mbuf with the mailbox struct in the LS_RJT path.
As part of the code review to figure the issue out a couple of other areas where found that also would not have released the mbuf. Those are cleaned up as well.
Link: https://lore.kernel.org/r/20211204002644.116455-2-jsmart2021@gmail.com Co-developed-by: Justin Tee justin.tee@broadcom.com Signed-off-by: Justin Tee justin.tee@broadcom.com Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/lpfc/lpfc_els.c | 6 +++++- drivers/scsi/lpfc/lpfc_init.c | 8 ++++++-- drivers/scsi/lpfc/lpfc_nportdisc.c | 6 ++++++ 3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e83453bea2aee..5c10416c1c75a 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -6899,6 +6899,7 @@ static int lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context) { LPFC_MBOXQ_t *mbox = NULL; + struct lpfc_dmabuf *mp; int rc;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); @@ -6914,8 +6915,11 @@ lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context) mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_page_a0; mbox->ctx_ndlp = (struct lpfc_rdp_context *)rdp_context; rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) + if (rc == MBX_NOT_FINISHED) { + mp = (struct lpfc_dmabuf *)mbox->ctx_buf; + lpfc_mbuf_free(phba, mp->virt, mp->phys); goto issue_mbox_fail; + }
return 0;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index ba17a8f740a95..7628b0634c57a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5373,8 +5373,10 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, */ if (!(phba->hba_flag & HBA_FCOE_MODE)) { rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) + if (rc == MBX_NOT_FINISHED) { + lpfc_mbuf_free(phba, mp->virt, mp->phys); goto out_free_dmabuf; + } return; } /* @@ -6337,8 +6339,10 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc) }
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) + if (rc == MBX_NOT_FINISHED) { + lpfc_mbuf_free(phba, mp->virt, mp->phys); goto out_free_dmabuf; + } return;
out_free_dmabuf: diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 27263f02ab9f6..7d717a4ac14d1 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -322,6 +322,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, { struct lpfc_hba *phba = vport->phba; struct lpfc_dmabuf *pcmd; + struct lpfc_dmabuf *mp; uint64_t nlp_portwwn = 0; uint32_t *lp; IOCB_t *icmd; @@ -571,6 +572,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * a default RPI. */ if (phba->sli_rev == LPFC_SLI_REV4) { + mp = (struct lpfc_dmabuf *)login_mbox->ctx_buf; + if (mp) { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } mempool_free(login_mbox, phba->mbox_mem_pool); login_mbox = NULL; } else {
From: James Smart jsmart2021@gmail.com
[ Upstream commit 7dd2e2a923173d637c272e483966be8e96a72b64 ]
Extraneous teardown routines are present in the firmware dump path causing altered states in firmware captures.
When a firmware dump is requested via sysfs, trigger the dump immediately without tearing down structures and changing adapter state.
The driver shall rely on pre-existing firmware error state clean up handlers to restore the adapter.
Link: https://lore.kernel.org/r/20211204002644.116455-6-jsmart2021@gmail.com Co-developed-by: Justin Tee justin.tee@broadcom.com Signed-off-by: Justin Tee justin.tee@broadcom.com Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/lpfc/lpfc.h | 2 +- drivers/scsi/lpfc/lpfc_attr.c | 62 ++++++++++++++++++++------------ drivers/scsi/lpfc/lpfc_hbadisc.c | 8 ++++- drivers/scsi/lpfc/lpfc_sli.c | 6 ---- 4 files changed, 48 insertions(+), 30 deletions(-)
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 2f8e6d0a926fe..54c58392fd5d0 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1023,7 +1023,6 @@ struct lpfc_hba { #define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */ #define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */ #define HBA_IOQ_FLUSH 0x8000 /* FCP/NVME I/O queues being flushed */ -#define HBA_FW_DUMP_OP 0x10000 /* Skips fn reset before FW dump */ #define HBA_RECOVERABLE_UE 0x20000 /* Firmware supports recoverable UE */ #define HBA_FORCED_LINK_SPEED 0x40000 /* * Firmware supports Forced Link Speed @@ -1040,6 +1039,7 @@ struct lpfc_hba { #define HBA_HBEAT_TMO 0x8000000 /* HBEAT initiated after timeout */ #define HBA_FLOGI_OUTSTANDING 0x10000000 /* FLOGI is outstanding */
+ struct completion *fw_dump_cmpl; /* cmpl event tracker for fw_dump */ uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ struct lpfc_dmabuf slim2p;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index dd4c51b6ef4e2..7a7f17d71811b 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1709,25 +1709,25 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) before_fc_flag = phba->pport->fc_flag; sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn;
- /* Disable SR-IOV virtual functions if enabled */ - if (phba->cfg_sriov_nr_virtfn) { - pci_disable_sriov(pdev); - phba->cfg_sriov_nr_virtfn = 0; - } + if (opcode == LPFC_FW_DUMP) { + init_completion(&online_compl); + phba->fw_dump_cmpl = &online_compl; + } else { + /* Disable SR-IOV virtual functions if enabled */ + if (phba->cfg_sriov_nr_virtfn) { + pci_disable_sriov(pdev); + phba->cfg_sriov_nr_virtfn = 0; + }
- if (opcode == LPFC_FW_DUMP) - phba->hba_flag |= HBA_FW_DUMP_OP; + status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
- status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); + if (status != 0) + return status;
- if (status != 0) { - phba->hba_flag &= ~HBA_FW_DUMP_OP; - return status; + /* wait for the device to be quiesced before firmware reset */ + msleep(100); }
- /* wait for the device to be quiesced before firmware reset */ - msleep(100); - reg_val = readl(phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
@@ -1756,24 +1756,42 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "3153 Fail to perform the requested " "access: x%x\n", reg_val); + if (phba->fw_dump_cmpl) + phba->fw_dump_cmpl = NULL; return rc; }
/* keep the original port state */ - if (before_fc_flag & FC_OFFLINE_MODE) - goto out; - - init_completion(&online_compl); - job_posted = lpfc_workq_post_event(phba, &status, &online_compl, - LPFC_EVT_ONLINE); - if (!job_posted) + if (before_fc_flag & FC_OFFLINE_MODE) { + if (phba->fw_dump_cmpl) + phba->fw_dump_cmpl = NULL; goto out; + }
- wait_for_completion(&online_compl); + /* Firmware dump will trigger an HA_ERATT event, and + * lpfc_handle_eratt_s4 routine already handles bringing the port back + * online. + */ + if (opcode == LPFC_FW_DUMP) { + wait_for_completion(phba->fw_dump_cmpl); + } else { + init_completion(&online_compl); + job_posted = lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_ONLINE); + if (!job_posted) + goto out;
+ wait_for_completion(&online_compl); + } out: /* in any case, restore the virtual functions enabled as before */ if (sriov_nr_virtfn) { + /* If fw_dump was performed, first disable to clean up */ + if (opcode == LPFC_FW_DUMP) { + pci_disable_sriov(pdev); + phba->cfg_sriov_nr_virtfn = 0; + } + sriov_err = lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn); if (!sriov_err) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 9fe6e5b386ce3..5e54ec503f18b 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -869,10 +869,16 @@ lpfc_work_done(struct lpfc_hba *phba) if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) lpfc_sli4_post_async_mbox(phba);
- if (ha_copy & HA_ERATT) + if (ha_copy & HA_ERATT) { /* Handle the error attention event */ lpfc_handle_eratt(phba);
+ if (phba->fw_dump_cmpl) { + complete(phba->fw_dump_cmpl); + phba->fw_dump_cmpl = NULL; + } + } + if (ha_copy & HA_MBATT) lpfc_sli_handle_mb_event(phba);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 5dedb3de271d8..513a78d08b1d5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -5046,12 +5046,6 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) phba->fcf.fcf_flag = 0; spin_unlock_irq(&phba->hbalock);
- /* SLI4 INTF 2: if FW dump is being taken skip INIT_PORT */ - if (phba->hba_flag & HBA_FW_DUMP_OP) { - phba->hba_flag &= ~HBA_FW_DUMP_OP; - return rc; - } - /* Now physically reset the device */ lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0389 Performing PCI function reset!\n");
From: Takashi Iwai tiwai@suse.de
[ Upstream commit 6fadb494a638d8b8a55864ecc6ac58194f03f327 ]
Currently ALSA sequencer core tries to process the queued events as much as possible when they become dispatchable. If applications try to queue too massive events to be processed at the very same timing, the sequencer core would still try to process such all events, either in the interrupt context or via some notifier; in either away, it might be a cause of RCU stall or such problems.
As a potential workaround for those problems, this patch adds the upper limit of the amount of events to be processed. The remaining events are processed in the next batch, so they won't be lost.
For the time being, it's limited up to 1000 events per queue, which should be high enough for any normal usages.
Reported-by: Zqiang qiang.zhang1211@gmail.com Reported-by: syzbot+bb950e68b400ab4f65f8@syzkaller.appspotmail.com Link: https://lore.kernel.org/r/20211102033222.3849-1-qiang.zhang1211@gmail.com Link: https://lore.kernel.org/r/20211207165146.2888-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/core/seq/seq_queue.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index d6c02dea976c8..bc933104c3eea 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -235,12 +235,15 @@ struct snd_seq_queue *snd_seq_queue_find_name(char *name)
/* -------------------------------------------------------- */
+#define MAX_CELL_PROCESSES_IN_QUEUE 1000 + void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) { unsigned long flags; struct snd_seq_event_cell *cell; snd_seq_tick_time_t cur_tick; snd_seq_real_time_t cur_time; + int processed = 0;
if (q == NULL) return; @@ -263,6 +266,8 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) if (!cell) break; snd_seq_dispatch_event(cell, atomic, hop); + if (++processed >= MAX_CELL_PROCESSES_IN_QUEUE) + goto out; /* the rest processed at the next batch */ }
/* Process time queue... */ @@ -272,14 +277,19 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) if (!cell) break; snd_seq_dispatch_event(cell, atomic, hop); + if (++processed >= MAX_CELL_PROCESSES_IN_QUEUE) + goto out; /* the rest processed at the next batch */ }
+ out: /* free lock */ spin_lock_irqsave(&q->check_lock, flags); if (q->check_again) { q->check_again = 0; - spin_unlock_irqrestore(&q->check_lock, flags); - goto __again; + if (processed < MAX_CELL_PROCESSES_IN_QUEUE) { + spin_unlock_irqrestore(&q->check_lock, flags); + goto __again; + } } q->check_blocked = 0; spin_unlock_irqrestore(&q->check_lock, flags);
From: Nathan Chancellor nathan@kernel.org
[ Upstream commit f2c6c22fa83ab2577619009057b3ebcb5305bb03 ]
LLVM's integrated assembler does not support 'slti <reg>, <imm>':
<instantiation>:16:12: error: invalid operand for instruction slti $12, (0x6300 | 0x0008) ^ arch/mips/kernel/head.S:86:2: note: while in macro instantiation kernel_entry_setup # cpu specific setup ^ <instantiation>:16:12: error: invalid operand for instruction slti $12, (0x6300 | 0x0008) ^ arch/mips/kernel/head.S:150:2: note: while in macro instantiation smp_slave_setup ^
To increase compatibility with LLVM's integrated assembler, use the full form of 'slti <reg>, <reg>, <imm>', which matches the rest of arch/mips/. This does not result in any change for GNU as.
Link: https://github.com/ClangBuiltLinux/linux/issues/1526 Reported-by: Ryutaroh Matsumoto ryutaroh@ict.e.titech.ac.jp Signed-off-by: Nathan Chancellor nathan@kernel.org Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/mach-loongson64/kernel-entry-init.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h index 13373c5144f89..efb41b3519747 100644 --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h @@ -32,7 +32,7 @@ nop /* Loongson-3A R2/R3 */ andi t0, (PRID_IMP_MASK | PRID_REV_MASK) - slti t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) + slti t0, t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) bnez t0, 2f nop 1: @@ -63,7 +63,7 @@ nop /* Loongson-3A R2/R3 */ andi t0, (PRID_IMP_MASK | PRID_REV_MASK) - slti t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) + slti t0, t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) bnez t0, 2f nop 1:
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit 06e7cbc29e97b4713b4ea6def04ae8501a7d1a59 ]
As reported by Carlo, 16Mbytes is not enough with modern kernels that tend to be a bit big, so map another 16M page at boot.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/89b5f974a7fa5011206682cd092e2c905530ff46.163275555... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/head_40x.S | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S index 7d72ee5ab387c..e783860bea838 100644 --- a/arch/powerpc/kernel/head_40x.S +++ b/arch/powerpc/kernel/head_40x.S @@ -27,6 +27,7 @@
#include <linux/init.h> #include <linux/pgtable.h> +#include <linux/sizes.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/mmu.h> @@ -650,7 +651,7 @@ start_here: b . /* prevent prefetch past rfi */
/* Set up the initial MMU state so we can do the first level of - * kernel initialization. This maps the first 16 MBytes of memory 1:1 + * kernel initialization. This maps the first 32 MBytes of memory 1:1 * virtual to physical and more importantly sets the cache mode. */ initial_mmu: @@ -687,6 +688,12 @@ initial_mmu: tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */ tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */
+ li r0,62 /* TLB slot 62 */ + addis r4,r4,SZ_16M@h + addis r3,r3,SZ_16M@h + tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */ + tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */ + isync
/* Establish the exception vector base
From: Thadeu Lima de Souza Cascardo cascardo@canonical.com
[ Upstream commit 3c42e9542050d49610077e083c7c3f5fd5e26820 ]
A mis-match between reported and actual mitigation is not restricted to the Vulnerable case. The guest might also report the mitigation as "Software count cache flush" and the host will still mitigate with branch cache disabled.
So, instead of skipping depending on the detected mitigation, simply skip whenever the detected miss_percent is the expected one for a fully mitigated system, that is, above 95%.
Signed-off-by: Thadeu Lima de Souza Cascardo cascardo@canonical.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20211207130557.40566-1-cascardo@canonical.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/powerpc/security/spectre_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/powerpc/security/spectre_v2.c b/tools/testing/selftests/powerpc/security/spectre_v2.c index adc2b7294e5fd..83647b8277e7d 100644 --- a/tools/testing/selftests/powerpc/security/spectre_v2.c +++ b/tools/testing/selftests/powerpc/security/spectre_v2.c @@ -193,7 +193,7 @@ int spectre_v2_test(void) * We are not vulnerable and reporting otherwise, so * missing such a mismatch is safe. */ - if (state == VULNERABLE) + if (miss_percent > 95) return 4;
return 1;
From: Hari Bathini hbathini@linux.ibm.com
[ Upstream commit 219572d2fc4135b5ce65c735d881787d48b10e71 ]
Kdump can be triggered after panic_notifers since commit f06e5153f4ae2 ("kernel/panic.c: add "crash_kexec_post_notifiers" option for kdump after panic_notifers") introduced crash_kexec_post_notifiers option. But using this option would mean smp_send_stop(), that marks all other CPUs as offline, gets called before kdump is triggered. As a result, kdump routines fail to save other CPUs' registers. To fix this, kdump friendly crash_smp_send_stop() function was introduced with kernel commit 0ee59413c967 ("x86/panic: replace smp_send_stop() with kdump friendly version in panic path"). Override this kdump friendly weak function to handle crash_kexec_post_notifiers option appropriately on powerpc.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Hari Bathini hbathini@linux.ibm.com [Fixed signature of crash_stop_this_cpu() - reported by lkp@intel.com] Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20211207103719.91117-1-hbathini@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/smp.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index aee3a7119f977..7201fdcf02f1c 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -620,6 +620,36 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)) } #endif
+#ifdef CONFIG_NMI_IPI +static void crash_stop_this_cpu(struct pt_regs *regs) +#else +static void crash_stop_this_cpu(void *dummy) +#endif +{ + /* + * Just busy wait here and avoid marking CPU as offline to ensure + * register data is captured appropriately. + */ + while (1) + cpu_relax(); +} + +void crash_smp_send_stop(void) +{ + static bool stopped = false; + + if (stopped) + return; + + stopped = true; + +#ifdef CONFIG_NMI_IPI + smp_send_nmi_ipi(NMI_IPI_ALL_OTHERS, crash_stop_this_cpu, 1000000); +#else + smp_call_function(crash_stop_this_cpu, NULL, 0); +#endif /* CONFIG_NMI_IPI */ +} + #ifdef CONFIG_NMI_IPI static void nmi_stop_this_cpu(struct pt_regs *regs) {
From: Hari Bathini hbathini@linux.ibm.com
[ Upstream commit 06e629c25daa519be620a8c17359ae8fc7a2e903 ]
In panic path, fadump is triggered via a panic notifier function. Before calling panic notifier functions, smp_send_stop() gets called, which stops all CPUs except the panic'ing CPU. Commit 8389b37dffdc ("powerpc: stop_this_cpu: remove the cpu from the online map.") and again commit bab26238bbd4 ("powerpc: Offline CPU in stop_this_cpu()") started marking CPUs as offline while stopping them. So, if a kernel has either of the above commits, vmcore captured with fadump via panic path would not process register data for all CPUs except the panic'ing CPU. Sample output of crash-utility with such vmcore:
# crash vmlinux vmcore ... KERNEL: vmlinux DUMPFILE: vmcore [PARTIAL DUMP] CPUS: 1 DATE: Wed Nov 10 09:56:34 EST 2021 UPTIME: 00:00:42 LOAD AVERAGE: 2.27, 0.69, 0.24 TASKS: 183 NODENAME: XXXXXXXXX RELEASE: 5.15.0+ VERSION: #974 SMP Wed Nov 10 04:18:19 CST 2021 MACHINE: ppc64le (2500 Mhz) MEMORY: 8 GB PANIC: "Kernel panic - not syncing: sysrq triggered crash" PID: 3394 COMMAND: "bash" TASK: c0000000150a5f80 [THREAD_INFO: c0000000150a5f80] CPU: 1 STATE: TASK_RUNNING (PANIC)
crash> p -x __cpu_online_mask __cpu_online_mask = $1 = { bits = {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} } crash> crash> crash> p -x __cpu_active_mask __cpu_active_mask = $2 = { bits = {0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} } crash>
While this has been the case since fadump was introduced, the issue was not identified for two probable reasons:
- In general, the bulk of the vmcores analyzed were from crash due to exception.
- The above did change since commit 8341f2f222d7 ("sysrq: Use panic() to force a crash") started using panic() instead of deferencing NULL pointer to force a kernel crash. But then commit de6e5d38417e ("powerpc: smp_send_stop do not offline stopped CPUs") stopped marking CPUs as offline till kernel commit bab26238bbd4 ("powerpc: Offline CPU in stop_this_cpu()") reverted that change.
To ensure post processing register data of all other CPUs happens as intended, let panic() function take the crash friendly path (read crash_smp_send_stop()) with the help of crash_kexec_post_notifiers option. Also, as register data for all CPUs is captured by f/w, skip IPI callbacks here for fadump, to avoid any complications in finding the right backtraces.
Signed-off-by: Hari Bathini hbathini@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20211207103719.91117-2-hbathini@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/fadump.c | 8 ++++++++ arch/powerpc/kernel/smp.c | 10 ++++++++++ 2 files changed, 18 insertions(+)
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index b7ceb041743c9..60f5fc14aa235 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -1641,6 +1641,14 @@ int __init setup_fadump(void) else if (fw_dump.reserve_dump_area_size) fw_dump.ops->fadump_init_mem_struct(&fw_dump);
+ /* + * In case of panic, fadump is triggered via ppc_panic_event() + * panic notifier. Setting crash_kexec_post_notifiers to 'true' + * lets panic() function take crash friendly path before panic + * notifiers are invoked. + */ + crash_kexec_post_notifiers = true; + return 1; } subsys_initcall(setup_fadump); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 7201fdcf02f1c..c338f9d8ab37a 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -61,6 +61,7 @@ #include <asm/cpu_has_feature.h> #include <asm/ftrace.h> #include <asm/kup.h> +#include <asm/fadump.h>
#ifdef DEBUG #include <asm/udbg.h> @@ -638,6 +639,15 @@ void crash_smp_send_stop(void) { static bool stopped = false;
+ /* + * In case of fadump, register data for all CPUs is captured by f/w + * on ibm,os-term rtas call. Skip IPI callbacks to other CPUs before + * this rtas call to avoid tricky post processing of those CPUs' + * backtraces. + */ + if (should_fadump_crash()) + return; + if (stopped) return;
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 288fad2f71fa0b989c075d4984879c26d47cfb06 ]
The code inherited from the Skylake driver does not seem to follow any known hardware recommendations.
The only two recommended options are a) use DPIB registers if VC1 traffic is not allowed b) use DPIB DDR update if VC1 traffic is used
In all of SOF-based updated, VC1 is not supported so we can 'safely' move to using DPIB registers only.
This patch keeps the legacy code, in case there was an undocumented issue lost to history, and adds the DPIB DDR update for additional debug.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Link: https://lore.kernel.org/r/20211207193947.71080-6-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/intel/hda-pcm.c | 86 +++++++++++++++++++++++++---------- sound/soc/sof/intel/hda.c | 9 +++- sound/soc/sof/intel/hda.h | 6 +++ 3 files changed, 75 insertions(+), 26 deletions(-)
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index cc8ddef37f37b..41cb60955f5c1 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -172,38 +172,74 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, goto found; }
- /* - * DPIB/posbuf position mode: - * For Playback, Use DPIB register from HDA space which - * reflects the actual data transferred. - * For Capture, Use the position buffer for pointer, as DPIB - * is not accurate enough, its update may be completed - * earlier than the data written to DDR. - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (sof_hda_position_quirk) { + case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY: + /* + * This legacy code, inherited from the Skylake driver, + * mixes DPIB registers and DPIB DDR updates and + * does not seem to follow any known hardware recommendations. + * It's not clear e.g. why there is a different flow + * for capture and playback, the only information that matters is + * what traffic class is used, and on all SOF-enabled platforms + * only VC0 is supported so the work-around was likely not necessary + * and quite possibly wrong. + */ + + /* DPIB/posbuf position mode: + * For Playback, Use DPIB register from HDA space which + * reflects the actual data transferred. + * For Capture, Use the position buffer for pointer, as DPIB + * is not accurate enough, its update may be completed + * earlier than the data written to DDR. + */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, + AZX_REG_VS_SDXDPIB_XBASE + + (AZX_REG_VS_SDXDPIB_XINTERVAL * + hstream->index)); + } else { + /* + * For capture stream, we need more workaround to fix the + * position incorrect issue: + * + * 1. Wait at least 20us before reading position buffer after + * the interrupt generated(IOC), to make sure position update + * happens on frame boundary i.e. 20.833uSec for 48KHz. + * 2. Perform a dummy Read to DPIB register to flush DMA + * position value. + * 3. Read the DMA Position from posbuf. Now the readback + * value should be >= period boundary. + */ + usleep_range(20, 21); + snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, + AZX_REG_VS_SDXDPIB_XBASE + + (AZX_REG_VS_SDXDPIB_XINTERVAL * + hstream->index)); + pos = snd_hdac_stream_get_pos_posbuf(hstream); + } + break; + case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS: + /* + * In case VC1 traffic is disabled this is the recommended option + */ pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, AZX_REG_VS_SDXDPIB_XBASE + (AZX_REG_VS_SDXDPIB_XINTERVAL * hstream->index)); - } else { + break; + case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE: /* - * For capture stream, we need more workaround to fix the - * position incorrect issue: - * - * 1. Wait at least 20us before reading position buffer after - * the interrupt generated(IOC), to make sure position update - * happens on frame boundary i.e. 20.833uSec for 48KHz. - * 2. Perform a dummy Read to DPIB register to flush DMA - * position value. - * 3. Read the DMA Position from posbuf. Now the readback - * value should be >= period boundary. + * This is the recommended option when VC1 is enabled. + * While this isn't needed for SOF platforms it's added for + * consistency and debug. */ - usleep_range(20, 21); - snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - AZX_REG_VS_SDXDPIB_XBASE + - (AZX_REG_VS_SDXDPIB_XINTERVAL * - hstream->index)); pos = snd_hdac_stream_get_pos_posbuf(hstream); + break; + default: + dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n", + sof_hda_position_quirk); + pos = 0; + break; }
if (pos >= hstream->bufsize) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 2c0d4d06ab364..25200a0e1dc9d 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -440,6 +440,10 @@ MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode"); #define hda_use_msi (1) #endif
+int sof_hda_position_quirk = SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS; +module_param_named(position_quirk, sof_hda_position_quirk, int, 0444); +MODULE_PARM_DESC(position_quirk, "SOF HDaudio position quirk"); + static char *hda_model; module_param(hda_model, charp, 0444); MODULE_PARM_DESC(hda_model, "Use the given HDA board model."); @@ -618,7 +622,10 @@ static int hda_init(struct snd_sof_dev *sdev) /* HDA bus init */ sof_hda_bus_init(bus, &pci->dev);
- bus->use_posbuf = 1; + if (sof_hda_position_quirk == SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS) + bus->use_posbuf = 0; + else + bus->use_posbuf = 1; bus->bdl_pos_adj = 0; bus->sync_write = 1;
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 1195018a1f4f5..dba4733ccf9ae 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -738,4 +738,10 @@ struct sof_ipc_dai_config; int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w); int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w);
+#define SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY (0) /* previous implementation */ +#define SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS (1) /* recommended if VC0 only */ +#define SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE (2) /* recommended with VC0 or VC1 */ + +extern int sof_hda_position_quirk; + #endif
From: Jan Kara jack@suse.cz
[ Upstream commit f05f2429eec60851b98bdde213de31dab697c01b ]
When memory allocation of iinfo or block allocation fails, already allocated struct udf_inode_info gets freed with iput() and udf_evict_inode() may look at inode fields which are not properly initialized. Fix it by marking inode bad before dropping reference to it in udf_new_inode().
Reported-by: syzbot+9ca499bb57a2b9e4c652@syzkaller.appspotmail.com Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- fs/udf/ialloc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 2ecf0e87660e3..b5d611cee749c 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -77,6 +77,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode) GFP_KERNEL); } if (!iinfo->i_data) { + make_bad_inode(inode); iput(inode); return ERR_PTR(-ENOMEM); } @@ -86,6 +87,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode) dinfo->i_location.partitionReferenceNum, start, &err); if (err) { + make_bad_inode(inode); iput(inode); return ERR_PTR(err); }
From: Ye Guojin ye.guojin@zte.com.cn
[ Upstream commit 858779df1c0787d3fec827fb705708df9ebdb15b ]
This was found by coccicheck: ./arch/mips/cavium-octeon/octeon-platform.c, 332, 1-7, ERROR missing put_device; call of_find_device_by_node on line 324, but without a corresponding object release within this function. ./arch/mips/cavium-octeon/octeon-platform.c, 395, 1-7, ERROR missing put_device; call of_find_device_by_node on line 387, but without a corresponding object release within this function. ./arch/mips/cavium-octeon/octeon-usb.c, 512, 3-9, ERROR missing put_device; call of_find_device_by_node on line 515, but without a corresponding object release within this function. ./arch/mips/cavium-octeon/octeon-usb.c, 543, 1-7, ERROR missing put_device; call of_find_device_by_node on line 515, but without a corresponding object release within this function.
Reported-by: Zeal Robot zealci@zte.com.cn Signed-off-by: Ye Guojin ye.guojin@zte.com.cn Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/cavium-octeon/octeon-platform.c | 2 ++ arch/mips/cavium-octeon/octeon-usb.c | 1 + 2 files changed, 3 insertions(+)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index d56e9b9d2e434..a994022e32c9f 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -328,6 +328,7 @@ static int __init octeon_ehci_device_init(void)
pd->dev.platform_data = &octeon_ehci_pdata; octeon_ehci_hw_start(&pd->dev); + put_device(&pd->dev);
return ret; } @@ -391,6 +392,7 @@ static int __init octeon_ohci_device_init(void)
pd->dev.platform_data = &octeon_ohci_pdata; octeon_ohci_hw_start(&pd->dev); + put_device(&pd->dev);
return ret; } diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/arch/mips/cavium-octeon/octeon-usb.c index 6e4d3619137af..4df919d26b082 100644 --- a/arch/mips/cavium-octeon/octeon-usb.c +++ b/arch/mips/cavium-octeon/octeon-usb.c @@ -537,6 +537,7 @@ static int __init dwc3_octeon_device_init(void) devm_iounmap(&pdev->dev, base); devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); + put_device(&pdev->dev); } } while (node != NULL);
From: Marc Zyngier maz@kernel.org
[ Upstream commit 79a7f77b9b154d572bd9d2f1eecf58c4d018d8e2 ]
Jay Chen reported that using a kdump kernel on a GICv4.1 system results in a RAS error being delivered when the secondary kernel configures the ITS's view of the new VPE table.
As it turns out, that's because each RD still has a pointer to the previous instance of the VPE table, and that particular implementation is very upset by seeing two bits of the HW that should point to the same table with different values.
To solve this, let's invalidate any reference that any RD has to the VPE table when discovering the RDs. The ITS can then be programmed as expected.
Reported-by: Jay Chen jkchen@linux.alibaba.com Signed-off-by: Marc Zyngier maz@kernel.org Cc: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Link: https://lore.kernel.org/r/20211214064716.21407-1-jkchen@linux.alibaba.com Link: https://lore.kernel.org/r/20211216144804.1578566-1-maz@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/irqchip/irq-gic-v3.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index daec3309b014d..86397522e7864 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -920,6 +920,22 @@ static int __gic_update_rdist_properties(struct redist_region *region, { u64 typer = gic_read_typer(ptr + GICR_TYPER);
+ /* Boot-time cleanip */ + if ((typer & GICR_TYPER_VLPIS) && (typer & GICR_TYPER_RVPEID)) { + u64 val; + + /* Deactivate any present vPE */ + val = gicr_read_vpendbaser(ptr + SZ_128K + GICR_VPENDBASER); + if (val & GICR_VPENDBASER_Valid) + gicr_write_vpendbaser(GICR_VPENDBASER_PendingLast, + ptr + SZ_128K + GICR_VPENDBASER); + + /* Mark the VPE table as invalid */ + val = gicr_read_vpropbaser(ptr + SZ_128K + GICR_VPROPBASER); + val &= ~GICR_VPROPBASER_4_1_VALID; + gicr_write_vpropbaser(val, ptr + SZ_128K + GICR_VPROPBASER); + } + gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
/* RVPEID implies some form of DirectLPI, no matter what the doc says... :-/ */
From: Lakshmi Sowjanya D lakshmi.sowjanya.d@intel.com
[ Upstream commit d52097010078c1844348dc0e467305e5f90fd317 ]
The data type of hcnt and lcnt in the struct dw_i2c_dev is of type u16. It's better to have same data type in struct dw_scl_sda_cfg as well.
Reported-by: Wolfram Sang wsa@kernel.org Signed-off-by: Lakshmi Sowjanya D lakshmi.sowjanya.d@intel.com Signed-off-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-designware-pcidrv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 0f409a4c2da0d..5b45941bcbddc 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -39,10 +39,10 @@ enum dw_pci_ctl_id_t { };
struct dw_scl_sda_cfg { - u32 ss_hcnt; - u32 fs_hcnt; - u32 ss_lcnt; - u32 fs_lcnt; + u16 ss_hcnt; + u16 fs_hcnt; + u16 ss_lcnt; + u16 fs_lcnt; u32 sda_hold; };
From: Thomas Gleixner tglx@linutronix.de
[ Upstream commit 3f35d2cf9fbc656db82579d849cc69c373b1ad0d ]
The MSI core will introduce runtime allocation of MSI related data. This data will be devres managed and has to be set up before enabling PCI/MSI[-X]. This would introduce an ordering issue vs. pcim_release().
The setup order is:
pcim_enable_device() devres_alloc(pcim_release...); ... pci_irq_alloc() msi_setup_device_data() devres_alloc(msi_device_data_release, ...)
and once the device is released these release functions are invoked in the opposite order:
msi_device_data_release() ... pcim_release() pci_disable_msi[x]()
which is obviously wrong, because pci_disable_msi[x]() requires the MSI data to be available to tear down the MSI[-X] interrupts.
Remove the MSI[-X] teardown from pcim_release() and add an explicit action to be installed on the attempt of enabling PCI/MSI[-X].
This allows the MSI core data allocation to be ordered correctly in a subsequent step.
Reported-by: Nishanth Menon nm@ti.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Tested-by: Michael Kelley mikelley@microsoft.com Tested-by: Nishanth Menon nm@ti.com Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Link: https://lore.kernel.org/r/87tuf9rdoj.ffs@tglx Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/msi.c | 33 +++++++++++++++++++++++++++++++++ drivers/pci/pci.c | 5 ----- include/linux/pci.h | 3 ++- 3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d84cf30bb2790..1093f099846eb 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -461,6 +461,31 @@ void pci_restore_msi_state(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_restore_msi_state);
+static void pcim_msi_release(void *pcidev) +{ + struct pci_dev *dev = pcidev; + + dev->is_msi_managed = false; + pci_free_irq_vectors(dev); +} + +/* + * Needs to be separate from pcim_release to prevent an ordering problem + * vs. msi_device_data_release() in the MSI core code. + */ +static int pcim_setup_msi_release(struct pci_dev *dev) +{ + int ret; + + if (!pci_is_managed(dev) || dev->is_msi_managed) + return 0; + + ret = devm_add_action(&dev->dev, pcim_msi_release, dev); + if (!ret) + dev->is_msi_managed = true; + return ret; +} + static struct msi_desc * msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) { @@ -1029,6 +1054,10 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, if (nvec > maxvec) nvec = maxvec;
+ rc = pcim_setup_msi_release(dev); + if (rc) + return rc; + for (;;) { if (affd) { nvec = irq_calc_affinity_vectors(minvec, nvec, affd); @@ -1072,6 +1101,10 @@ static int __pci_enable_msix_range(struct pci_dev *dev, if (WARN_ON_ONCE(dev->msix_enabled)) return -EINVAL;
+ rc = pcim_setup_msi_release(dev); + if (rc) + return rc; + for (;;) { if (affd) { nvec = irq_calc_affinity_vectors(minvec, nvec, affd); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3d2fb394986a4..f3f606c232a8a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2024,11 +2024,6 @@ static void pcim_release(struct device *gendev, void *res) struct pci_devres *this = res; int i;
- if (dev->msi_enabled) - pci_disable_msi(dev); - if (dev->msix_enabled) - pci_disable_msix(dev); - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) if (this->region_mask & (1 << i)) pci_release_region(dev, i); diff --git a/include/linux/pci.h b/include/linux/pci.h index 18a75c8e615cd..e26000404e3c3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -425,7 +425,8 @@ struct pci_dev { unsigned int ats_enabled:1; /* Address Translation Svc */ unsigned int pasid_enabled:1; /* Process Address Space ID */ unsigned int pri_enabled:1; /* Page Request Interface */ - unsigned int is_managed:1; + unsigned int is_managed:1; /* Managed via devres */ + unsigned int is_msi_managed:1; /* MSI release via devres installed */ unsigned int needs_freset:1; /* Requires fundamental reset */ unsigned int state_saved:1; unsigned int is_physfn:1;
On Mon, Jan 17, 2022 at 11:58:37AM -0500, Sasha Levin wrote:
From: Thomas Gleixner tglx@linutronix.de
[ Upstream commit 3f35d2cf9fbc656db82579d849cc69c373b1ad0d ]
The MSI core will introduce runtime allocation of MSI related data. This data will be devres managed and has to be set up before enabling PCI/MSI[-X]. This would introduce an ordering issue vs. pcim_release().
The setup order is:
pcim_enable_device() devres_alloc(pcim_release...); ... pci_irq_alloc() msi_setup_device_data() devres_alloc(msi_device_data_release, ...)
and once the device is released these release functions are invoked in the opposite order:
msi_device_data_release() ... pcim_release() pci_disable_msi[x]()
which is obviously wrong, because pci_disable_msi[x]() requires the MSI data to be available to tear down the MSI[-X] interrupts.
Remove the MSI[-X] teardown from pcim_release() and add an explicit action to be installed on the attempt of enabling PCI/MSI[-X].
This allows the MSI core data allocation to be ordered correctly in a subsequent step.
Reported-by: Nishanth Menon nm@ti.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Tested-by: Michael Kelley mikelley@microsoft.com Tested-by: Nishanth Menon nm@ti.com Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Link: https://lore.kernel.org/r/87tuf9rdoj.ffs@tglx Signed-off-by: Sasha Levin sashal@kernel.org
drivers/pci/msi.c | 33 +++++++++++++++++++++++++++++++++ drivers/pci/pci.c | 5 ----- include/linux/pci.h | 3 ++- 3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d84cf30bb2790..1093f099846eb 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -461,6 +461,31 @@ void pci_restore_msi_state(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_restore_msi_state); +static void pcim_msi_release(void *pcidev) +{
- struct pci_dev *dev = pcidev;
- dev->is_msi_managed = false;
- pci_free_irq_vectors(dev);
+}
+/*
- Needs to be separate from pcim_release to prevent an ordering problem
- vs. msi_device_data_release() in the MSI core code.
- */
+static int pcim_setup_msi_release(struct pci_dev *dev) +{
- int ret;
- if (!pci_is_managed(dev) || dev->is_msi_managed)
return 0;
- ret = devm_add_action(&dev->dev, pcim_msi_release, dev);
- if (!ret)
dev->is_msi_managed = true;
- return ret;
+}
static struct msi_desc * msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) { @@ -1029,6 +1054,10 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, if (nvec > maxvec) nvec = maxvec;
- rc = pcim_setup_msi_release(dev);
- if (rc)
return rc;
- for (;;) { if (affd) { nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
@@ -1072,6 +1101,10 @@ static int __pci_enable_msix_range(struct pci_dev *dev, if (WARN_ON_ONCE(dev->msix_enabled)) return -EINVAL;
- rc = pcim_setup_msi_release(dev);
- if (rc)
return rc;
- for (;;) { if (affd) { nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3d2fb394986a4..f3f606c232a8a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2024,11 +2024,6 @@ static void pcim_release(struct device *gendev, void *res) struct pci_devres *this = res; int i;
- if (dev->msi_enabled)
pci_disable_msi(dev);
- if (dev->msix_enabled)
pci_disable_msix(dev);
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) if (this->region_mask & (1 << i)) pci_release_region(dev, i);
diff --git a/include/linux/pci.h b/include/linux/pci.h index 18a75c8e615cd..e26000404e3c3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -425,7 +425,8 @@ struct pci_dev { unsigned int ats_enabled:1; /* Address Translation Svc */ unsigned int pasid_enabled:1; /* Process Address Space ID */ unsigned int pri_enabled:1; /* Page Request Interface */
- unsigned int is_managed:1;
- unsigned int is_managed:1; /* Managed via devres */
- unsigned int is_msi_managed:1; /* MSI release via devres installed */ unsigned int needs_freset:1; /* Requires fundamental reset */ unsigned int state_saved:1; unsigned int is_physfn:1;
-- 2.34.1
I do not think this is needed for the stable trees, as it only showed up in the MSI rework that Thomas added for 5.17-rc1. So please drop this from all of the AUTOSEL kernels.
thanks,
greg k-h
On Mon, Jan 17, 2022 at 06:08:34PM +0100, Greg Kroah-Hartman wrote:
On Mon, Jan 17, 2022 at 11:58:37AM -0500, Sasha Levin wrote:
From: Thomas Gleixner tglx@linutronix.de
[ Upstream commit 3f35d2cf9fbc656db82579d849cc69c373b1ad0d ]
The MSI core will introduce runtime allocation of MSI related data. This data will be devres managed and has to be set up before enabling PCI/MSI[-X]. This would introduce an ordering issue vs. pcim_release().
The setup order is:
pcim_enable_device() devres_alloc(pcim_release...); ... pci_irq_alloc() msi_setup_device_data() devres_alloc(msi_device_data_release, ...)
and once the device is released these release functions are invoked in the opposite order:
msi_device_data_release() ... pcim_release() pci_disable_msi[x]()
which is obviously wrong, because pci_disable_msi[x]() requires the MSI data to be available to tear down the MSI[-X] interrupts.
Remove the MSI[-X] teardown from pcim_release() and add an explicit action to be installed on the attempt of enabling PCI/MSI[-X].
This allows the MSI core data allocation to be ordered correctly in a subsequent step.
Reported-by: Nishanth Menon nm@ti.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Tested-by: Michael Kelley mikelley@microsoft.com Tested-by: Nishanth Menon nm@ti.com Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Link: https://lore.kernel.org/r/87tuf9rdoj.ffs@tglx Signed-off-by: Sasha Levin sashal@kernel.org
drivers/pci/msi.c | 33 +++++++++++++++++++++++++++++++++ drivers/pci/pci.c | 5 ----- include/linux/pci.h | 3 ++- 3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d84cf30bb2790..1093f099846eb 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -461,6 +461,31 @@ void pci_restore_msi_state(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_restore_msi_state);
+static void pcim_msi_release(void *pcidev) +{
- struct pci_dev *dev = pcidev;
- dev->is_msi_managed = false;
- pci_free_irq_vectors(dev);
+}
+/*
- Needs to be separate from pcim_release to prevent an ordering problem
- vs. msi_device_data_release() in the MSI core code.
- */
+static int pcim_setup_msi_release(struct pci_dev *dev) +{
- int ret;
- if (!pci_is_managed(dev) || dev->is_msi_managed)
return 0;
- ret = devm_add_action(&dev->dev, pcim_msi_release, dev);
- if (!ret)
dev->is_msi_managed = true;
- return ret;
+}
static struct msi_desc * msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) { @@ -1029,6 +1054,10 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, if (nvec > maxvec) nvec = maxvec;
- rc = pcim_setup_msi_release(dev);
- if (rc)
return rc;
- for (;;) { if (affd) { nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
@@ -1072,6 +1101,10 @@ static int __pci_enable_msix_range(struct pci_dev *dev, if (WARN_ON_ONCE(dev->msix_enabled)) return -EINVAL;
- rc = pcim_setup_msi_release(dev);
- if (rc)
return rc;
- for (;;) { if (affd) { nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3d2fb394986a4..f3f606c232a8a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2024,11 +2024,6 @@ static void pcim_release(struct device *gendev, void *res) struct pci_devres *this = res; int i;
- if (dev->msi_enabled)
pci_disable_msi(dev);
- if (dev->msix_enabled)
pci_disable_msix(dev);
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) if (this->region_mask & (1 << i)) pci_release_region(dev, i);
diff --git a/include/linux/pci.h b/include/linux/pci.h index 18a75c8e615cd..e26000404e3c3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -425,7 +425,8 @@ struct pci_dev { unsigned int ats_enabled:1; /* Address Translation Svc */ unsigned int pasid_enabled:1; /* Process Address Space ID */ unsigned int pri_enabled:1; /* Page Request Interface */
- unsigned int is_managed:1;
- unsigned int is_managed:1; /* Managed via devres */
- unsigned int is_msi_managed:1; /* MSI release via devres installed */ unsigned int needs_freset:1; /* Requires fundamental reset */ unsigned int state_saved:1; unsigned int is_physfn:1;
-- 2.34.1
I do not think this is needed for the stable trees, as it only showed up in the MSI rework that Thomas added for 5.17-rc1. So please drop this from all of the AUTOSEL kernels.
Dropped, thanks!
From: Qi Liu liuqi115@huawei.com
[ Upstream commit 16775db613c2bdea09705dcb876942c0641a1098 ]
If we issue a controller reset command during executing a FLR a hung task may be found:
Call trace: __switch_to+0x158/0x1cc __schedule+0x2e8/0x85c schedule+0x7c/0x110 schedule_timeout+0x190/0x1cc __down+0x7c/0xd4 down+0x5c/0x7c hisi_sas_task_exec+0x510/0x680 [hisi_sas_main] hisi_sas_queue_command+0x24/0x30 [hisi_sas_main] smp_execute_task_sg+0xf4/0x23c [libsas] sas_smp_phy_control+0x110/0x1e0 [libsas] transport_sas_phy_reset+0xc8/0x190 [libsas] phy_reset_work+0x2c/0x40 [libsas] process_one_work+0x1dc/0x48c worker_thread+0x15c/0x464 kthread+0x160/0x170 ret_from_fork+0x10/0x18
This is a race condition which occurs when the FLR completes first.
Here the host HISI_SAS_RESETTING_BIT flag out gets of sync as HISI_SAS_RESETTING_BIT is not always cleared with the hisi_hba.sem held, so now only set/unset HISI_SAS_RESETTING_BIT under hisi_hba.sem .
Link: https://lore.kernel.org/r/1639579061-179473-7-git-send-email-john.garry@huaw... Signed-off-by: Qi Liu liuqi115@huawei.com Signed-off-by: John Garry john.garry@huawei.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/hisi_sas/hisi_sas_main.c | 8 +++++--- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 + 2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index f206c433de325..8a13bc08d6575 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1581,7 +1581,6 @@ void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba) { struct Scsi_Host *shost = hisi_hba->shost;
- down(&hisi_hba->sem); hisi_hba->phy_state = hisi_hba->hw->get_phys_state(hisi_hba);
scsi_block_requests(shost); @@ -1606,9 +1605,9 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) if (hisi_hba->reject_stp_links_msk) hisi_sas_terminate_stp_reject(hisi_hba); hisi_sas_reset_init_all_devices(hisi_hba); - up(&hisi_hba->sem); scsi_unblock_requests(shost); clear_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags); + up(&hisi_hba->sem);
hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state); } @@ -1619,8 +1618,11 @@ static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba) if (!hisi_hba->hw->soft_reset) return -1;
- if (test_and_set_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags)) + down(&hisi_hba->sem); + if (test_and_set_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags)) { + up(&hisi_hba->sem); return -1; + }
if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) hisi_hba->hw->debugfs_snapshot_regs(hisi_hba); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 0ef6c21bf0811..11a44d9dd9b2d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -4848,6 +4848,7 @@ static void hisi_sas_reset_prepare_v3_hw(struct pci_dev *pdev) int rc;
dev_info(dev, "FLR prepare\n"); + down(&hisi_hba->sem); set_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags); hisi_sas_controller_reset_prepare(hisi_hba);
From: Ajit Kumar Pandey AjitKumar.Pandey@amd.com
[ Upstream commit 182b682b9ab1348e07ea1bf9d8f2505cc67f9237 ]
When pcm stream is stopped "substream->runtime" pointer will be set to NULL by ALSA core. In case host received an ipc msg from firmware of type IPC_STREAM_POSITION after pcm stream is stopped, there will be kernel NULL pointer exception in ipc_period_elapsed(). This patch fixes it by adding NULL pointer check for "substream->runtime".
Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Ajit Kumar Pandey AjitKumar.Pandey@amd.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20211216232422.345164-3-pierre-louis.bossart@linux... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/ipc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index e6c53c6c470e4..ca30c506a0fd6 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -547,7 +547,8 @@ static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
if (spcm->pcm.compress) snd_sof_compr_fragment_elapsed(stream->cstream); - else if (!stream->substream->runtime->no_period_wakeup) + else if (stream->substream->runtime && + !stream->substream->runtime->no_period_wakeup) /* only inform ALSA for period_wakeup mode */ snd_sof_pcm_period_elapsed(stream->substream); }
From: Michael Ellerman mpe@ellerman.id.au
[ Upstream commit a8968521cfdc3e339fe69473d6632e0aa8d7202a ]
We have a general signal fuzzer, sigfuz, which can modify the MSR & NIP before sigreturn. But the chance of it hitting a kernel address and also clearing MSR_PR is fairly slim.
So add a specific test of sigreturn to a kernel address, both with and without attempting to clear MSR_PR (which the kernel must block).
Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20211209115944.4062384-1-mpe@ellerman.id.au Signed-off-by: Sasha Levin sashal@kernel.org --- .../selftests/powerpc/signal/.gitignore | 1 + .../testing/selftests/powerpc/signal/Makefile | 1 + .../powerpc/signal/sigreturn_kernel.c | 132 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tools/testing/selftests/powerpc/signal/sigreturn_kernel.c
diff --git a/tools/testing/selftests/powerpc/signal/.gitignore b/tools/testing/selftests/powerpc/signal/.gitignore index ce3375cd8e73e..8f6c816099a48 100644 --- a/tools/testing/selftests/powerpc/signal/.gitignore +++ b/tools/testing/selftests/powerpc/signal/.gitignore @@ -4,3 +4,4 @@ signal_tm sigfuz sigreturn_vdso sig_sc_double_restart +sigreturn_kernel diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile index d6ae54663aed7..84e201572466d 100644 --- a/tools/testing/selftests/powerpc/signal/Makefile +++ b/tools/testing/selftests/powerpc/signal/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 TEST_GEN_PROGS := signal signal_tm sigfuz sigreturn_vdso sig_sc_double_restart +TEST_GEN_PROGS += sigreturn_kernel
CFLAGS += -maltivec $(OUTPUT)/signal_tm: CFLAGS += -mhtm diff --git a/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c b/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c new file mode 100644 index 0000000000000..0a1b6e591eeed --- /dev/null +++ b/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test that we can't sigreturn to kernel addresses, or to kernel mode. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <signal.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "utils.h" + +#define MSR_PR (1ul << 14) + +static volatile unsigned long long sigreturn_addr; +static volatile unsigned long long sigreturn_msr_mask; + +static void sigusr1_handler(int signo, siginfo_t *si, void *uc_ptr) +{ + ucontext_t *uc = (ucontext_t *)uc_ptr; + + if (sigreturn_addr) + UCONTEXT_NIA(uc) = sigreturn_addr; + + if (sigreturn_msr_mask) + UCONTEXT_MSR(uc) &= sigreturn_msr_mask; +} + +static pid_t fork_child(void) +{ + pid_t pid; + + pid = fork(); + if (pid == 0) { + raise(SIGUSR1); + exit(0); + } + + return pid; +} + +static int expect_segv(pid_t pid) +{ + int child_ret; + + waitpid(pid, &child_ret, 0); + FAIL_IF(WIFEXITED(child_ret)); + FAIL_IF(!WIFSIGNALED(child_ret)); + FAIL_IF(WTERMSIG(child_ret) != 11); + + return 0; +} + +int test_sigreturn_kernel(void) +{ + struct sigaction act; + int child_ret, i; + pid_t pid; + + act.sa_sigaction = sigusr1_handler; + act.sa_flags = SA_SIGINFO; + sigemptyset(&act.sa_mask); + + FAIL_IF(sigaction(SIGUSR1, &act, NULL)); + + for (i = 0; i < 2; i++) { + // Return to kernel + sigreturn_addr = 0xcull << 60; + pid = fork_child(); + expect_segv(pid); + + // Return to kernel virtual + sigreturn_addr = 0xc008ull << 48; + pid = fork_child(); + expect_segv(pid); + + // Return out of range + sigreturn_addr = 0xc010ull << 48; + pid = fork_child(); + expect_segv(pid); + + // Return to no-man's land, just below PAGE_OFFSET + sigreturn_addr = (0xcull << 60) - (64 * 1024); + pid = fork_child(); + expect_segv(pid); + + // Return to no-man's land, above TASK_SIZE_4PB + sigreturn_addr = 0x1ull << 52; + pid = fork_child(); + expect_segv(pid); + + // Return to 0xd space + sigreturn_addr = 0xdull << 60; + pid = fork_child(); + expect_segv(pid); + + // Return to 0xe space + sigreturn_addr = 0xeull << 60; + pid = fork_child(); + expect_segv(pid); + + // Return to 0xf space + sigreturn_addr = 0xfull << 60; + pid = fork_child(); + expect_segv(pid); + + // Attempt to set PR=0 for 2nd loop (should be blocked by kernel) + sigreturn_msr_mask = ~MSR_PR; + } + + printf("All children killed as expected\n"); + + // Don't change address, just MSR, should return to user as normal + sigreturn_addr = 0; + sigreturn_msr_mask = ~MSR_PR; + pid = fork_child(); + waitpid(pid, &child_ret, 0); + FAIL_IF(!WIFEXITED(child_ret)); + FAIL_IF(WIFSIGNALED(child_ret)); + FAIL_IF(WEXITSTATUS(child_ret) != 0); + + return 0; +} + +int main(void) +{ + return test_harness(test_sigreturn_kernel, "sigreturn_kernel"); +}
From: Tianjia Zhang tianjia.zhang@linux.alibaba.com
[ Upstream commit 95339b70677dc6f9a2d669c4716058e71b8dc1c7 ]
A large number of the following errors is reported when compiling with clang:
cvmx-bootinfo.h:326:3: error: adding 'int' to a string does not append to the string [-Werror,-Wstring-plus-int] ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cvmx-bootinfo.h:321:20: note: expanded from macro 'ENUM_BRD_TYPE_CASE' case x: return(#x + 16); /* Skip CVMX_BOARD_TYPE_ */ ~~~^~~~ cvmx-bootinfo.h:326:3: note: use array indexing to silence this warning cvmx-bootinfo.h:321:20: note: expanded from macro 'ENUM_BRD_TYPE_CASE' case x: return(#x + 16); /* Skip CVMX_BOARD_TYPE_ */ ^
Follow the prompts to use the address operator '&' to fix this error.
Signed-off-by: Tianjia Zhang tianjia.zhang@linux.alibaba.com Reviewed-by: Nathan Chancellor nathan@kernel.org Reviewed-by: Philippe Mathieu-Daudé f4bug@amsat.org Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/octeon/cvmx-bootinfo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index 0e6bf220db618..6c61e0a639249 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -318,7 +318,7 @@ enum cvmx_chip_types_enum {
/* Functions to return string based on type */ #define ENUM_BRD_TYPE_CASE(x) \ - case x: return(#x + 16); /* Skip CVMX_BOARD_TYPE_ */ + case x: return (&#x[16]); /* Skip CVMX_BOARD_TYPE_ */ static inline const char *cvmx_board_type_to_string(enum cvmx_board_types_enum type) { @@ -410,7 +410,7 @@ static inline const char *cvmx_board_type_to_string(enum }
#define ENUM_CHIP_TYPE_CASE(x) \ - case x: return(#x + 15); /* Skip CVMX_CHIP_TYPE */ + case x: return (&#x[15]); /* Skip CVMX_CHIP_TYPE */ static inline const char *cvmx_chip_type_to_string(enum cvmx_chip_types_enum type) {
From: Christoph Hellwig hch@lst.de
[ Upstream commit d94d94969a4ba07a43d62429c60372320519c391 ]
The allocated buffers are used as a command payload, for which the block layer and/or DMA API do the proper bounce buffering if needed.
Link: https://lore.kernel.org/r/20211222090842.920724-1-hch@lst.de Reported-by: Baoquan He bhe@redhat.com Reviewed-by: Baoquan He bhe@redhat.com Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/sr.c | 2 +- drivers/scsi/sr_vendor.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 8e4af111c0787..f5a2eed543452 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -856,7 +856,7 @@ static void get_capabilities(struct scsi_cd *cd)
/* allocate transfer buffer */ - buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL); if (!buffer) { sr_printk(KERN_ERR, cd, "out of memory.\n"); return; diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c index 1f988a1b9166f..a61635326ae0a 100644 --- a/drivers/scsi/sr_vendor.c +++ b/drivers/scsi/sr_vendor.c @@ -131,7 +131,7 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) if (cd->vendor == VENDOR_TOSHIBA) density = (blocklength > 2048) ? 0x81 : 0x83;
- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL); if (!buffer) return -ENOMEM;
@@ -179,7 +179,7 @@ int sr_cd_check(struct cdrom_device_info *cdi) if (cd->cdi.mask & CDC_MULTI_SESSION) return 0;
- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL); if (!buffer) return -ENOMEM;
From: Sreekanth Reddy sreekanth.reddy@broadcom.com
[ Upstream commit 243bcc8efdb1f44b1a1d415e6821a246714c68ce ]
Set reply queue depth of 1K for B0 and 4K for A0.
While freeing the segmented request queues use the actual queue depth that is used while creating them.
Link: https://lore.kernel.org/r/20211220141159.16117-25-sreekanth.reddy@broadcom.c... Signed-off-by: Sreekanth Reddy sreekanth.reddy@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/mpi3mr/mpi3mr.h | 3 ++- drivers/scsi/mpi3mr/mpi3mr_fw.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 9787b53a2b598..2cc42432bd0c0 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -79,7 +79,8 @@ extern int prot_mask;
/* Operational queue management definitions */ #define MPI3MR_OP_REQ_Q_QD 512 -#define MPI3MR_OP_REP_Q_QD 4096 +#define MPI3MR_OP_REP_Q_QD 1024 +#define MPI3MR_OP_REP_Q_QD4K 4096 #define MPI3MR_OP_REQ_Q_SEG_SIZE 4096 #define MPI3MR_OP_REP_Q_SEG_SIZE 4096 #define MPI3MR_MAX_SEG_LIST_SIZE 4096 diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index aa5d877df6f83..2daf633ea2955 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -1278,7 +1278,7 @@ static void mpi3mr_free_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx) mrioc->op_reply_qinfo[q_idx].q_segment_list = NULL; } } else - size = mrioc->req_qinfo[q_idx].num_requests * + size = mrioc->req_qinfo[q_idx].segment_qd * mrioc->facts.op_req_sz;
for (j = 0; j < mrioc->req_qinfo[q_idx].num_segments; j++) { @@ -1565,6 +1565,8 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
reply_qid = qidx + 1; op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; + if (!mrioc->pdev->revision) + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K; op_reply_q->ci = 0; op_reply_q->ephase = 1; atomic_set(&op_reply_q->pend_ios, 0);
From: Tzung-Bi Shih tzungbi@google.com
[ Upstream commit 4e28491a7a198c668437f2be8a91a76aa52f20eb ]
The of_parse_phandle() document: >>> Use of_node_put() on it when done.
The driver didn't call of_node_put(). Fixes the leak.
Signed-off-by: Tzung-Bi Shih tzungbi@google.com Link: https://lore.kernel.org/r/20211214040028.2992627-1-tzungbi@google.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index a606133951b70..24a5d0adec1ba 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -1172,7 +1172,11 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev) return ret; }
- return devm_snd_soc_register_card(&pdev->dev, card); + ret = devm_snd_soc_register_card(&pdev->dev, card); + + of_node_put(platform_node); + of_node_put(hdmi_codec); + return ret; }
#ifdef CONFIG_OF
From: Chunfeng Yun chunfeng.yun@mediatek.com
[ Upstream commit 6f2b033cb883f64ad084a75f13634242c7e179a6 ]
Due to some SoCs have a bit shift issue that will drop a bit for usb3 phy or pcie phy, fix it by adding software efuse reading and setting, but only support it optionally for version 2/3.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com Link: https://lore.kernel.org/r/20211218082802.5256-2-chunfeng.yun@mediatek.com Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/mediatek/phy-mtk-tphy.c | 162 ++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+)
diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index cdcef865fe9e5..98a942c607a67 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -12,6 +12,7 @@ #include <linux/iopoll.h> #include <linux/mfd/syscon.h> #include <linux/module.h> +#include <linux/nvmem-consumer.h> #include <linux/of_address.h> #include <linux/of_device.h> #include <linux/phy/phy.h> @@ -41,6 +42,9 @@ #define SSUSB_SIFSLV_V2_U3PHYD 0x200 #define SSUSB_SIFSLV_V2_U3PHYA 0x400
+#define U3P_MISC_REG1 0x04 +#define MR1_EFUSE_AUTO_LOAD_DIS BIT(6) + #define U3P_USBPHYACR0 0x000 #define PA0_RG_U2PLL_FORCE_ON BIT(15) #define PA0_USB20_PLL_PREDIV GENMASK(7, 6) @@ -133,6 +137,8 @@ #define P3C_RG_SWRST_U3_PHYD_FORCE_EN BIT(24)
#define U3P_U3_PHYA_REG0 0x000 +#define P3A_RG_IEXT_INTR GENMASK(15, 10) +#define P3A_RG_IEXT_INTR_VAL(x) ((0x3f & (x)) << 10) #define P3A_RG_CLKDRV_OFF GENMASK(3, 2) #define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2)
@@ -187,6 +193,19 @@ #define P3D_RG_FWAKE_TH GENMASK(21, 16) #define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
+#define U3P_U3_PHYD_IMPCAL0 0x010 +#define P3D_RG_FORCE_TX_IMPEL BIT(31) +#define P3D_RG_TX_IMPEL GENMASK(28, 24) +#define P3D_RG_TX_IMPEL_VAL(x) ((0x1f & (x)) << 24) + +#define U3P_U3_PHYD_IMPCAL1 0x014 +#define P3D_RG_FORCE_RX_IMPEL BIT(31) +#define P3D_RG_RX_IMPEL GENMASK(28, 24) +#define P3D_RG_RX_IMPEL_VAL(x) ((0x1f & (x)) << 24) + +#define U3P_U3_PHYD_RSV 0x054 +#define P3D_RG_EFUSE_AUTO_LOAD_DIS BIT(12) + #define U3P_U3_PHYD_CDR1 0x05c #define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24) #define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24) @@ -307,6 +326,11 @@ struct mtk_phy_pdata { * 48M PLL, fix it by switching PLL to 26M from default 48M */ bool sw_pll_48m_to_26m; + /* + * Some SoCs (e.g. mt8195) drop a bit when use auto load efuse, + * support sw way, also support it for v2/v3 optionally. + */ + bool sw_efuse_supported; enum mtk_phy_version version; };
@@ -336,6 +360,10 @@ struct mtk_phy_instance { struct regmap *type_sw; u32 type_sw_reg; u32 type_sw_index; + u32 efuse_sw_en; + u32 efuse_intr; + u32 efuse_tx_imp; + u32 efuse_rx_imp; int eye_src; int eye_vrt; int eye_term; @@ -1040,6 +1068,130 @@ static int phy_type_set(struct mtk_phy_instance *instance) return 0; }
+static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instance) +{ + struct device *dev = &instance->phy->dev; + int ret = 0; + + /* tphy v1 doesn't support sw efuse, skip it */ + if (!tphy->pdata->sw_efuse_supported) { + instance->efuse_sw_en = 0; + return 0; + } + + /* software efuse is optional */ + instance->efuse_sw_en = device_property_read_bool(dev, "nvmem-cells"); + if (!instance->efuse_sw_en) + return 0; + + switch (instance->type) { + case PHY_TYPE_USB2: + ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr); + if (ret) { + dev_err(dev, "fail to get u2 intr efuse, %d\n", ret); + break; + } + + /* no efuse, ignore it */ + if (!instance->efuse_intr) { + dev_warn(dev, "no u2 intr efuse, but dts enable it\n"); + instance->efuse_sw_en = 0; + break; + } + + dev_dbg(dev, "u2 efuse - intr %x\n", instance->efuse_intr); + break; + + case PHY_TYPE_USB3: + case PHY_TYPE_PCIE: + ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr); + if (ret) { + dev_err(dev, "fail to get u3 intr efuse, %d\n", ret); + break; + } + + ret = nvmem_cell_read_variable_le_u32(dev, "rx_imp", &instance->efuse_rx_imp); + if (ret) { + dev_err(dev, "fail to get u3 rx_imp efuse, %d\n", ret); + break; + } + + ret = nvmem_cell_read_variable_le_u32(dev, "tx_imp", &instance->efuse_tx_imp); + if (ret) { + dev_err(dev, "fail to get u3 tx_imp efuse, %d\n", ret); + break; + } + + /* no efuse, ignore it */ + if (!instance->efuse_intr && + !instance->efuse_rx_imp && + !instance->efuse_rx_imp) { + dev_warn(dev, "no u3 intr efuse, but dts enable it\n"); + instance->efuse_sw_en = 0; + break; + } + + dev_dbg(dev, "u3 efuse - intr %x, rx_imp %x, tx_imp %x\n", + instance->efuse_intr, instance->efuse_rx_imp,instance->efuse_tx_imp); + break; + default: + dev_err(dev, "no sw efuse for type %d\n", instance->type); + ret = -EINVAL; + } + + return ret; +} + +static void phy_efuse_set(struct mtk_phy_instance *instance) +{ + struct device *dev = &instance->phy->dev; + struct u2phy_banks *u2_banks = &instance->u2_banks; + struct u3phy_banks *u3_banks = &instance->u3_banks; + u32 tmp; + + if (!instance->efuse_sw_en) + return; + + switch (instance->type) { + case PHY_TYPE_USB2: + tmp = readl(u2_banks->misc + U3P_MISC_REG1); + tmp |= MR1_EFUSE_AUTO_LOAD_DIS; + writel(tmp, u2_banks->misc + U3P_MISC_REG1); + + tmp = readl(u2_banks->com + U3P_USBPHYACR1); + tmp &= ~PA1_RG_INTR_CAL; + tmp |= PA1_RG_INTR_CAL_VAL(instance->efuse_intr); + writel(tmp, u2_banks->com + U3P_USBPHYACR1); + break; + case PHY_TYPE_USB3: + case PHY_TYPE_PCIE: + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); + tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS; + writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RSV); + + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); + tmp &= ~P3D_RG_TX_IMPEL; + tmp |= P3D_RG_TX_IMPEL_VAL(instance->efuse_tx_imp); + tmp |= P3D_RG_FORCE_TX_IMPEL; + writel(tmp, u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); + + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); + tmp &= ~P3D_RG_RX_IMPEL; + tmp |= P3D_RG_RX_IMPEL_VAL(instance->efuse_rx_imp); + tmp |= P3D_RG_FORCE_RX_IMPEL; + writel(tmp, u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); + + tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0); + tmp &= ~P3A_RG_IEXT_INTR; + tmp |= P3A_RG_IEXT_INTR_VAL(instance->efuse_intr); + writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0); + break; + default: + dev_warn(dev, "no sw efuse for type %d\n", instance->type); + break; + } +} + static int mtk_phy_init(struct phy *phy) { struct mtk_phy_instance *instance = phy_get_drvdata(phy); @@ -1050,6 +1202,8 @@ static int mtk_phy_init(struct phy *phy) if (ret) return ret;
+ phy_efuse_set(instance); + switch (instance->type) { case PHY_TYPE_USB2: u2_phy_instance_init(tphy, instance); @@ -1134,6 +1288,7 @@ static struct phy *mtk_phy_xlate(struct device *dev, struct mtk_phy_instance *instance = NULL; struct device_node *phy_np = args->np; int index; + int ret;
if (args->args_count != 1) { dev_err(dev, "invalid number of cells in 'phy' property\n"); @@ -1174,6 +1329,10 @@ static struct phy *mtk_phy_xlate(struct device *dev, return ERR_PTR(-EINVAL); }
+ ret = phy_efuse_get(tphy, instance); + if (ret) + return ERR_PTR(ret); + phy_parse_property(tphy, instance); phy_type_set(instance);
@@ -1196,10 +1355,12 @@ static const struct mtk_phy_pdata tphy_v1_pdata = {
static const struct mtk_phy_pdata tphy_v2_pdata = { .avoid_rx_sen_degradation = false, + .sw_efuse_supported = true, .version = MTK_PHY_V2, };
static const struct mtk_phy_pdata tphy_v3_pdata = { + .sw_efuse_supported = true, .version = MTK_PHY_V3, };
@@ -1210,6 +1371,7 @@ static const struct mtk_phy_pdata mt8173_pdata = {
static const struct mtk_phy_pdata mt8195_pdata = { .sw_pll_48m_to_26m = true, + .sw_efuse_supported = true, .version = MTK_PHY_V3, };
From: Tzung-Bi Shih tzungbi@google.com
[ Upstream commit 493433785df0075afc0c106ab65f10a605d0b35d ]
Fixes the device_node leak.
Signed-off-by: Tzung-Bi Shih tzungbi@google.com Link: https://lore.kernel.org/r/20211224064719.2031210-2-tzungbi@google.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/mediatek/mt8173/mt8173-max98090.c | 3 +++ sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c | 2 ++ sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c | 2 ++ sound/soc/mediatek/mt8173/mt8173-rt5650.c | 2 ++ 4 files changed, 9 insertions(+)
diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c index fc94314bfc02f..3bdd4931316cd 100644 --- a/sound/soc/mediatek/mt8173/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c @@ -180,6 +180,9 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev) if (ret) dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", __func__, ret); + + of_node_put(codec_node); + of_node_put(platform_node); return ret; }
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c index 0f28dc2217c09..390da5bf727eb 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c @@ -218,6 +218,8 @@ static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev) if (ret) dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", __func__, ret); + + of_node_put(platform_node); return ret; }
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c index 077c6ee067806..c8e4e85e10575 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c @@ -285,6 +285,8 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) if (ret) dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", __func__, ret); + + of_node_put(platform_node); return ret; }
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index 2cbf679f5c74b..d8cf0802813a0 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -323,6 +323,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) if (ret) dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", __func__, ret); + + of_node_put(platform_node); return ret; }
From: Tzung-Bi Shih tzungbi@google.com
[ Upstream commit cb006006fe6221f092fadaffd3f219288304c9ad ]
Fixes the device_node leak.
Signed-off-by: Tzung-Bi Shih tzungbi@google.com Link: https://lore.kernel.org/r/20211224064719.2031210-3-tzungbi@google.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 6 +++++- sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index a4d26a6fc8492..bda103211e0bd 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -781,7 +781,11 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) return ret; }
- return devm_snd_soc_register_card(&pdev->dev, card); + ret = devm_snd_soc_register_card(&pdev->dev, card); + + of_node_put(platform_node); + of_node_put(hdmi_codec); + return ret; }
#ifdef CONFIG_OF diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index aeb1af86047ef..9f0bf15fe465e 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -780,7 +780,12 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) __func__, ret); }
- return devm_snd_soc_register_card(&pdev->dev, card); + ret = devm_snd_soc_register_card(&pdev->dev, card); + + of_node_put(platform_node); + of_node_put(ec_codec); + of_node_put(hdmi_codec); + return ret; }
#ifdef CONFIG_OF
From: Dani Liberman dliberman@habana.ai
[ Upstream commit 48f31169830f589e4c7ac475ccc7414951ded3f0 ]
In order to increase maximum wait-for-interrupt timeout, change it to 64 bit variable. This wait is used only by newer ASICs, so no problem in changing this interface at this time.
Signed-off-by: Dani Liberman dliberman@habana.ai Reviewed-by: Oded Gabbay ogabbay@kernel.org Signed-off-by: Oded Gabbay ogabbay@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../habanalabs/common/command_submission.c | 22 ++++++++++++++----- include/uapi/misc/habanalabs.h | 18 +++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index 4c8000fd246cd..9451e4bae05df 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -2765,8 +2765,23 @@ static int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data) return 0; }
+static inline unsigned long hl_usecs64_to_jiffies(const u64 usecs) +{ + if (usecs <= U32_MAX) + return usecs_to_jiffies(usecs); + + /* + * If the value in nanoseconds is larger than 64 bit, use the largest + * 64 bit value. + */ + if (usecs >= ((u64)(U64_MAX / NSEC_PER_USEC))) + return nsecs_to_jiffies(U64_MAX); + + return nsecs_to_jiffies(usecs * NSEC_PER_USEC); +} + static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, - u32 timeout_us, u64 user_address, + u64 timeout_us, u64 user_address, u64 target_value, u16 interrupt_offset, enum hl_cs_wait_status *status, u64 *timestamp) @@ -2778,10 +2793,7 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, long completion_rc; int rc = 0;
- if (timeout_us == U32_MAX) - timeout = timeout_us; - else - timeout = usecs_to_jiffies(timeout_us); + timeout = hl_usecs64_to_jiffies(timeout_us);
hl_ctx_get(hdev, ctx);
diff --git a/include/uapi/misc/habanalabs.h b/include/uapi/misc/habanalabs.h index 00b3095904995..c5760acebdd1d 100644 --- a/include/uapi/misc/habanalabs.h +++ b/include/uapi/misc/habanalabs.h @@ -911,14 +911,18 @@ struct hl_wait_cs_in { */ __u32 flags;
- /* Multi CS API info- valid entries in multi-CS array */ - __u8 seq_arr_len; - __u8 pad[3]; + union { + struct { + /* Multi CS API info- valid entries in multi-CS array */ + __u8 seq_arr_len; + __u8 pad[7]; + };
- /* Absolute timeout to wait for an interrupt in microseconds. - * Relevant only when HL_WAIT_CS_FLAGS_INTERRUPT is set - */ - __u32 interrupt_timeout_us; + /* Absolute timeout to wait for an interrupt in microseconds. + * Relevant only when HL_WAIT_CS_FLAGS_INTERRUPT is set + */ + __u64 interrupt_timeout_us; + }; };
#define HL_WAIT_CS_STATUS_COMPLETED 0
From: Ohad Sharabi osharabi@habana.ai
[ Upstream commit 4fac990f604e6c10538026835a8a30f3c1b6fcf5 ]
Reporting FW errors involves reading of the error registers.
In case we have a corrupted FW descriptor we cannot do that since the dynamic scratchpad is potentially corrupted as well and may cause kernel crush when attempting access to a corrupted register offset.
Signed-off-by: Ohad Sharabi osharabi@habana.ai Reviewed-by: Oded Gabbay ogabbay@kernel.org Signed-off-by: Oded Gabbay ogabbay@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/habanalabs/common/firmware_if.c | 17 +++++++++++++++-- drivers/misc/habanalabs/common/habanalabs.h | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c index 4e68fb9d2a6bd..67a0be4573710 100644 --- a/drivers/misc/habanalabs/common/firmware_if.c +++ b/drivers/misc/habanalabs/common/firmware_if.c @@ -1703,6 +1703,9 @@ static int hl_fw_dynamic_validate_descriptor(struct hl_device *hdev, return rc; }
+ /* here we can mark the descriptor as valid as the content has been validated */ + fw_loader->dynamic_loader.fw_desc_valid = true; + return 0; }
@@ -1759,7 +1762,13 @@ static int hl_fw_dynamic_read_and_validate_descriptor(struct hl_device *hdev, return rc; }
- /* extract address copy the descriptor from */ + /* + * extract address to copy the descriptor from + * in addition, as the descriptor value is going to be over-ridden by new data- we mark it + * as invalid. + * it will be marked again as valid once validated + */ + fw_loader->dynamic_loader.fw_desc_valid = false; src = hdev->pcie_bar[region->bar_id] + region->offset_in_bar + response->ram_offset; memcpy_fromio(fw_desc, src, sizeof(struct lkd_fw_comms_desc)); @@ -2247,6 +2256,9 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, dev_info(hdev->dev, "Loading firmware to device, may take some time...\n");
+ /* initialize FW descriptor as invalid */ + fw_loader->dynamic_loader.fw_desc_valid = false; + /* * In this stage, "cpu_dyn_regs" contains only LKD's hard coded values! * It will be updated from FW after hl_fw_dynamic_request_descriptor(). @@ -2333,7 +2345,8 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, return 0;
protocol_err: - fw_read_errors(hdev, le32_to_cpu(dyn_regs->cpu_boot_err0), + if (fw_loader->dynamic_loader.fw_desc_valid) + fw_read_errors(hdev, le32_to_cpu(dyn_regs->cpu_boot_err0), le32_to_cpu(dyn_regs->cpu_boot_err1), le32_to_cpu(dyn_regs->cpu_boot_dev_sts0), le32_to_cpu(dyn_regs->cpu_boot_dev_sts1)); diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index a2002cbf794b5..ba0965667b182 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -1010,6 +1010,7 @@ struct fw_response { * @image_region: region to copy the FW image to * @fw_image_size: size of FW image to load * @wait_for_bl_timeout: timeout for waiting for boot loader to respond + * @fw_desc_valid: true if FW descriptor has been validated and hence the data can be used */ struct dynamic_fw_load_mgr { struct fw_response response; @@ -1017,6 +1018,7 @@ struct dynamic_fw_load_mgr { struct pci_mem_region *image_region; size_t fw_image_size; u32 wait_for_bl_timeout; + bool fw_desc_valid; };
/**
From: Miaoqian Lin linmq006@gmail.com
[ Upstream commit 399c91c3f30531593e5ff6ca7b53f47092128669 ]
The of_device_get_match_data() function may return NULL. Add check to prevent potential null dereference.
Signed-off-by: Miaoqian Lin linmq006@gmail.com Reviewed-by: AngeloGioacchino Del Regno angelogioacchino.delregno@collabora.com Link: https://lore.kernel.org/r/20211224082103.7658-1-linmq006@gmail.com Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/mediatek/phy-mtk-mipi-dsi.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c index 28ad9403c4414..67b005d5b9e35 100644 --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c @@ -146,6 +146,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) return -ENOMEM;
mipi_tx->driver_data = of_device_get_match_data(dev); + if (!mipi_tx->driver_data) + return -ENODEV;
mipi_tx->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mipi_tx->regs))
From: Ajit Kumar Pandey AjitKumar.Pandey@amd.com
[ Upstream commit 7112550890d7e415188a3351ec0a140be60f6deb ]
RT1019 components was initially registered with i2c1 and i2c2 but now changed to i2c0 and i2c1 in most of our AMD platforms. Change default rt1019 components to 10EC1019:00 and 10EC1019:01 which is aligned with most of AMD machines.
Any exception to rt1019 device ids in near future board design can be handled using dmi based quirk for that machine.
Signed-off-by: Ajit Kumar Pandey AjitKumar.Pandey@amd.com Link: https://lore.kernel.org/r/20220106150525.396170-1-AjitKumar.Pandey@amd.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/amd/acp/acp-mach-common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index 7785f12aa0065..7386e5bb61b5e 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -268,8 +268,8 @@ static const struct snd_soc_ops acp_card_rt5682s_ops = {
/* Declare RT1019 codec components */ SND_SOC_DAILINK_DEF(rt1019, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"), - COMP_CODEC("i2c-10EC1019:02", "rt1019-aif"))); + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"), + COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));
static const struct snd_soc_dapm_route rt1019_map_lr[] = { { "Left Spk", NULL, "Left SPO" }, @@ -278,11 +278,11 @@ static const struct snd_soc_dapm_route rt1019_map_lr[] = {
static struct snd_soc_codec_conf rt1019_conf[] = { { - .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), + .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"), .name_prefix = "Left", }, { - .dlc = COMP_CODEC_CONF("i2c-10EC1019:02"), + .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), .name_prefix = "Right", }, };
On Mon, Jan 17, 2022 at 11:58:51AM -0500, Sasha Levin wrote:
From: Ajit Kumar Pandey AjitKumar.Pandey@amd.com
[ Upstream commit 7112550890d7e415188a3351ec0a140be60f6deb ]
RT1019 components was initially registered with i2c1 and i2c2 but now changed to i2c0 and i2c1 in most of our AMD platforms. Change default rt1019 components to 10EC1019:00 and 10EC1019:01 which is aligned with most of AMD machines.
This seems like a disruptive change to be backporting into stable...
On Tue, Jan 18, 2022 at 04:18:45PM +0000, Mark Brown wrote:
On Mon, Jan 17, 2022 at 11:58:51AM -0500, Sasha Levin wrote:
From: Ajit Kumar Pandey AjitKumar.Pandey@amd.com
[ Upstream commit 7112550890d7e415188a3351ec0a140be60f6deb ]
RT1019 components was initially registered with i2c1 and i2c2 but now changed to i2c0 and i2c1 in most of our AMD platforms. Change default rt1019 components to 10EC1019:00 and 10EC1019:01 which is aligned with most of AMD machines.
This seems like a disruptive change to be backporting into stable...
I'll drop it, thanks!
From: Conor Dooley conor.dooley@microchip.com
[ Upstream commit f10b1fc0161cd99e54c5687fcc63368aa255e05e ]
The Polarfire SoC is currently using two different compatible string prefixes. Fix this by changing "polarfire-soc-*" strings to "mpfs-*" in its system controller in order to match the compatible string used in the soc binding and device tree.
Signed-off-by: Conor Dooley conor.dooley@microchip.com Reviewed-by: Geert Uytterhoeven geert@linux-m68k.org Signed-off-by: Jassi Brar jaswinder.singh@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mailbox/mailbox-mpfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c index 0d6e2231a2c75..4e34854d12389 100644 --- a/drivers/mailbox/mailbox-mpfs.c +++ b/drivers/mailbox/mailbox-mpfs.c @@ -232,7 +232,7 @@ static int mpfs_mbox_probe(struct platform_device *pdev) }
static const struct of_device_id mpfs_mbox_of_match[] = { - {.compatible = "microchip,polarfire-soc-mailbox", }, + {.compatible = "microchip,mpfs-mailbox", }, {}, }; MODULE_DEVICE_TABLE(of, mpfs_mbox_of_match);
From: Linus Walleij linus.walleij@linaro.org
[ Upstream commit b7f1ac9bb6413b739ea91bd61bdf23c9130a8007 ]
The board file using this driver has been deleted and the FSG3 LEDs can be modeled using a system controller and some register bit LEDs in the device tree so this driver is no longer needed.
Reported-by: Lukas Bulwahn lukas.bulwahn@gmail.com Cc: Krzysztof Hałasa khalasa@piap.pl Cc: Rod Whitby rod@whitby.id.au Signed-off-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Pavel Machek pavel@ucw.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/leds/Kconfig | 7 -- drivers/leds/Makefile | 1 - drivers/leds/leds-fsg.c | 193 ---------------------------------------- 3 files changed, 201 deletions(-) delete mode 100644 drivers/leds/leds-fsg.c
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index ed800f5da7d88..c262ee4453494 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -260,13 +260,6 @@ config LEDS_NET48XX This option enables support for the Soekris net4801 and net4826 error LED.
-config LEDS_FSG - tristate "LED Support for the Freecom FSG-3" - depends on LEDS_CLASS - depends on MACH_FSG - help - This option enables support for the LEDs on the Freecom FSG-3. - config LEDS_WRAP tristate "LED Support for the WRAP series LEDs" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index c636ec069612d..36506bddcc303 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o obj-$(CONFIG_LEDS_CPCAP) += leds-cpcap.o obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o -obj-$(CONFIG_LEDS_FSG) += leds-fsg.o obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c deleted file mode 100644 index bc6b420637d61..0000000000000 --- a/drivers/leds/leds-fsg.c +++ /dev/null @@ -1,193 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * LED Driver for the Freecom FSG-3 - * - * Copyright (c) 2008 Rod Whitby rod@whitby.id.au - * - * Author: Rod Whitby rod@whitby.id.au - * - * Based on leds-spitz.c - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie rpurdie@openedhand.com - */ - -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/leds.h> -#include <linux/module.h> -#include <linux/io.h> -#include <mach/hardware.h> - -#define FSG_LED_WLAN_BIT 0 -#define FSG_LED_WAN_BIT 1 -#define FSG_LED_SATA_BIT 2 -#define FSG_LED_USB_BIT 4 -#define FSG_LED_RING_BIT 5 -#define FSG_LED_SYNC_BIT 7 - -static short __iomem *latch_address; -static unsigned short latch_value; - - -static void fsg_led_wlan_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) { - latch_value &= ~(1 << FSG_LED_WLAN_BIT); - *latch_address = latch_value; - } else { - latch_value |= (1 << FSG_LED_WLAN_BIT); - *latch_address = latch_value; - } -} - -static void fsg_led_wan_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) { - latch_value &= ~(1 << FSG_LED_WAN_BIT); - *latch_address = latch_value; - } else { - latch_value |= (1 << FSG_LED_WAN_BIT); - *latch_address = latch_value; - } -} - -static void fsg_led_sata_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) { - latch_value &= ~(1 << FSG_LED_SATA_BIT); - *latch_address = latch_value; - } else { - latch_value |= (1 << FSG_LED_SATA_BIT); - *latch_address = latch_value; - } -} - -static void fsg_led_usb_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) { - latch_value &= ~(1 << FSG_LED_USB_BIT); - *latch_address = latch_value; - } else { - latch_value |= (1 << FSG_LED_USB_BIT); - *latch_address = latch_value; - } -} - -static void fsg_led_sync_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) { - latch_value &= ~(1 << FSG_LED_SYNC_BIT); - *latch_address = latch_value; - } else { - latch_value |= (1 << FSG_LED_SYNC_BIT); - *latch_address = latch_value; - } -} - -static void fsg_led_ring_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) { - latch_value &= ~(1 << FSG_LED_RING_BIT); - *latch_address = latch_value; - } else { - latch_value |= (1 << FSG_LED_RING_BIT); - *latch_address = latch_value; - } -} - - -static struct led_classdev fsg_wlan_led = { - .name = "fsg:blue:wlan", - .brightness_set = fsg_led_wlan_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static struct led_classdev fsg_wan_led = { - .name = "fsg:blue:wan", - .brightness_set = fsg_led_wan_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static struct led_classdev fsg_sata_led = { - .name = "fsg:blue:sata", - .brightness_set = fsg_led_sata_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static struct led_classdev fsg_usb_led = { - .name = "fsg:blue:usb", - .brightness_set = fsg_led_usb_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static struct led_classdev fsg_sync_led = { - .name = "fsg:blue:sync", - .brightness_set = fsg_led_sync_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static struct led_classdev fsg_ring_led = { - .name = "fsg:blue:ring", - .brightness_set = fsg_led_ring_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - - -static int fsg_led_probe(struct platform_device *pdev) -{ - int ret; - - /* Map the LED chip select address space */ - latch_address = (unsigned short *) devm_ioremap(&pdev->dev, - IXP4XX_EXP_BUS_BASE(2), 512); - if (!latch_address) - return -ENOMEM; - - latch_value = 0xffff; - *latch_address = latch_value; - - ret = devm_led_classdev_register(&pdev->dev, &fsg_wlan_led); - if (ret < 0) - return ret; - - ret = devm_led_classdev_register(&pdev->dev, &fsg_wan_led); - if (ret < 0) - return ret; - - ret = devm_led_classdev_register(&pdev->dev, &fsg_sata_led); - if (ret < 0) - return ret; - - ret = devm_led_classdev_register(&pdev->dev, &fsg_usb_led); - if (ret < 0) - return ret; - - ret = devm_led_classdev_register(&pdev->dev, &fsg_sync_led); - if (ret < 0) - return ret; - - ret = devm_led_classdev_register(&pdev->dev, &fsg_ring_led); - if (ret < 0) - return ret; - - return ret; -} - -static struct platform_driver fsg_led_driver = { - .probe = fsg_led_probe, - .driver = { - .name = "fsg-led", - }, -}; - -module_platform_driver(fsg_led_driver); - -MODULE_AUTHOR("Rod Whitby rod@whitby.id.au"); -MODULE_DESCRIPTION("Freecom FSG-3 LED driver"); -MODULE_LICENSE("GPL");
linux-stable-mirror@lists.linaro.org