From patchwork Fri Jun 30 10:57:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: suijingfeng X-Patchwork-Id: 698851 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E530C001B0 for ; Fri, 30 Jun 2023 10:58:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232330AbjF3K6R (ORCPT ); Fri, 30 Jun 2023 06:58:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46134 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232398AbjF3K6D (ORCPT ); Fri, 30 Jun 2023 06:58:03 -0400 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D7CEF2D4A; Fri, 30 Jun 2023 03:58:00 -0700 (PDT) Received: from loongson.cn (unknown [10.20.42.43]) by gateway (Coremail) with SMTP id _____8DxOsY3tZ5kmEQEAA--.7093S3; Fri, 30 Jun 2023 18:57:59 +0800 (CST) Received: from openarena.loongson.cn (unknown [10.20.42.43]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxJ801tZ5k5GETAA--.63992S3; Fri, 30 Jun 2023 18:57:58 +0800 (CST) From: Sui Jingfeng To: Alex Deucher , David Airlie , Daniel Vetter , Thomas Zimmermann , Maxime Ripard , Jani Nikula Cc: dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, intel-gfx@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-pci@vger.kernel.org, kvm@vger.kernel.org, linux-fbdev@vger.kernel.org, Javier Martinez Canillas , Maarten Lankhorst , Helge Deller Subject: [PATCH v1 1/4] video/aperture: Add a helper to detect if an aperture contains firmware FB Date: Fri, 30 Jun 2023 18:57:54 +0800 Message-Id: <20230630105757.141582-2-suijingfeng@loongson.cn> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230630105757.141582-1-suijingfeng@loongson.cn> References: <20230630105757.141582-1-suijingfeng@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxJ801tZ5k5GETAA--.63992S3 X-CM-SenderInfo: xvxlyxpqjiv03j6o00pqjv00gofq/ X-Coremail-Antispam: 1Uk129KBj93XoW3WF1UKFW5JrWrArW8Zr4fJFc_yoW7CFWrpF sxAFZ8Gr4UKF1Fyay3CrW09r1rXa1SgFWrW39xA3s3AF47CFykAr17AFykJrZxJrZrAFya gFsxtryrCa1DAFXCm3ZEXasCq-sJn29KB7ZKAUJUUUUD529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUB2b4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVWxJr0_GcWln4kS14v26r126r1DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12 xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1q 6rW5McIj6I8E87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lc7CjxVAaw2AFwI0_Jw0_GFyl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_ Jr0_Gr1l4IxYO2xFxVAFwI0_JF0_Jw1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8Gjc xK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r4a6rW5MIIYrxkI7VAKI48JMIIF0xvE2Ix0 cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE42xK8V AvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E 14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxU4YLvDUUUU Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org This patch adds the aperture_contain_firmware_fb() function to do the determination. Unfortunately due to the fact that apertures list will be freed dynamically, the location and size information of the firmware fb will be lost after dedicated drivers call aperture_remove_conflicting_devices(), aperture_remove_conflicting_pci_devices() or aperture_remove_all_conflicting_devices() functions We handle this problem by introducing two static variables which record the firmware framebuffer's start addrness and end addrness. It assumes that the system has only one active firmware framebuffer driver at a time. We don't use the global structure screen_info here, because PCI resource may get reallocated(the VRAM BAR could be moved) at kernel boot stage. Cc: Thomas Zimmermann Cc: Javier Martinez Canillas Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: David Airlie Cc: Daniel Vetter Cc: Helge Deller Signed-off-by: Sui Jingfeng --- drivers/gpu/drm/drm_aperture.c | 16 ++++++++++++++++ drivers/video/aperture.c | 29 +++++++++++++++++++++++++++++ include/drm/drm_aperture.h | 2 ++ include/linux/aperture.h | 7 +++++++ 4 files changed, 54 insertions(+) diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c index 5729f3bb4398..6e5d8a08683c 100644 --- a/drivers/gpu/drm/drm_aperture.c +++ b/drivers/gpu/drm/drm_aperture.c @@ -190,3 +190,19 @@ int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, return aperture_remove_conflicting_pci_devices(pdev, req_driver->name); } EXPORT_SYMBOL(drm_aperture_remove_conflicting_pci_framebuffers); + +/** + * drm_aperture_contain_firmware_fb - Determine if a aperture contains firmware framebuffer + * + * @base: the aperture's base address in physical memory + * @size: aperture size in bytes + * + * Returns: + * true on if there is a firmware framebuffer belong to the aperture passed in, + * or false otherwise. + */ +bool drm_aperture_contain_firmware_fb(resource_size_t base, resource_size_t size) +{ + return aperture_contain_firmware_fb(base, base + size); +} +EXPORT_SYMBOL(drm_aperture_contain_firmware_fb); diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c index 561be8feca96..5a5422cec669 100644 --- a/drivers/video/aperture.c +++ b/drivers/video/aperture.c @@ -141,6 +141,9 @@ struct aperture_range { static LIST_HEAD(apertures); static DEFINE_MUTEX(apertures_lock); +static resource_size_t firm_fb_start; +static resource_size_t firm_fb_end; + static bool overlap(resource_size_t base1, resource_size_t end1, resource_size_t base2, resource_size_t end2) { @@ -170,6 +173,9 @@ static int devm_aperture_acquire(struct device *dev, mutex_lock(&apertures_lock); + firm_fb_start = base; + firm_fb_end = end; + list_for_each(pos, &apertures) { ap = container_of(pos, struct aperture_range, lh); if (overlap(base, end, ap->base, ap->base + ap->size)) { @@ -377,3 +383,26 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na } EXPORT_SYMBOL(aperture_remove_conflicting_pci_devices); + +/** + * aperture_contain_firmware_fb - Detect if the firmware framebuffer belong to + * a aperture. + * @ap_start: the aperture's start address in physical memory + * @ap_end: the aperture's end address in physical memory + * + * Returns: + * true on if there is a firmware framebuffer belong to the aperture passed in, + * or false otherwise. + */ +bool aperture_contain_firmware_fb(resource_size_t ap_start, resource_size_t ap_end) +{ + /* No firmware framebuffer support */ + if (!firm_fb_start || !firm_fb_end) + return false; + + if (firm_fb_start >= ap_start && firm_fb_end <= ap_end) + return true; + + return false; +} +EXPORT_SYMBOL(aperture_contain_firmware_fb); diff --git a/include/drm/drm_aperture.h b/include/drm/drm_aperture.h index cbe33b49fd5d..6a0b9bacb081 100644 --- a/include/drm/drm_aperture.h +++ b/include/drm/drm_aperture.h @@ -35,4 +35,6 @@ drm_aperture_remove_framebuffers(const struct drm_driver *req_driver) req_driver); } +bool drm_aperture_contain_firmware_fb(resource_size_t base, resource_size_t size); + #endif diff --git a/include/linux/aperture.h b/include/linux/aperture.h index 1a9a88b11584..d4dc5917c49b 100644 --- a/include/linux/aperture.h +++ b/include/linux/aperture.h @@ -19,6 +19,8 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev); int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name); + +bool aperture_contain_firmware_fb(resource_size_t ap_start, resource_size_t ap_end); #else static inline int devm_aperture_acquire_for_platform_device(struct platform_device *pdev, resource_size_t base, @@ -42,6 +44,11 @@ static inline int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, { return 0; } + +static inline bool aperture_contain_firmware_fb(resource_size_t ap_start, resource_size_t ap_end) +{ + return false; +} #endif /** From patchwork Fri Jun 30 10:57:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: suijingfeng X-Patchwork-Id: 698168 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE0EAC001DF for ; Fri, 30 Jun 2023 10:58:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230013AbjF3K6S (ORCPT ); Fri, 30 Jun 2023 06:58:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232593AbjF3K6F (ORCPT ); Fri, 30 Jun 2023 06:58:05 -0400 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id C34093AB9; Fri, 30 Jun 2023 03:58:02 -0700 (PDT) Received: from loongson.cn (unknown [10.20.42.43]) by gateway (Coremail) with SMTP id _____8CxqMU5tZ5kpEQEAA--.6977S3; Fri, 30 Jun 2023 18:58:01 +0800 (CST) Received: from openarena.loongson.cn (unknown [10.20.42.43]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxJ801tZ5k5GETAA--.63992S4; Fri, 30 Jun 2023 18:57:58 +0800 (CST) From: Sui Jingfeng To: Alex Deucher , David Airlie , Daniel Vetter , Thomas Zimmermann , Maxime Ripard , Jani Nikula Cc: dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, intel-gfx@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-pci@vger.kernel.org, kvm@vger.kernel.org, linux-fbdev@vger.kernel.org, Christian Konig , Pan Xinhui , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , Ben Skeggs , Karol Herbst , Lyude Paul , Bjorn Helgaas , Alex Williamson , Maarten Lankhorst , Hawking Zhang , Mario Limonciello , Lijo Lazar , YiPeng Chai , Bokun Zhang , Likun Gao , Ville Syrjala , Jason Gunthorpe , Kevin Tian , Cornelia Huck , Yishai Hadas , Abhishek Sahu , Yi Liu Subject: [PATCH v1 2/4] PCI/VGA: Improve the default VGA device selection Date: Fri, 30 Jun 2023 18:57:55 +0800 Message-Id: <20230630105757.141582-3-suijingfeng@loongson.cn> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230630105757.141582-1-suijingfeng@loongson.cn> References: <20230630105757.141582-1-suijingfeng@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxJ801tZ5k5GETAA--.63992S4 X-CM-SenderInfo: xvxlyxpqjiv03j6o00pqjv00gofq/ X-Coremail-Antispam: 1Uk129KBj93XoW3CryrXF4DKr13CrWrJw4DJrc_yoWDZr1fpF 4rGF98AryxuF4I9w47Za48AFyYv3y2vayrGrW7Aw1Yga45ArWFqF90yFy5tryxJFZrCF13 tr9rKFW7uF1jvFcCm3ZEXasCq-sJn29KB7ZKAUJUUUUP529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBqb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Cr0_Gr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Cr1j6rxdM2kKe7AKxVWUtVW8ZwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07 AIYIkI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU tVWrXwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JMxkF7I0En4kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY 6r1j6r4UMxCIbckI1I0E14v26r1q6r43MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7 xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWrXVW8Jr1lIxkGc2Ij64vIr41lIxAIcVC0 I7IYx2IY67AKxVW5JVW7JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0xvE42 xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF 7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IUeVpB3UUUUU== Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org Currently, the default VGA device selection is not perfect. Potential problems are: 1) This function is a no-op on non-x86 architectures. 2) It does not take the PCI Bar may get relocated into consideration. 3) It is not effective for the PCI device without a dedicated VRAM Bar. 4) It is device-agnostic, thus it has to waste the effort to iterate all of the PCI Bar to find the VRAM aperture. 5) It has invented lots of methods to determine which one is the default boot device on a multiple video card coexistence system. But this is still a policy because it doesn't give the user a choice to override. With the observation that device drivers or video aperture helpers may have better knowledge about which PCI bar contains the firmware FB, This patch tries to solve the above problems by introducing a function callback to the vga_client_register() function interface. DRM device drivers for the PCI device need to register the is_boot_device() function callback during the driver loading time. Once the driver binds the device successfully, VRAARB will call back to the driver. This gives the device drivers a chance to provide accurate boot device identification. Which in turn unlock the abitration service to non-x86 architectures. A device driver can also pass a NULL pointer to the keep the original behavior. This patch is to introduce the mechanism only, while the implementation is left to the authors of various device driver. Also honor the comment: "Clients have two callback mechanisms they can use" Cc: Alex Deucher Cc: Christian Konig Cc: Pan Xinhui Cc: David Airlie Cc: Daniel Vetter Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: Ben Skeggs Cc: Karol Herbst Cc: Lyude Paul Cc: Bjorn Helgaas Cc: Alex Williamson Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: Hawking Zhang Cc: Mario Limonciello Cc: Lijo Lazar Cc: YiPeng Chai Cc: Bokun Zhang Cc: Likun Gao Cc: Ville Syrjala Cc: Jason Gunthorpe CC: Kevin Tian Cc: Cornelia Huck Cc: Yishai Hadas Cc: Abhishek Sahu Cc: Yi Liu Reviewed-by: Lyude Paul # nouveau Signed-off-by: Sui Jingfeng --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/i915/display/intel_vga.c | 3 +-- drivers/gpu/drm/nouveau/nouveau_vga.c | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 2 +- drivers/pci/vgaarb.c | 21 ++++++++++++++++++++- drivers/vfio/pci/vfio_pci_core.c | 2 +- include/linux/vgaarb.h | 8 +++++--- 7 files changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index e25f085ee886..c5bdf6eff29e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4082,7 +4082,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, /* this will fail for cards that aren't VGA class devices, just * ignore it */ if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) - vga_client_register(adev->pdev, amdgpu_device_vga_set_decode); + vga_client_register(adev->pdev, amdgpu_device_vga_set_decode, NULL); px = amdgpu_device_supports_px(ddev); diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index 286a0bdd28c6..98d7d4dffe9f 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -115,7 +115,6 @@ intel_vga_set_decode(struct pci_dev *pdev, bool enable_decode) int intel_vga_register(struct drm_i915_private *i915) { - struct pci_dev *pdev = to_pci_dev(i915->drm.dev); int ret; @@ -127,7 +126,7 @@ int intel_vga_register(struct drm_i915_private *i915) * then we do not take part in VGA arbitration and the * vga_client_register() fails with -ENODEV. */ - ret = vga_client_register(pdev, intel_vga_set_decode); + ret = vga_client_register(pdev, intel_vga_set_decode, NULL); if (ret && ret != -ENODEV) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index f8bf0ec26844..162b4f4676c7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -92,7 +92,7 @@ nouveau_vga_init(struct nouveau_drm *drm) return; pdev = to_pci_dev(dev->dev); - vga_client_register(pdev, nouveau_vga_set_decode); + vga_client_register(pdev, nouveau_vga_set_decode, NULL); /* don't register Thunderbolt eGPU with vga_switcheroo */ if (pci_is_thunderbolt_attached(pdev)) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index afbb3a80c0c6..71f2ff39d6a1 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1425,7 +1425,7 @@ int radeon_device_init(struct radeon_device *rdev, /* if we have > 1 VGA cards, then disable the radeon VGA resources */ /* this will fail for cards that aren't VGA class devices, just * ignore it */ - vga_client_register(rdev->pdev, radeon_vga_set_decode); + vga_client_register(rdev->pdev, radeon_vga_set_decode, NULL); if (rdev->flags & RADEON_IS_PX) runtime = true; diff --git a/drivers/pci/vgaarb.c b/drivers/pci/vgaarb.c index 17bd1268c36a..99d6f1f9b789 100644 --- a/drivers/pci/vgaarb.c +++ b/drivers/pci/vgaarb.c @@ -53,6 +53,7 @@ struct vga_device { bool bridge_has_one_vga; bool is_firmware_default; /* device selected by firmware */ unsigned int (*set_decode)(struct pci_dev *pdev, bool decode); + bool (*is_boot_device)(struct pci_dev *pdev); }; static LIST_HEAD(vga_list); @@ -969,6 +970,10 @@ EXPORT_SYMBOL(vga_set_legacy_decoding); * @set_decode callback: If a client can disable its GPU VGA resource, it * will get a callback from this to set the encode/decode state. * + * @is_boot_device: callback to the device driver, query if a client is the + * default boot device, as the device driver typically has better knowledge + * if specific device is the boot device. But this callback is optional. + * * Rationale: we cannot disable VGA decode resources unconditionally, some * single GPU laptops seem to require ACPI or BIOS access to the VGA registers * to control things like backlights etc. Hopefully newer multi-GPU laptops do @@ -984,7 +989,8 @@ EXPORT_SYMBOL(vga_set_legacy_decoding); * Returns: 0 on success, -1 on failure */ int vga_client_register(struct pci_dev *pdev, - unsigned int (*set_decode)(struct pci_dev *pdev, bool decode)) + unsigned int (*set_decode)(struct pci_dev *pdev, bool decode), + bool (*is_boot_device)(struct pci_dev *pdev)) { int ret = -ENODEV; struct vga_device *vgadev; @@ -996,6 +1002,7 @@ int vga_client_register(struct pci_dev *pdev, goto bail; vgadev->set_decode = set_decode; + vgadev->is_boot_device = is_boot_device; ret = 0; bail: @@ -1521,6 +1528,18 @@ static int pci_notify(struct notifier_block *nb, unsigned long action, notify = vga_arbiter_add_pci_device(pdev); else if (action == BUS_NOTIFY_DEL_DEVICE) notify = vga_arbiter_del_pci_device(pdev); + else if (action == BUS_NOTIFY_BOUND_DRIVER) { + struct vga_device *vgadev = vgadev_find(pdev); + + if (vgadev && vgadev->is_boot_device) { + bool boot_dev = vgadev->is_boot_device(pdev); + + if (boot_dev) { + vgaarb_info(dev, "Overriding as boot device\n"); + vga_set_default_device(pdev); + } + } + } vgaarb_dbg(dev, "%s: action = %lu\n", __func__, action); diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index a5ab416cf476..2a8873a330ba 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -2067,7 +2067,7 @@ static int vfio_pci_vga_init(struct vfio_pci_core_device *vdev) if (ret) return ret; - ret = vga_client_register(pdev, vfio_pci_set_decode); + ret = vga_client_register(pdev, vfio_pci_set_decode, NULL); if (ret) return ret; vga_set_legacy_decoding(pdev, vfio_pci_set_decode(pdev, false)); diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index 97129a1bbb7d..dfde5a6ba55a 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h @@ -33,7 +33,8 @@ struct pci_dev *vga_default_device(void); void vga_set_default_device(struct pci_dev *pdev); int vga_remove_vgacon(struct pci_dev *pdev); int vga_client_register(struct pci_dev *pdev, - unsigned int (*set_decode)(struct pci_dev *pdev, bool state)); + unsigned int (*set_decode)(struct pci_dev *pdev, bool state), + bool (*is_boot_device)(struct pci_dev *pdev)); #else /* CONFIG_VGA_ARB */ static inline void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes) @@ -59,7 +60,8 @@ static inline int vga_remove_vgacon(struct pci_dev *pdev) return 0; } static inline int vga_client_register(struct pci_dev *pdev, - unsigned int (*set_decode)(struct pci_dev *pdev, bool state)) + unsigned int (*set_decode)(struct pci_dev *pdev, bool state), + bool (*is_boot_device)(struct pci_dev *pdev)) { return 0; } @@ -97,7 +99,7 @@ static inline int vga_get_uninterruptible(struct pci_dev *pdev, static inline void vga_client_unregister(struct pci_dev *pdev) { - vga_client_register(pdev, NULL); + vga_client_register(pdev, NULL, NULL); } #endif /* LINUX_VGA_H */