drm/ast: Rework I/O register setup
authorThomas Zimmermann <tzimmermann@suse.de>
Thu, 16 Nov 2023 09:59:21 +0000 (10:59 +0100)
committerThomas Zimmermann <tzimmermann@suse.de>
Tue, 28 Nov 2023 15:12:29 +0000 (16:12 +0100)
There are three different ways of retrieving the I/O-memory ranges
for AST devices: either from PCI BAR 1, from PCI BAR 2 or from PCI
BAR 1 by 'guessing'.

Make the respective code more readable by making each case self-
contained. Also add error checking against the length of the PCI
BARs.

v2:
* fix I/O range length to 128 bytes
* fix length test for PCI BAR 2

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231116100240.22975-3-tzimmermann@suse.de
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_reg.h

index 445cf47871a43b135a1179866557ddd7252d9173..70e1871dbaf94410efb8e7a0f296042f97621855 100644 (file)
@@ -444,22 +444,42 @@ struct ast_device *ast_device_create(const struct drm_driver *drv,
        if (!ast->regs)
                return ERR_PTR(-EIO);
 
-       /*
-        * After AST2500, MMIO is enabled by default, and it should be adopted
-        * to be compatible with Arm.
-        */
        if (pdev->revision >= 0x40) {
+               /*
+                * On AST2500 and later models, MMIO is enabled by
+                * default. Adopt it to be compatible with ARM.
+                */
+               resource_size_t len = pci_resource_len(pdev, 1);
+
+               if (len < AST_IO_MM_OFFSET)
+                       return ERR_PTR(-EIO);
+               if ((len - AST_IO_MM_OFFSET) < AST_IO_MM_LENGTH)
+                       return ERR_PTR(-EIO);
                ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
-       } else if (!(pci_resource_flags(pdev, 2) & IORESOURCE_IO)) {
-               drm_info(dev, "platform has no IO space, trying MMIO\n");
-               ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
-       }
+       } else if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
+               /*
+                * Map I/O registers if we have a PCI BAR for I/O.
+                */
+               resource_size_t len = pci_resource_len(pdev, 2);
 
-       /* "map" IO regs if the above hasn't done so already */
-       if (!ast->ioregs) {
+               if (len < AST_IO_MM_LENGTH)
+                       return -EIO;
                ast->ioregs = pcim_iomap(pdev, 2, 0);
                if (!ast->ioregs)
                        return ERR_PTR(-EIO);
+       } else {
+               /*
+                * Anything else is best effort.
+                */
+               resource_size_t len = pci_resource_len(pdev, 1);
+
+               if (len < AST_IO_MM_OFFSET)
+                       return ERR_PTR(-EIO);
+               if ((len - AST_IO_MM_OFFSET) < AST_IO_MM_LENGTH)
+                       return ERR_PTR(-EIO);
+               ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
+
+               drm_info(dev, "Platform has no I/O space, using MMIO\n");
        }
 
        if (!ast_is_vga_enabled(dev)) {
index 555286ecf52098475cf06eb753abf62af634cdd6..05bab94a9a9067d00bd21277202b02748efd7360 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #define AST_IO_MM_OFFSET               (0x380)
+#define AST_IO_MM_LENGTH               (128)
 
 #define AST_IO_VGAARI_W                        (0x40)
 #define AST_IO_VGAMR_W                 (0x42)