In aperture_remove_conflicting_pci_devices(), match the pci
device determine whether or not to call sysfb_disable().  This
fixes cases where the pimary device is not VGA compatible which
leads to the following problem:

1. A PCI device with a non-VGA class is the the boot display
2. That device is probed first and it is not a vga device so
   sysfb_disable() is not called, but the device resources
   are freed by aperture_detach_platform_device()
3. Non-primary GPU is vga device and it ends up calling sysfb_disable()
4. NULL pointer dereference via sysfb_disable() since the resources
   have already been freed by aperture_detach_platform_device() when
   it was called by the other device.

Fix this by calling sysfb_disable() on the device associated with it.

Fixes: 5ae3716cfdcd ("video/aperture: Only remove sysfb on the default vga pci 
device")
Cc: Javier Martinez Canillas <javi...@redhat.com>
Cc: Thomas Zimmermann <tzimmerm...@suse.de>
Cc: Helge Deller <del...@gmx.de>
Cc: Sam Ravnborg <s...@ravnborg.org>
Cc: Daniel Vetter <daniel.vet...@ffwll.ch>
Signed-off-by: Alex Deucher <alexander.deuc...@amd.com>
Cc: sta...@vger.kernel.org
---
 drivers/video/aperture.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c
index 561be8feca96..56a5a0bc2b1a 100644
--- a/drivers/video/aperture.c
+++ b/drivers/video/aperture.c
@@ -6,6 +6,7 @@
 #include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/screen_info.h>
 #include <linux/slab.h>
 #include <linux/sysfb.h>
 #include <linux/types.h>
@@ -346,6 +347,7 @@ EXPORT_SYMBOL(__aperture_remove_legacy_vga_devices);
  */
 int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char 
*name)
 {
+       struct screen_info *si = &screen_info;
        bool primary = false;
        resource_size_t base, size;
        int bar, ret = 0;
@@ -353,7 +355,7 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev 
*pdev, const char *na
        if (pdev == vga_default_device())
                primary = true;
 
-       if (primary)
+       if (pdev == screen_info_pci_dev(si))
                sysfb_disable();
 
        for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
-- 
2.45.2

Reply via email to