On Thu, Apr 06, 2023 at 10:32:40AM +0200, Thomas Zimmermann wrote:
> The hardware for gma500 is different from the rest, as it uses stolen
> framebuffer memory that is not available via PCI BAR. The regular PCI
> removal helper cannot detect the framebuffer, while the non-PCI helper
> misses possible conflicting VGA devices (i.e., a framebuffer or text
> console).
> 
> Gma500 therefore calls both helpers to catch all cases. It's confusing
> as it implies that there's something about the PCI device that requires
> ownership management. The relationship between the PCI device and the
> VGA devices is non-obvious. At worst, readers might assume that calling
> two functions for clearing aperture ownership is a bug in the driver.
> 
> Hence, move the PCI removal helper's code for VGA functionality into
> a separate function and call this function from gma500. Documents the
> purpose of each call to aperture helpers. The change contains comments
> and example code form the discussion at [1].
> 
> Signed-off-by: Thomas Zimmermann <[email protected]>
> Link: 
> https://patchwork.kernel.org/project/dri-devel/patch/[email protected]/
>  # 1

I'm still not clued in on why we need this, but I also don't think it's
terrible, so ...

Acked-by: Daniel Vetter <[email protected]>


> ---
>  drivers/gpu/drm/gma500/psb_drv.c | 48 ++++++++++++++++++--------
>  drivers/video/aperture.c         | 58 ++++++++++++++++++++++----------
>  include/linux/aperture.h         |  7 ++++
>  3 files changed, 81 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/gpu/drm/gma500/psb_drv.c 
> b/drivers/gpu/drm/gma500/psb_drv.c
> index 4bb06a89e48d..f50a9a58a2db 100644
> --- a/drivers/gpu/drm/gma500/psb_drv.c
> +++ b/drivers/gpu/drm/gma500/psb_drv.c
> @@ -7,6 +7,7 @@
>   *
>   **************************************************************************/
>  
> +#include <linux/aperture.h>
>  #include <linux/cpu.h>
>  #include <linux/module.h>
>  #include <linux/notifier.h>
> @@ -19,7 +20,6 @@
>  #include <acpi/video.h>
>  
>  #include <drm/drm.h>
> -#include <drm/drm_aperture.h>
>  #include <drm/drm_drv.h>
>  #include <drm/drm_file.h>
>  #include <drm/drm_ioctl.h>
> @@ -414,25 +414,45 @@ static int psb_driver_load(struct drm_device *dev, 
> unsigned long flags)
>       return ret;
>  }
>  
> -static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id 
> *ent)
> +/*
> + * Hardware for gma500 is a hybrid device, which both acts as a PCI
> + * device (for legacy vga functionality) but also more like an
> + * integrated display on a SoC where the framebuffer simply
> + * resides in main memory and not in a special PCI bar (that
> + * internally redirects to a stolen range of main memory) like all
> + * other integrated PCI display devices have.
> + *
> + * To catch all cases we need to remove conflicting firmware devices
> + * for the stolen system memory and for the VGA functionality. As we
> + * currently cannot easily find the framebuffer's location in stolen
> + * memory, we remove all framebuffers here.
> + *
> + * TODO: Refactor psb_driver_load() to map vdc_reg earlier. Then
> + *       we might be able to read the framebuffer range from the
> + *       device.
> + */
> +static int gma_remove_conflicting_framebuffers(struct pci_dev *pdev,
> +                                            const struct drm_driver 
> *req_driver)
>  {
> -     struct drm_psb_private *dev_priv;
> -     struct drm_device *dev;
> +     resource_size_t base = 0;
> +     resource_size_t size = U32_MAX; /* 4 GiB HW limit */
> +     const char *name = req_driver->name;
>       int ret;
>  
> -     /*
> -      * We cannot yet easily find the framebuffer's location in memory. So
> -      * remove all framebuffers here. Note that we still want the pci special
> -      * handling to kick out vgacon.
> -      *
> -      * TODO: Refactor psb_driver_load() to map vdc_reg earlier. Then we
> -      *       might be able to read the framebuffer range from the device.
> -      */
> -     ret = drm_aperture_remove_framebuffers(&driver);
> +     ret = aperture_remove_conflicting_devices(base, size, name);
>       if (ret)
>               return ret;
>  
> -     ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver);
> +     return __aperture_remove_legacy_vga_devices(pdev);
> +}
> +
> +static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id 
> *ent)
> +{
> +     struct drm_psb_private *dev_priv;
> +     struct drm_device *dev;
> +     int ret;
> +
> +     ret = gma_remove_conflicting_framebuffers(pdev, &driver);
>       if (ret)
>               return ret;
>  
> diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c
> index e4091688b5eb..2824345e87ef 100644
> --- a/drivers/video/aperture.c
> +++ b/drivers/video/aperture.c
> @@ -301,6 +301,37 @@ int aperture_remove_conflicting_devices(resource_size_t 
> base, resource_size_t si
>  }
>  EXPORT_SYMBOL(aperture_remove_conflicting_devices);
>  
> +/**
> + * __aperture_remove_legacy_vga_devices - remove legacy VGA devices of a PCI 
> devices
> + * @pdev: PCI device
> + *
> + * This function removes VGA devices provided by @pdev, such as a VGA
> + * framebuffer or a console. This is useful if you have a VGA-compatible
> + * PCI graphics device with framebuffers in non-BAR locations. Drivers
> + * should acquire ownership of those memory areas and afterwards call
> + * this helper to release remaining VGA devices.
> + *
> + * If your hardware has its framebuffers accessible via PCI BARS, use
> + * aperture_remove_conflicting_pci_devices() instead. The function will
> + * release any VGA devices automatically.
> + *
> + * WARNING: Apparently we must remove graphics drivers before calling
> + *          this helper. Otherwise the vga fbdev driver falls over if
> + *          we have vgacon configured.
> + *
> + * Returns:
> + * 0 on success, or a negative errno code otherwise
> + */
> +int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev)
> +{
> +     /* VGA framebuffer */
> +     aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE);
> +
> +     /* VGA textmode console */
> +     return vga_remove_vgacon(pdev);
> +}
> +EXPORT_SYMBOL(__aperture_remove_legacy_vga_devices);
> +
>  /**
>   * aperture_remove_conflicting_pci_devices - remove existing framebuffers 
> for PCI devices
>   * @pdev: PCI device
> @@ -317,7 +348,7 @@ int aperture_remove_conflicting_pci_devices(struct 
> pci_dev *pdev, const char *na
>  {
>       bool primary = false;
>       resource_size_t base, size;
> -     int bar, ret;
> +     int bar, ret = 0;
>  
>       if (pdev == vga_default_device())
>               primary = true;
> @@ -334,24 +365,15 @@ int aperture_remove_conflicting_pci_devices(struct 
> pci_dev *pdev, const char *na
>               aperture_detach_devices(base, size);
>       }
>  
> -     if (primary) {
> -             /*
> -              * If this is the primary adapter, there could be a VGA device
> -              * that consumes the VGA framebuffer I/O range. Remove this
> -              * device as well.
> -              */
> -             aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE);
> -
> -             /*
> -              * WARNING: Apparently we must kick fbdev drivers before vgacon,
> -              * otherwise the vga fbdev driver falls over.
> -              */
> -             ret = vga_remove_vgacon(pdev);
> -             if (ret)
> -                     return ret;
> -     }
> +     /*
> +      * If this is the primary adapter, there could be a VGA device
> +      * that consumes the VGA framebuffer I/O range. Remove this
> +      * device as well.
> +      */
> +     if (primary)
> +             ret = __aperture_remove_legacy_vga_devices(pdev);
>  
> -     return 0;
> +     return ret;
>  
>  }
>  EXPORT_SYMBOL(aperture_remove_conflicting_pci_devices);
> diff --git a/include/linux/aperture.h b/include/linux/aperture.h
> index 7248727753be..1a9a88b11584 100644
> --- a/include/linux/aperture.h
> +++ b/include/linux/aperture.h
> @@ -16,6 +16,8 @@ int devm_aperture_acquire_for_platform_device(struct 
> platform_device *pdev,
>  int aperture_remove_conflicting_devices(resource_size_t base, 
> resource_size_t size,
>                                       const char *name);
>  
> +int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev);
> +
>  int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char 
> *name);
>  #else
>  static inline int devm_aperture_acquire_for_platform_device(struct 
> platform_device *pdev,
> @@ -31,6 +33,11 @@ static inline int 
> aperture_remove_conflicting_devices(resource_size_t base, reso
>       return 0;
>  }
>  
> +static inline int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev)
> +{
> +     return 0;
> +}
> +
>  static inline int aperture_remove_conflicting_pci_devices(struct pci_dev 
> *pdev, const char *name)
>  {
>       return 0;
> -- 
> 2.40.0
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

Reply via email to