Re: [PATCH] drm/vmwgfx: Stop requesting the pci regions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Zack

Am 19.01.22 um 10:13 schrieb Thomas Zimmermann:
Hi

Am 19.01.22 um 03:15 schrieb Zack Rusin:
On Tue, 2022-01-18 at 20:00 +0100, Javier Martinez Canillas wrote:
Hello Zack,

On 1/17/22 19:03, Zack Rusin wrote:
From: Zack Rusin <zackr@xxxxxxxxxx>

When sysfb_simple is enabled loading vmwgfx fails because the regions
are held by the platform. In that case
remove_conflicting*_framebuffers
only removes the simplefb but not the regions held by sysfb.


Indeed, that's an issue. I wonder if we should drop the IORESOURCE_BUSY
flag from the memory resource added to the "simple-framebuffer" device
?

I think this is one of those cases where it depends on what we plan to
do after that. Sementically it makes sense to have it in there - the
framebuffer memory is claimed by the "simple-framebuffer" and it's
busy, it's just that it creates issues for drivers after unloading. I
think removing it, while making things easier for drivers, would be
confusing for people reading the code later, unless there's some kind
of cleanup that would happen with it (e.g. removing IORESOURCE_BUSY
altogether and making the drm drivers properly request their
resources). At least by itself it doesn't seem to be much better
solution than having the drm drivers not call pci_request_region[s],
which apart from hyperv and cirrus (iirc bochs does it for resources
other than fb which wouldn't have been claimed by "simple-framebuffer")
is already the case.

I do think we should do one of them to make the codebase coherent:
either remove IORESOURCE_BUSY from "simple-framebuffer" or remove
pci_request_region[s] from hyperv and cirrus.

I just discussed this a bit with Javier. It's a problem with the simple-framebuffer code, rather then vmwgfx.

IMHO the best solution is to drop IORESOURCE_BUSY from sysfb and have drivers register/release the range with _BUSY. That would signal the memory belongs to the sysfb device but is not busy unless a driver has been bound. After simplefb released the range, it should be 'non-busy' again and available for vmwgfx. Simpledrm does a hot-unplug of the sysfb device, so the memory range gets released entirely. If you want, I'll prepare some patches for this scenario.

Attached is a patch that implements this. Doing

 cat /proc/iomem
  ...
  e0000000-efffffff : 0000:00:02.0

    e0000000-e07e8fff : BOOTFB

      e0000000-e07e8fff : simplefb

  ...

shows the memory. 'BOOTFB' is the simple-framebuffer device and 'simplefb' is the driver. Only the latter uses _BUSY. Same for simpledrm. Once the drivers have been unloaded, the BUSY flag is gone and the memory canbe acquired by vmwgfx.

Zack, please test this patch. If it works, I'll send out the real patchset.

Best regards
Thomas


If this doesn't work, pushing all request/release pairs into drivers would be my next option.

If none of this is feasible, we can still remove pci_request_region() from vmwgfx.

Best regards
Thomas




Like the other drm drivers we need to stop requesting all the pci
regions
to let the driver load with platform code enabled.
This allows vmwgfx to load correctly on systems with sysfb_simple
enabled.


I read this very interesting thread from two years ago:

https://lkml.org/lkml/2020/11/5/248

Maybe is worth mentioning in the commit message what Daniel said there,
that is that only a few DRM drivers request explicitly the PCI regions
and the only reliable approach is for bus drivers to claim these.

Ah, great point. I'll update the commit log with that.

Signed-off-by: Zack Rusin <zackr@xxxxxxxxxx>
Fixes: 523375c943e5 ("drm/vmwgfx: Port vmwgfx to arm64")
Cc: dri-devel@xxxxxxxxxxxxxxxxxxxxx
Cc: <stable@xxxxxxxxxxxxxxx>
Reviewed-by: Martin Krastev <krastevm@xxxxxxxxxx>
---

The patch looks good to me, thanks a lot for fixing this:

Reviewed-by: Javier Martinez Canillas <javierm@xxxxxxxxxx>

Thanks for taking a look at this, I appreciate it!

z


--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev
From f5da496296f7dcaf8754e1b0446660b100539a73 Mon Sep 17 00:00:00 2001
From: Thomas Zimmermann <tzimmermann@xxxxxxx>
Date: Wed, 19 Jan 2022 10:23:07 +0100
Subject: [PATCH] [RFC] drop IORESOURCE_BUSY from sysfb code and request memory
 in drivers

Drop the IORESOURCE_BUSY flag when creating a simple-framebuffer
device. Instead acquire the memory in drivers.
---
 drivers/firmware/sysfb_simplefb.c |  2 +-
 drivers/gpu/drm/tiny/simpledrm.c  | 17 ++++++---
 drivers/video/fbdev/simplefb.c    | 57 ++++++++++++++++++++++---------
 3 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/drivers/firmware/sysfb_simplefb.c b/drivers/firmware/sysfb_simplefb.c
index b86761904949..179e9d0ef3e9 100644
--- a/drivers/firmware/sysfb_simplefb.c
+++ b/drivers/firmware/sysfb_simplefb.c
@@ -99,7 +99,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
 
 	/* setup IORESOURCE_MEM as framebuffer memory */
 	memset(&res, 0, sizeof(res));
-	res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	res.flags = IORESOURCE_MEM;
 	res.name = simplefb_resname;
 	res.start = base;
 	res.end = res.start + length - 1;
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 04146da2d1d8..32550697b1a7 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -526,21 +526,28 @@ static int simpledrm_device_init_mm(struct simpledrm_device *sdev)
 {
 	struct drm_device *dev = &sdev->dev;
 	struct platform_device *pdev = sdev->pdev;
-	struct resource *mem;
+	struct resource *res, *mem;
 	void __iomem *screen_base;
 	int ret;
 
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem)
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
 		return -EINVAL;
 
-	ret = devm_aperture_acquire_from_firmware(dev, mem->start, resource_size(mem));
+	ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res));
 	if (ret) {
 		drm_err(dev, "could not acquire memory range %pr: error %d\n",
-			mem, ret);
+			res, ret);
 		return ret;
 	}
 
