From patchwork Wed Jul 26 08:19:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai-Heng Feng X-Patchwork-Id: 1813025 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=canonical.com header.i=@canonical.com header.a=rsa-sha256 header.s=20210705 header.b=TqpLK5nu; dkim-atps=neutral Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4R9n0l2P1rz1yZv for ; Wed, 26 Jul 2023 18:21:11 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1qOZlX-0005PT-O9; Wed, 26 Jul 2023 08:21:03 +0000 Received: from smtp-relay-canonical-1.internal ([10.131.114.174] helo=smtp-relay-canonical-1.canonical.com) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1qOZlQ-0005D4-IF for kernel-team@lists.ubuntu.com; Wed, 26 Jul 2023 08:20:56 +0000 Received: from localhost.localdomain (unknown [10.101.196.174]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-1.canonical.com (Postfix) with ESMTPSA id DFB7041FAB for ; Wed, 26 Jul 2023 08:20:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1690359655; bh=9QzqwKf9v7hqfk58kAeUwqhtXmopV1/b3ueAmzGjTZo=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TqpLK5nu7+AZlqVpiht1hHxgCoSbOTRhFwRaCyMBiBjxml33Lhnk8U7lN/a9qbf3v WizRQCIJNI7Rs69l/GtZ7cSGdYdGQXZVyGoXnHx/oVvllcAGuzOrcK+x4AS6DNq8n7 AYdGOV6GZTuWsWjEvXgUJgxdvsMUPq1lHiGzDOBFuqpZBkFKh9QT80w/EQMufGmy6q 1U9NROqbFgp7/UMqX/BNXGX+xkxZegYuNw2XE9HcvywHjsrlCvG5xkaBi1eQWyEPY2 M9THYK312qAiZLnMhMOThNVVy8dXWV4SgzD0PfoFeNQdteZ8DodJw7aVCM914qM/fW s4AQoWfmluowg== From: Kai-Heng Feng To: kernel-team@lists.ubuntu.com Subject: [L] [PATCH 9/9] video/aperture: Provide a VGA helper for gma500 and internal use Date: Wed, 26 Jul 2023 16:19:47 +0800 Message-Id: <20230726081947.3310004-10-kai.heng.feng@canonical.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230726081947.3310004-1-kai.heng.feng@canonical.com> References: <20230726081947.3310004-1-kai.heng.feng@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Thomas Zimmermann BugLink: https://bugs.launchpad.net/bugs/2028749 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]. v5: * fix grammar in gma500 comment (Javier) Signed-off-by: Thomas Zimmermann Link: https://patchwork.kernel.org/project/dri-devel/patch/20230404201842.567344-1-daniel.vetter@ffwll.ch/ # 1 Reviewed-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20230406132109.32050-10-tzimmermann@suse.de (cherry picked from commit 116b1c5a364bcbdc40be64d4f3ec9dbc32e264dd) Signed-off-by: Kai-Heng Feng --- 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 738eb558a97e..031ca1c016c4 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -7,6 +7,7 @@ * **************************************************************************/ +#include #include #include #include @@ -19,7 +20,6 @@ #include #include -#include #include #include #include @@ -416,25 +416,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 implement it. + * + * 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;