fbdev: hyperv_fb: framebuffer release cleanup
v3 cover fbdev: hyperv_fb: framebuffer release cleanup
This patch series addresses an issue in the unbind path of the hyperv_fb driver, which is resolved in the second patch of this series.
While working on this fix, it was observed that hvfb_putmem() and its child functions could be cleaned up first to simplify the movement of hvfb_putmem(). This cleanup is done in the first patch.
Although hvfb_getmem() could also be cleaned up, it depends on vmbus_allocate_mmio(), which is used by multiple other drivers. Since addressing hvfb_getmem() is independent of this fix, it will be handled in a separate patch series.
[V3]
- Add a patch 1 for cleanup of hvfb_putmem()
- Use the simplified hvfb_putmem()
Saurabh Sengar (2):
fbdev: hyperv_fb: Simplify hvfb_putmem
fbdev: hyperv_fb: Allow graceful removal of framebuffer
drivers/video/fbdev/hyperv_fb.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-)
Signature · 1 line
2.43.0
PATCH v3 1/2 fbdev: hyperv_fb: Simplify hvfb_putmem
The device object required in 'hvfb_release_phymem' function for 'dma_free_coherent' can also be obtained from the 'info' pointer, making 'hdev' parameter in 'hvfb_putmem' redundant. Remove the unnecessary 'hdev' argument from 'hvfb_putmem'.
--- drivers/video/fbdev/hyperv_fb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/video/fbdev/hyperv_fb.c +6 -6
@@ -952,7 +952,7 @@ static phys_addr_t hvfb_get_phymem(struct hv_device *hdev, }/* Release contiguous physical memory */ -static void hvfb_release_phymem (struct hv_device *hdev, +static void hvfb_release_phymem (struct device *device,phys_addr_t paddr,unsigned int size) {unsigned int order =get_order (size);
@@ -960,7 +960,7 @@ static void hvfb_release_phymem(struct hv_device *hdev,if (order <=MAX_PAGE_ORDER )__free_pages (pfn_to_page (paddr >>PAGE_SHIFT ), order);else -dma_free_coherent (&hdev->device, +dma_free_coherent (device,round_up (size,PAGE_SIZE ),phys_to_virt (paddr), paddr);
@@ -1074,7 +1074,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) }/* Release the framebuffer */ -static void hvfb_putmem (struct hv_device *hdev,struct fb_info *info) +static void hvfb_putmem (struct fb_info *info) {struct hvfb_par *par = info->par;
@@ -1083,7 +1083,7 @@ static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info)iounmap (par->mmio_vp);vmbus_free_mmio (par->mem->start, screen_fb_size); }else { -hvfb_release_phymem (hdev, info->fix.smem_start, +hvfb_release_phymem (info->device, info->fix.smem_start, screen_fb_size); }
@@ -1197,7 +1197,7 @@ static int hvfb_probe(struct hv_device *hdev, error:fb_deferred_io_cleanup (info); -hvfb_putmem (hdev, info); +hvfb_putmem (info); error2:vmbus_close (hdev->channel); error1:
@@ -1226,7 +1226,7 @@ static void hvfb_remove(struct hv_device *hdev)vmbus_close (hdev->channel);hv_set_drvdata (hdev,NULL ); -hvfb_putmem (hdev, info); +hvfb_putmem (info);framebuffer_release (info); }
Signature · 1 line
2.43.0
RE: [PATCH v3 1/2] fbdev: hyperv_fb: Simplify hvfb_putmem
From: Saurabh Sengar <[email protected]> Sent: Saturday, March 1, 2025 8:17 AM
Quoted 70 lines
The device object required in '
hvfb_release_phymem' function for 'dma_free_coherent' can also be obtained from the 'info' pointer, making 'hdev' parameter in 'hvfb_putmem' redundant. Remove the unnecessary 'hdev' argument from 'hvfb_putmem'.Signed-off-by Saurabh Sengar <[email protected]>--- drivers/video/fbdev/hyperv_fb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)drivers/video/fbdev/hyperv_fb.c +6
-7@@ -952,7 +952,7 @@ static phys_addr_t hvfb_get_phymem(struct hv_device *hdev, }/* Release contiguous physical memory */ -static void hvfb_release_phymem (struct hv_device *hdev, +static void hvfb_release_phymem (struct device *device,phys_addr_t paddr,unsigned int size) {unsigned int order =get_order (size);@@ -960,7 +960,7 @@ static void hvfb_release_phymem(struct hv_device *hdev,if (order <=MAX_PAGE_ORDER )__free_pages (pfn_to_page (paddr >>PAGE_SHIFT ), order);else -dma_free_coherent (&hdev->device, +dma_free_coherent (device,round_up (size,PAGE_SIZE ),phys_to_virt (paddr), paddr);@@ -1074,7 +1074,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) }/* Release the framebuffer */ -static void hvfb_putmem (struct hv_device *hdev,struct fb_info *info) +static void hvfb_putmem (struct fb_info *info) {struct hvfb_par *par = info->par;@@ -1083,7 +1083,7 @@ static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info)iounmap (par->mmio_vp);vmbus_free_mmio (par->mem->start, screen_fb_size); }else { -hvfb_release_phymem (hdev, info->fix.smem_start, +hvfb_release_phymem (info->device, info->fix.smem_start, screen_fb_size); }@@ -1197,7 +1197,7 @@ static int hvfb_probe(struct hv_device *hdev, error:fb_deferred_io_cleanup (info); -hvfb_putmem (hdev, info); +hvfb_putmem (info); error2:vmbus_close (hdev->channel); error1:@@ -1226,7 +1226,7 @@ static void hvfb_remove(struct hv_device *hdev)vmbus_close (hdev->channel);hv_set_drvdata (hdev,NULL ); -hvfb_putmem (hdev, info); +hvfb_putmem (info);framebuffer_release (info); } --
Quoted 1 line
2.43.0
PATCH v3 2/2 fbdev: hyperv_fb: Allow graceful removal of framebuffer
In reply to Saurabh SengarWhen a Hyper-V framebuffer device is unbind, hyperv_fb driver tries to release the framebuffer forcefully. If this framebuffer is in use it produce the following WARN and hence this framebuffer is never released.
[ 44.111220] WARNING: CPU: 35 PID: 1882 at drivers/video/fbdev/core/fb_info.c:70 framebuffer_release+0x2c/0x40 < snip > [ 44.111289] Call Trace: [ 44.111290] <TASK> [ 44.111291] ? show_regs+0x6c/0x80 [ 44.111295] ? __warn+0x8d/0x150 [ 44.111298] ? framebuffer_release+0x2c/0x40 [ 44.111300] ? report_bug+0x182/0x1b0 [ 44.111303] ? handle_bug+0x6e/0xb0 [ 44.111306] ? exc_invalid_op+0x18/0x80 [ 44.111308] ? asm_exc_invalid_op+0x1b/0x20 [ 44.111311] ? framebuffer_release+0x2c/0x40 [ 44.111313] ? hvfb_remove+0x86/0xa0 [hyperv_fb] [ 44.111315] vmbus_remove+0x24/0x40 [hv_vmbus] [ 44.111323] device_remove+0x40/0x80 [ 44.111325] device_release_driver_internal+0x20b/0x270 [ 44.111327] ? bus_find_device+0xb3/0xf0
Fix this by moving the release of framebuffer and assosiated memory to fb_ops.fb_destroy function, so that framebuffer framework handles it gracefully.
While we fix this, also replace manual registrations/unregistration of framebuffer with devm_register_framebuffer.
---
[V3]
- using simplified hvfb_putmem()
drivers/video/fbdev/hyperv_fb.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
drivers/video/fbdev/hyperv_fb.c +15 -5
@@ -282,6 +282,8 @@ static uint screen_depth;static uint screen_fb_size;static uint dio_fb_size;/* FB size for deferred IO */ +static void hvfb_putmem (struct fb_info *info); +/* Send message to Hyper-V host */ static inline int synthvid_send (struct hv_device *hdev,struct synthvid_msg *msg)
@@ -862,6 +864,17 @@ static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width,hvfb_ondemand_refresh_throttle (par, x, y, width, height); } +/* +* fb_ops.fb_destroy is called by the last put_fb_info() call at the end +* of unregister_framebuffer() or fb_release(). Do any cleanup related to +* framebuffer here. +*/ +static void hvfb_destroy (struct fb_info *info) +{ +hvfb_putmem (info); +framebuffer_release (info); +} +/* * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the * driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases.
@@ -877,6 +890,7 @@ static const struct fb_ops hvfb_ops = { .fb_set_par = hvfb_set_par, .fb_setcolreg = hvfb_setcolreg, .fb_blank = hvfb_blank, + .fb_destroy = hvfb_destroy, };/* Get options from kernel paramenter "video=" */
@@ -1172,7 +1186,7 @@ static int hvfb_probe(struct hv_device *hdev,if (ret) goto error; - ret =register_framebuffer (info); + ret =devm_register_framebuffer (&hdev->device, info);if (ret) {pr_err ("Unable to register framebuffer\n" ); goto error;
@@ -1220,14 +1234,10 @@ static void hvfb_remove(struct hv_device *hdev)fb_deferred_io_cleanup (info); -unregister_framebuffer (info);cancel_delayed_work_sync (&par->dwork);vmbus_close (hdev->channel);hv_set_drvdata (hdev,NULL ); - -hvfb_putmem (info); -framebuffer_release (info); }static int hvfb_suspend (struct hv_device *hdev)
Signature · 1 line
2.43.0
RE: [PATCH v3 2/2] fbdev: hyperv_fb: Allow graceful removal of framebuffer
From: Saurabh Sengar <[email protected]> Sent: Saturday, March 1, 2025 8:17 AM
Quoted 105 lines
When a Hyper-V framebuffer device is unbind,
hyperv_fbdriver tries to release the framebuffer forcefully. If this framebuffer is in use it produce the following WARN and hence this framebuffer is never released.[ 44.111220] WARNING: CPU: 35 PID: 1882 at drivers/video/fbdev/core/fb_info.c:70 framebuffer_release+0x2c/0x40 < snip > [ 44.111289] Call Trace: [ 44.111290] <TASK> [ 44.111291] ? show_regs+0x6c/0x80 [ 44.111295] ? __warn+0x8d/0x150 [ 44.111298] ? framebuffer_release+0x2c/0x40 [ 44.111300] ? report_bug+0x182/0x1b0 [ 44.111303] ? handle_bug+0x6e/0xb0 [ 44.111306] ? exc_invalid_op+0x18/0x80 [ 44.111308] ? asm_exc_invalid_op+0x1b/0x20 [ 44.111311] ? framebuffer_release+0x2c/0x40 [ 44.111313] ? hvfb_remove+0x86/0xa0 [hyperv_fb] [ 44.111315] vmbus_remove+0x24/0x40 [hv_vmbus] [ 44.111323] device_remove+0x40/0x80 [ 44.111325] device_release_driver_internal+0x20b/0x270 [ 44.111327] ? bus_find_device+0xb3/0xf0Fix this by moving the release of framebuffer and assosiated memory to fb_ops.fb_destroy function, so that framebuffer framework handles it gracefully.
While we fix this, also replace manual registrations/unregistration of framebuffer with
devm_register_framebuffer.Fixes 68a2d20b79b1 ("drivers/video: add Hyper-V Synthetic Video Frame Buffer Driver")Signed-off-by Saurabh Sengar <[email protected]>---
[V3]
- using simplifiedhvfb_putmem()drivers/video/fbdev/hyperv_fb.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)drivers/video/fbdev/hyperv_fb.c +15
-6@@ -282,6 +282,8 @@ static uint screen_depth;static uint screen_fb_size;static uint dio_fb_size;/* FB size for deferred IO */ +static void hvfb_putmem (struct fb_info *info); +/* Send message to Hyper-V host */ static inline int synthvid_send (struct hv_device *hdev,struct synthvid_msg *msg)@@ -862,6 +864,17 @@ static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width,hvfb_ondemand_refresh_throttle (par, x, y, width, height); } +/* +* fb_ops.fb_destroy is called by the last put_fb_info() call at the end +* of unregister_framebuffer() or fb_release(). Do any cleanup related to +* framebuffer here. +*/ +static void hvfb_destroy (struct fb_info *info) +{ +hvfb_putmem (info); +framebuffer_release (info); +} +/* * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the * driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases. @@ -877,6 +890,7 @@ static const struct fb_ops hvfb_ops = { .fb_set_par = hvfb_set_par, .fb_setcolreg = hvfb_setcolreg, .fb_blank = hvfb_blank, + .fb_destroy = hvfb_destroy, };/* Get options from kernel paramenter "video=" */ @@ -1172,7 +1186,7 @@ static int hvfb_probe(struct hv_device *hdev,if (ret) goto error; - ret =register_framebuffer (info); + ret =devm_register_framebuffer (&hdev->device, info);if (ret) {pr_err ("Unable to register framebuffer\n" ); goto error;@@ -1220,14 +1234,10 @@ static void hvfb_remove(struct hv_device *hdev)fb_deferred_io_cleanup (info); -unregister_framebuffer (info);cancel_delayed_work_sync (&par->dwork);vmbus_close (hdev->channel);hv_set_drvdata (hdev,NULL ); - -hvfb_putmem (info); -framebuffer_release (info); }static int hvfb_suspend (struct hv_device *hdev) --
Quoted 1 line
2.43.0
Quoted 12 lines · Saurabh Sengar
This patch series addresses an issue in the unbind path of the
hyperv_fbdriver, which is resolved in the second patch of this series.While working on this fix, it was observed that
hvfb_putmem()and its child functions could be cleaned up first to simplify the movement ofhvfb_putmem(). This cleanup is done in the first patch.Although
hvfb_getmem()could also be cleaned up, it depends onvmbus_allocate_mmio(), which is used by multiple other drivers. Since addressinghvfb_getmem()is independent of this fix, it will be handled in a separate patch series.
Quoted 7 lines
[V3]
- Add a patch 1 for cleanup ofhvfb_putmem()
- Use the simplifiedhvfb_putmem()Saurabh Sengar (2):
fbdev:hyperv_fb: Simplifyhvfb_putmem
fbdev:hyperv_fb: Allow graceful removal of framebuffer
Applied to hyperv-fixes, thanks!