+	mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				      sdev->dev.driver->name);
+	if (!mem) {
+		drm_err(dev, "could not acquire memory region %pr\n", res);
+		return -EBUSY;
+	}
+
 	screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
 				      resource_size(mem));
 	if (!screen_base)
diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
index 57541887188b..7b9072f07337 100644
--- a/drivers/video/fbdev/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
@@ -66,16 +66,36 @@ static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 	return 0;
 }
 
-struct simplefb_par;
+struct simplefb_par {
+	u32 palette[PSEUDO_PALETTE_SIZE];
+#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
+	bool clks_enabled;
+	unsigned int clk_count;
+	struct clk **clks;
+#endif
+#if defined CONFIG_OF && defined CONFIG_REGULATOR
+	bool regulators_enabled;
+	u32 regulator_count;
+	struct regulator **regulators;
+#endif
+	bool release_mem_region;
+};
+
 static void simplefb_clocks_destroy(struct simplefb_par *par);
 static void simplefb_regulators_destroy(struct simplefb_par *par);
 
 static void simplefb_destroy(struct fb_info *info)
 {
+	struct simplefb_par *par = info->par;
+
 	simplefb_regulators_destroy(info->par);
 	simplefb_clocks_destroy(info->par);
 	if (info->screen_base)
 		iounmap(info->screen_base);
+
+	if (par->release_mem_region)
+		release_mem_region(info->apertures->ranges[0].base,
+				   info->apertures->ranges[0].size);
 }
 
 static const struct fb_ops simplefb_ops = {
@@ -169,20 +189,6 @@ static int simplefb_parse_pd(struct platform_device *pdev,
 	return 0;
 }
 
-struct simplefb_par {
-	u32 palette[PSEUDO_PALETTE_SIZE];
-#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
-	bool clks_enabled;
-	unsigned int clk_count;
-	struct clk **clks;
-#endif
-#if defined CONFIG_OF && defined CONFIG_REGULATOR
-	bool regulators_enabled;
-	u32 regulator_count;
-	struct regulator **regulators;
-#endif
-};
-
 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
 /*
  * Clock handling code.
@@ -401,6 +407,7 @@ static void simplefb_regulators_destroy(struct simplefb_par *par) { }
 
 static int simplefb_probe(struct platform_device *pdev)
 {
+	bool request_mem_succeeded = false;
 	int ret;
 	struct simplefb_params params;
 	struct fb_info *info;
@@ -436,9 +443,20 @@ static int simplefb_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	if (request_mem_region(mem->start, resource_size(mem), "simplefb")) {
+		request_mem_succeeded = true;
+	} else {
+		/* We cannot make this fatal. Sometimes this comes from magic
+		   spaces our resource handlers simply don't know about */
+		dev_warn(&pdev->dev, "simplefb: cannot reserve video memory at %pR\n",
+			 mem);
+	}
+
 	info = framebuffer_alloc(sizeof(struct simplefb_par), &pdev->dev);
-	if (!info)
-		return -ENOMEM;
+	if (!info) {
+		ret = -ENOMEM;
+		goto error_release_mem_region;
+	}
 	platform_set_drvdata(pdev, info);
 
 	par = info->par;
@@ -495,6 +513,8 @@ static int simplefb_probe(struct platform_device *pdev)
 			     info->var.xres, info->var.yres,
 			     info->var.bits_per_pixel, info->fix.line_length);
 
+	par->release_mem_region = request_mem_succeeded;
+
 	ret = register_framebuffer(info);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
@@ -513,6 +533,9 @@ static int simplefb_probe(struct platform_device *pdev)
 	iounmap(info->screen_base);
 error_fb_release:
 	framebuffer_release(info);
+error_release_mem_region:
+	if (request_mem_succeeded)
+		release_mem_region(mem->start, resource_size(mem));
 	return ret;
 }
 
-- 
2.34.1

Attachment: OpenPGP_signature
Description: OpenPGP digital signature


[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux