FAILED: patch "[PATCH] spi: cadence-qspi: defer runtime support on socfpga if reset" failed to apply to 6.16-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.16-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.16.y
git checkout FETCH_HEAD
git cherry-pick -x 30dbc1c8d50f13c1581b49abe46fe89f393eacbf
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025092913-wriggly-condition-4b00@gregkh' --subject-prefix 'PATCH 6.16.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 30dbc1c8d50f13c1581b49abe46fe89f393eacbf Mon Sep 17 00:00:00 2001
From: Khairul Anuar Romli <[email protected]>
Date: Wed, 10 Sep 2025 16:06:32 +0800
Subject: [PATCH] spi: cadence-qspi: defer runtime support on socfpga if reset
bit is enabled
Enabling runtime PM allows the kernel to gate clocks and power to idle devices. On SoCFPGA, a warm reset does not fully reinitialize these domains.This leaves devices suspended and powered down, preventing U-Boot or the kernel from reusing them after a warm reset, which breaks the boot process.
drivers/spi/spi-cadence-quadspi.c +36 -17
@@ -46,6 +46,7 @@ static_assert(CQSPI_MAX_CHIPSELECT <= SPI_CS_CNT_MAX);#define CQSPI_DMA_SET_MASK BIT(7)#define CQSPI_SUPPORT_DEVICE_RESET BIT(8)#define CQSPI_DISABLE_STIG_MODE BIT(9) +#define CQSPI_DISABLE_RUNTIME_PM BIT(10)/* Capabilities */ #define CQSPI_SUPPORTS_OCTAL BIT(0)
@@ -1468,14 +1469,17 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)int ret;struct cqspi_st *cqspi =spi_controller_get_devdata (mem->spi->controller);struct device *dev = &cqspi->pdev->dev; +const struct cqspi_driver_platdata *ddata =of_device_get_match_data (dev);if (refcount_read (&cqspi->inflight_ops) ==0 )return -ENODEV ; - ret =pm_runtime_resume_and_get (dev); -if (ret) { -dev_err (&mem->spi->dev,"resume failed with %d\n" , ret); -return ret; +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { + ret =pm_runtime_resume_and_get (dev); +if (ret) { +dev_err (&mem->spi->dev,"resume failed with %d\n" , ret); +return ret; + } }if (!refcount_read (&cqspi->refcount))
@@ -1491,7 +1495,8 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) ret =cqspi_mem_process (mem, op); -pm_runtime_put_autosuspend (dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) +pm_runtime_put_autosuspend (dev);if (ret)dev_err (&mem->spi->dev,"operation failed with %d\n" , ret);
@@ -1985,11 +1990,12 @@ static int cqspi_probe(struct platform_device *pdev) goto probe_setup_failed; } -pm_runtime_enable (dev); - -pm_runtime_set_autosuspend_delay (dev,CQSPI_AUTOSUSPEND_TIMEOUT ); -pm_runtime_use_autosuspend (dev); -pm_runtime_get_noresume (dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { +pm_runtime_enable (dev); +pm_runtime_set_autosuspend_delay (dev,CQSPI_AUTOSUSPEND_TIMEOUT ); +pm_runtime_use_autosuspend (dev); +pm_runtime_get_noresume (dev); + } ret =spi_register_controller (host);if (ret) {
@@ -1997,12 +2003,17 @@ static int cqspi_probe(struct platform_device *pdev) goto probe_setup_failed; } -pm_runtime_put_autosuspend (dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { +pm_runtime_put_autosuspend (dev); +pm_runtime_mark_last_busy (dev); +pm_runtime_put_autosuspend (dev); + }return 0 ; probe_setup_failed:cqspi_controller_enable (cqspi,0 ); -pm_runtime_disable (dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) +pm_runtime_disable (dev); probe_reset_failed:if (cqspi->is_jh7110)cqspi_jh7110_disable_clk (pdev, cqspi);
@@ -2013,7 +2024,11 @@ static int cqspi_probe(struct platform_device *pdev)static void cqspi_remove (struct platform_device *pdev) { +const struct cqspi_driver_platdata *ddata;struct cqspi_st *cqspi =platform_get_drvdata (pdev); +struct device *dev = &pdev->dev; + + ddata =of_device_get_match_data (dev);refcount_set (&cqspi->refcount,0 );
@@ -2026,14 +2041,17 @@ static void cqspi_remove(struct platform_device *pdev)if (cqspi->rx_chan)dma_release_channel (cqspi->rx_chan); -if (pm_runtime_get_sync (&pdev->dev) >=0 ) -clk_disable (cqspi->clk); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) +if (pm_runtime_get_sync (&pdev->dev) >=0 ) +clk_disable (cqspi->clk);if (cqspi->is_jh7110)cqspi_jh7110_disable_clk (pdev, cqspi); -pm_runtime_put_sync (&pdev->dev); -pm_runtime_disable (&pdev->dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { +pm_runtime_put_sync (&pdev->dev); +pm_runtime_disable (&pdev->dev); + } }static int cqspi_runtime_suspend (struct device *dev)
@@ -2112,7 +2130,8 @@ static const struct cqspi_driver_platdata socfpga_qspi = { .quirks = CQSPI_DISABLE_DAC_MODE |CQSPI_NO_SUPPORT_WR_COMPLETION |CQSPI_SLOW_SRAM - | CQSPI_DISABLE_STIG_MODE, + |CQSPI_DISABLE_STIG_MODE + | CQSPI_DISABLE_RUNTIME_PM, };static const struct cqspi_driver_platdata versal_ospi = {
Sasha Levin
maintainerPATCH 1/2 spi: cadence-quadspi: Implement refcount to handle unbind during busy
From: Khairul Anuar Romli <[email protected]>
[ Upstream commit 7446284023e8ef694fb392348185349c773eefb3 ]
driver support indirect read and indirect write operation with assumption no force device removal(unbind) operation. However force device removal(removal) is still available to root superuser.
Unbinding driver during operation causes kernel crash. This changes ensure driver able to handle such operation for indirect read and indirect write by implementing refcount to track attached devices to the controller and gracefully wait and until attached devices remove operation completed before proceed with removal operation.
Stable-dep-of: 30dbc1c8d50f ("spi: cadence-qspi: defer runtime support on socfpga if reset bit is enabled")
--- drivers/spi/spi-cadence-quadspi.c | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
drivers/spi/spi-cadence-quadspi.c +33 -0
@@ -108,6 +108,8 @@ struct cqspi_st {bool is_jh7110;/* Flag for StarFive JH7110 SoC */ bool disable_stig_mode; +refcount_t refcount; +refcount_t inflight_ops;const struct cqspi_driver_platdata *ddata; };
@@ -735,6 +737,9 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,u8 *rxbuf_end = rxbuf + n_rx;int ret =0 ; +if (!refcount_read (&cqspi->refcount)) +return -ENODEV ; +writel (from_addr, reg_base +CQSPI_REG_INDIRECTRDSTARTADDR );writel (remaining, reg_base +CQSPI_REG_INDIRECTRDBYTES );
@@ -1071,6 +1076,9 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata,unsigned int write_bytes;int ret; +if (!refcount_read (&cqspi->refcount)) +return -ENODEV ; +writel (to_addr, reg_base +CQSPI_REG_INDIRECTWRSTARTADDR );writel (remaining, reg_base +CQSPI_REG_INDIRECTWRBYTES );
@@ -1461,12 +1469,26 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)struct cqspi_st *cqspi =spi_controller_get_devdata (mem->spi->controller);struct device *dev = &cqspi->pdev->dev; +if (refcount_read (&cqspi->inflight_ops) ==0 ) +return -ENODEV ; + ret =pm_runtime_resume_and_get (dev);if (ret) {dev_err (&mem->spi->dev,"resume failed with %d\n" , ret);return ret; } +if (!refcount_read (&cqspi->refcount)) +return -EBUSY ; + +refcount_inc (&cqspi->inflight_ops); + +if (!refcount_read (&cqspi->refcount)) { +if (refcount_read (&cqspi->inflight_ops)) +refcount_dec (&cqspi->inflight_ops); +return -EBUSY ; + } + ret =cqspi_mem_process (mem, op);pm_runtime_mark_last_busy (dev);
@@ -1475,6 +1497,9 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)if (ret)dev_err (&mem->spi->dev,"operation failed with %d\n" , ret); +if (refcount_read (&cqspi->inflight_ops) >1 ) +refcount_dec (&cqspi->inflight_ops); +return ret; }
@@ -1926,6 +1951,9 @@ static int cqspi_probe(struct platform_device *pdev) } } +refcount_set (&cqspi->refcount,1 ); +refcount_set (&cqspi->inflight_ops,1 ); + ret =devm_request_irq (dev, irq, cqspi_irq_handler,0 , pdev->name, cqspi);if (ret) {
@@ -1989,6 +2017,11 @@ static void cqspi_remove(struct platform_device *pdev) {struct cqspi_st *cqspi =platform_get_drvdata (pdev); +refcount_set (&cqspi->refcount,0 ); + +if (!refcount_dec_and_test (&cqspi->inflight_ops)) +cqspi_wait_idle (cqspi); +spi_unregister_controller (cqspi->host);cqspi_controller_enable (cqspi,0 );
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 2/2 spi: cadence-qspi: defer runtime support on socfpga if reset bit is enabled
From: Khairul Anuar Romli <[email protected]>
[ Upstream commit 30dbc1c8d50f13c1581b49abe46fe89f393eacbf ]
Enabling runtime PM allows the kernel to gate clocks and power to idle devices. On SoCFPGA, a warm reset does not fully reinitialize these domains.This leaves devices suspended and powered down, preventing U-Boot or the kernel from reusing them after a warm reset, which breaks the boot process.
--- drivers/spi/spi-cadence-quadspi.c | 57 ++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 19 deletions(-)
drivers/spi/spi-cadence-quadspi.c +38 -19
@@ -46,6 +46,7 @@ static_assert(CQSPI_MAX_CHIPSELECT <= SPI_CS_CNT_MAX);#define CQSPI_DMA_SET_MASK BIT(7)#define CQSPI_SUPPORT_DEVICE_RESET BIT(8)#define CQSPI_DISABLE_STIG_MODE BIT(9) +#define CQSPI_DISABLE_RUNTIME_PM BIT(10)/* Capabilities */ #define CQSPI_SUPPORTS_OCTAL BIT(0)
@@ -1468,14 +1469,17 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)int ret;struct cqspi_st *cqspi =spi_controller_get_devdata (mem->spi->controller);struct device *dev = &cqspi->pdev->dev; +const struct cqspi_driver_platdata *ddata =of_device_get_match_data (dev);if (refcount_read (&cqspi->inflight_ops) ==0 )return -ENODEV ; - ret =pm_runtime_resume_and_get (dev); -if (ret) { -dev_err (&mem->spi->dev,"resume failed with %d\n" , ret); -return ret; +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { + ret =pm_runtime_resume_and_get (dev); +if (ret) { +dev_err (&mem->spi->dev,"resume failed with %d\n" , ret); +return ret; + } }if (!refcount_read (&cqspi->refcount))
@@ -1491,8 +1495,10 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) ret =cqspi_mem_process (mem, op); -pm_runtime_mark_last_busy (dev); -pm_runtime_put_autosuspend (dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { +pm_runtime_mark_last_busy (dev); +pm_runtime_put_autosuspend (dev); + }if (ret)dev_err (&mem->spi->dev,"operation failed with %d\n" , ret);
@@ -1986,11 +1992,12 @@ static int cqspi_probe(struct platform_device *pdev) goto probe_setup_failed; } -pm_runtime_enable (dev); - -pm_runtime_set_autosuspend_delay (dev,CQSPI_AUTOSUSPEND_TIMEOUT ); -pm_runtime_use_autosuspend (dev); -pm_runtime_get_noresume (dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { +pm_runtime_enable (dev); +pm_runtime_set_autosuspend_delay (dev,CQSPI_AUTOSUSPEND_TIMEOUT ); +pm_runtime_use_autosuspend (dev); +pm_runtime_get_noresume (dev); + } ret =spi_register_controller (host);if (ret) {
@@ -1998,13 +2005,17 @@ static int cqspi_probe(struct platform_device *pdev) goto probe_setup_failed; } -pm_runtime_mark_last_busy (dev); -pm_runtime_put_autosuspend (dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { +pm_runtime_put_autosuspend (dev); +pm_runtime_mark_last_busy (dev); +pm_runtime_put_autosuspend (dev); + }return 0 ; probe_setup_failed:cqspi_controller_enable (cqspi,0 ); -pm_runtime_disable (dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) +pm_runtime_disable (dev); probe_reset_failed:if (cqspi->is_jh7110)cqspi_jh7110_disable_clk (pdev, cqspi);
@@ -2015,7 +2026,11 @@ static int cqspi_probe(struct platform_device *pdev)static void cqspi_remove (struct platform_device *pdev) { +const struct cqspi_driver_platdata *ddata;struct cqspi_st *cqspi =platform_get_drvdata (pdev); +struct device *dev = &pdev->dev; + + ddata =of_device_get_match_data (dev);refcount_set (&cqspi->refcount,0 );
@@ -2028,14 +2043,17 @@ static void cqspi_remove(struct platform_device *pdev)if (cqspi->rx_chan)dma_release_channel (cqspi->rx_chan); -if (pm_runtime_get_sync (&pdev->dev) >=0 ) -clk_disable (cqspi->clk); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) +if (pm_runtime_get_sync (&pdev->dev) >=0 ) +clk_disable (cqspi->clk);if (cqspi->is_jh7110)cqspi_jh7110_disable_clk (pdev, cqspi); -pm_runtime_put_sync (&pdev->dev); -pm_runtime_disable (&pdev->dev); +if (!(ddata && (ddata->quirks &CQSPI_DISABLE_RUNTIME_PM ))) { +pm_runtime_put_sync (&pdev->dev); +pm_runtime_disable (&pdev->dev); + } }static int cqspi_runtime_suspend (struct device *dev)
@@ -2114,7 +2132,8 @@ static const struct cqspi_driver_platdata socfpga_qspi = { .quirks = CQSPI_DISABLE_DAC_MODE |CQSPI_NO_SUPPORT_WR_COMPLETION |CQSPI_SLOW_SRAM - | CQSPI_DISABLE_STIG_MODE, + |CQSPI_DISABLE_STIG_MODE + | CQSPI_DISABLE_RUNTIME_PM, };static const struct cqspi_driver_platdata versal_ospi = {
Signature · 1 line
2.51.0