* [PATCH v2 1/2] media: aspeed: join IRQ and work before probe cleanup
2026-11-10 4:58 [PATCH v2 0/2] media: aspeed: order probe cleanup and last close Myeonghun Pak
@ 2026-11-10 4:58 ` Myeonghun Pak
2026-11-10 4:58 ` [PATCH v2 2/2] media: aspeed: drain IRQ work before stopping the engine Myeonghun Pak
1 sibling, 0 replies; 3+ messages in thread
From: Myeonghun Pak @ 2026-11-10 4:58 UTC (permalink / raw)
To: Eddie James, Mauro Carvalho Chehab
Cc: Jammy Huang, Joel Stanley, Andrew Jeffery, Ryan Chen, Billy Tsai,
linux-media, openbmc, linux-arm-kernel, linux-aspeed,
linux-kernel, Ijae Kim
The setup failure path unprepares the clocks before devres frees the IRQ.
An IRQ handler that has sampled an enabled status can still queue
resolution work. Masking the source does not synchronize that handler.
Save the IRQ number after a successful request, then free the action and
drain resolution work before the manual JPEG and clock cleanup. Turn the
engine off after the work has finished. Request the IRQ after reset,
clock and JPEG initialization so earlier init failures have no live IRQ.
Fixes: 3536169f8531 ("media: aspeed: fix clock handling logic")
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
No hardware testing.
With reset-default masking, no probe IRQ failure has been demonstrated;
this part hardens cleanup ordering.
Changes in v2:
- Join the IRQ and resolution work before manual probe-failure cleanup.
- Rebase onto managed reserved-memory initialization.
- Clean up JPEG and clocks if the late IRQ request fails.
- Split normal last-close ordering into patch 2.
drivers/media/platform/aspeed/aspeed-video.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/media/platform/aspeed/aspeed-video.c b/drivers/media/platform/aspeed/aspeed-video.c
--- a/drivers/media/platform/aspeed/aspeed-video.c
+++ b/drivers/media/platform/aspeed/aspeed-video.c
@@ -308,6 +308,7 @@
* perf: holds the statistics primary for debugfs
*/
struct aspeed_video {
+ int irq;
void __iomem *base;
struct clk *eclk;
struct clk *vclk;
@@ -2232,14 +2233,6 @@
return -ENODEV;
}
- rc = devm_request_threaded_irq(dev, irq, NULL, aspeed_video_irq,
- IRQF_ONESHOT, DEVICE_NAME, video);
- if (rc < 0) {
- dev_err(dev, "Unable to request IRQ %d\n", irq);
- return rc;
- }
- dev_info(video->dev, "irq %d\n", irq);
-
video->reset = devm_reset_control_get(dev, NULL);
if (IS_ERR(video->reset)) {
dev_err(dev, "Unable to get reset\n");
@@ -2286,8 +2279,19 @@
aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
+ rc = devm_request_threaded_irq(dev, irq, NULL, aspeed_video_irq,
+ IRQF_ONESHOT, DEVICE_NAME, video);
+ if (rc < 0) {
+ dev_err(dev, "Unable to request IRQ %d\n", irq);
+ goto err_free_jpeg;
+ }
+ video->irq = irq;
+ dev_info(video->dev, "irq %d\n", irq);
+
return 0;
+err_free_jpeg:
+ aspeed_video_free_buf(video, &video->jpeg);
err_unprepare_vclk:
clk_unprepare(video->vclk);
err_unprepare_eclk:
@@ -2341,6 +2345,10 @@
rc = aspeed_video_setup_video(video);
if (rc) {
+ set_bit(VIDEO_STOPPED, &video->flags);
+ devm_free_irq(video->dev, video->irq, video);
+ cancel_delayed_work_sync(&video->res_work);
+ aspeed_video_off(video);
aspeed_video_free_buf(video, &video->jpeg);
clk_unprepare(video->vclk);
clk_unprepare(video->eclk);
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH v2 2/2] media: aspeed: drain IRQ work before stopping the engine
2026-11-10 4:58 [PATCH v2 0/2] media: aspeed: order probe cleanup and last close Myeonghun Pak
2026-11-10 4:58 ` [PATCH v2 1/2] media: aspeed: join IRQ and work before probe cleanup Myeonghun Pak
@ 2026-11-10 4:58 ` Myeonghun Pak
1 sibling, 0 replies; 3+ messages in thread
From: Myeonghun Pak @ 2026-11-10 4:58 UTC (permalink / raw)
To: Eddie James, Mauro Carvalho Chehab
Cc: Jammy Huang, Joel Stanley, Andrew Jeffery, Ryan Chen, Billy Tsai,
linux-media, openbmc, linux-arm-kernel, linux-aspeed,
linux-kernel, Ijae Kim
Last close cancels resolution work while its IRQ producer is still live.
A handler can queue work after cancellation and buffer cleanup. The worker
can then turn clocks back on after stop has cleared VIDEO_STOPPED.
Release the VB2 queue before shutting down the engine, since streamoff
can need capture and mode-detect interrupts. Disable and join the IRQ,
drain work, stop the engine and free its buffers before re-enabling the
IRQ. Check VIDEO_STOPPED before enabling clocks in the worker.
Fixes: d2b4387f3bdf ("media: platform: Add Aspeed Video Engine driver")
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
No hardware testing.
Changes in v2:
- Split normal last-close ordering into a separate patch.
- Balance IRQ disable/enable within stop; add no reopen state.
drivers/media/platform/aspeed/aspeed-video.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/media/platform/aspeed/aspeed-video.c b/drivers/media/platform/aspeed/aspeed-video.c
--- a/drivers/media/platform/aspeed/aspeed-video.c
+++ b/drivers/media/platform/aspeed/aspeed-video.c
@@ -1423,6 +1423,7 @@
static void aspeed_video_stop(struct aspeed_video *video)
{
set_bit(VIDEO_STOPPED, &video->flags);
+ disable_irq(video->irq);
cancel_delayed_work_sync(&video->res_work);
aspeed_video_off(video);
@@ -1438,6 +1439,7 @@
video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
video->flags = 0;
+ enable_irq(video->irq);
}
static int aspeed_video_querycap(struct file *file, void *fh,
@@ -1847,11 +1849,11 @@
struct aspeed_video *video = container_of(dwork, struct aspeed_video,
res_work);
- aspeed_video_on(video);
-
/* Exit early in case no clients remain */
if (test_bit(VIDEO_STOPPED, &video->flags))
goto done;
+
+ aspeed_video_on(video);
aspeed_video_init_regs(video);
@@ -1901,15 +1903,17 @@
static int aspeed_video_release(struct file *file)
{
+ bool last;
int rc;
struct aspeed_video *video = video_drvdata(file);
mutex_lock(&video->video_lock);
- if (v4l2_fh_is_singular_file(file))
+ last = v4l2_fh_is_singular_file(file);
+ rc = _vb2_fop_release(file, NULL);
+
+ if (last)
aspeed_video_stop(video);
-
- rc = _vb2_fop_release(file, NULL);
mutex_unlock(&video->video_lock);
^ permalink raw reply [flat|nested] 3+ messages in thread