From nobody Sun Apr 19 09:11:21 2026 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 DB475C433EF for ; Mon, 4 Jul 2022 04:34:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231730AbiGDEeL (ORCPT ); Mon, 4 Jul 2022 00:34:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51138 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229461AbiGDEeJ (ORCPT ); Mon, 4 Jul 2022 00:34:09 -0400 Received: from mx2.absolutedigital.net (mx2.absolutedigital.net [50.242.207.105]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id AA24B5F55 for ; Sun, 3 Jul 2022 21:34:08 -0700 (PDT) Received: from lancer.cnet.absolutedigital.net (lancer.cnet.absolutedigital.net [10.7.5.10]) by luxor.inet.absolutedigital.net (8.14.4/8.14.4) with ESMTP id 2644XoMD017608 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Mon, 4 Jul 2022 00:33:50 -0400 Received: from localhost (localhost [127.0.0.1]) by lancer.cnet.absolutedigital.net (8.17.1/8.17.1) with ESMTPS id 2644XoDH029139 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Mon, 4 Jul 2022 00:33:50 -0400 Date: Mon, 4 Jul 2022 00:33:50 -0400 (EDT) From: Cal Peake To: Randy Dunlap cc: Kernel Mailing List , Bjorn Helgaas , Huacai Chen Subject: [PATCH] vgaarb: Add module param to allow for choosing the boot VGA device Message-ID: <29b1e2e3-8954-2516-78f2-7e57cd5b976d@absolutedigital.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" My first attempt at solving this problem was based on a bit of a=20 misunderstanding of the code and, while it worked, could be much improved. This is a new attempt that creates the module parameter 'vgaarb.bootdev'=20 that can be passed a PCI ID (e.g. 0a:00.0) that the VGA arbiter will=20 attempt to use as the boot VGA device over any other eligible devices. If the passed ID is invalid or is an ineligible device, the arbiter will=20 fallback to its normal method of trying to find the preferred device for=20 the job. I've tested it thoroughly and it is working very well for me. The patch is available below for review and, if found acceptable, can be=20 pulled via: git pull https://github.com/peake/linux.git vgaarb-2 --=20 Cal Peake Signed-off-by: Cal Peake diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentatio= n/admin-guide/kernel-parameters.txt index 2522b11e593f..21ac87f4a8a9 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6518,6 +6518,13 @@ This is actually a boot loader parameter; the value is passed to the kernel using a special protocol. =20 + vgaarb.bootdev=3D [PCI] Specify the PCI ID (e.g. 0e:00.0) of the + device to use as the boot VGA device, overriding + the heuristic used to normally determine which + of the eligible VGA devices to use. If the device + specified is not valid or not eligible, then we + fallback to the heuristic. + vm_debug[=3Doptions] [KNL] Available with CONFIG_DEBUG_VM=3Dy. May slow down system boot speed, especially when enabled on systems with a large amount of memory. diff --git a/drivers/pci/vgaarb.c b/drivers/pci/vgaarb.c index f80b6ec88dc3..d3689b7dc63d 100644 --- a/drivers/pci/vgaarb.c +++ b/drivers/pci/vgaarb.c @@ -35,6 +35,34 @@ =20 #include =20 +static char *bootdev __initdata; +module_param(bootdev, charp, 0); +MODULE_PARM_DESC(bootdev, "Force boot device to the specified PCI ID"); + +/* + * Initialize to the last possible ID to have things work as normal + * when no 'bootdev' option is supplied. We especially do not want + * this to be zero (0) since that is a valid PCI ID (00:00.0). + */ +static u16 bootdev_id =3D 0xffff; + +static void __init parse_bootdev(char *input) +{ + unsigned int bus, dev, func; + int ret; + + if (input =3D=3D NULL) + return; + + ret =3D sscanf(input, "%x:%x.%x", &bus, &dev, &func); + if (ret !=3D 3) { + pr_warn("Improperly formatted PCI ID: %s\n", input); + return; + } + + bootdev_id =3D PCI_DEVID(bus, PCI_DEVFN(dev, func)); +} + static void vga_arbiter_notify_clients(void); /* * We keep a list of all vga devices in the system to speed @@ -53,6 +81,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_chosen_one; /* device specified on command line */ }; =20 static LIST_HEAD(vga_list); @@ -605,6 +634,7 @@ static bool vga_is_boot_device(struct vga_device *vgade= v) =20 /* * We select the default VGA device in this order: + * User specified device (see module param bootdev=3D) * Firmware framebuffer (see vga_arb_select_default_device()) * Legacy VGA device (owns VGA_RSRC_LEGACY_MASK) * Non-legacy integrated device (see vga_arb_select_default_device()) @@ -612,6 +642,14 @@ static bool vga_is_boot_device(struct vga_device *vgad= ev) * Other device (see vga_arb_select_default_device()) */ =20 + if (boot_vga && boot_vga->is_chosen_one) + return false; + + if (bootdev_id =3D=3D PCI_DEVID(pdev->bus->number, pdev->devfn)) { + vgadev->is_chosen_one =3D true; + return true; + } + /* * We always prefer a firmware default device, so if we've already * found one, there's no need to consider vgadev. @@ -1544,6 +1582,8 @@ static int __init vga_arb_device_init(void) int rc; struct pci_dev *pdev; =20 + parse_bootdev(bootdev); + rc =3D misc_register(&vga_arb_device); if (rc < 0) pr_err("error %d registering device\n", rc);