mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
PCI/VGA: Factor out default VGA device selection
Default VGA device selection fails when PCI devices are enumerated after the vga_arb_device_init() subsys_initcall. vga_arbiter_add_pci_device() selects the first fully enabled device to which legacy VGA resources are routed as the default VGA device. This is an ADD_DEVICE notifier, so it runs after every PCI device is enumerated. vga_arb_select_default_device() may select framebuffer devices, partially enabled GPUs, or non-legacy devices that don't have legacy VGA resources routed to them as the default VGA device. But this only happens once, from the vga_arb_device_init() subsys_initcall, so it doesn't consider devices enumerated after that: acpi_init acpi_scan_init acpi_pci_root_init # PCI device enumeration (ACPI systems) vga_arb_device_init for_each_pci_device vga_arbiter_add_pci_device # ADD_DEVICE notifier if (VGA-owner) vga_set_default_device <-- set default VGA vga_arb_select_default_device # only called ONCE for_each_vga_device if (framebuffer) vga_set_default_device <-- set default VGA to framebuffer if (!vga_default_device()) if (non-legacy, integrated GPU, etc) vga_set_default_device <-- set default VGA if (!vga_default_device()) vga_set_default_device <-- set default VGA pcibios_init pcibios_scanbus # PCI device enumeration (non-ACPI systems) ... vga_arbiter_add_pci_device # ADD_DEVICE notification if (VGA-owner) vga_set_default_device <-- set default VGA Note that on non-ACPI systems, vga_arb_select_default_device() runs before pcibios_init(), so it sees no VGA devices and can never set a framebuffer device, a non-legacy integrated GPU, etc., as the default device. Factor out the default VGA device selection to vga_is_boot_device(), called from vga_arbiter_add_pci_device(). Then we can migrate the default device selection from vga_arb_select_default_device() to the vga_arbiter_add_pci_device() path. [bhelgaas: commit log, split to separate patch] Link: https://lore.kernel.org/r/20211015061512.2941859-4-chenhuacai@loongson.cn Link: https://lore.kernel.org/r/20220224224753.297579-5-helgaas@kernel.org Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
parent
60a9bac8ab
commit
dfe3da812d
@ -628,6 +628,41 @@ static bool vga_arb_integrated_gpu(struct device *dev)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if vgadev is a better default VGA device than the best one
|
||||
* we've seen so far.
|
||||
*/
|
||||
static bool vga_is_boot_device(struct vga_device *vgadev)
|
||||
{
|
||||
struct vga_device *boot_vga = vgadev_find(vga_default_device());
|
||||
|
||||
/*
|
||||
* We select the default VGA device in this order:
|
||||
* 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())
|
||||
* Non-legacy discrete device (see vga_arb_select_default_device())
|
||||
* Other device (see vga_arb_select_default_device())
|
||||
*/
|
||||
|
||||
/*
|
||||
* A legacy VGA device has MEM and IO enabled and any bridges
|
||||
* leading to it have PCI_BRIDGE_CTL_VGA enabled so the legacy
|
||||
* resources ([mem 0xa0000-0xbffff], [io 0x3b0-0x3bb], etc) are
|
||||
* routed to it.
|
||||
*
|
||||
* We use the first one we find, so if we've already found one,
|
||||
* vgadev is no better.
|
||||
*/
|
||||
if (boot_vga)
|
||||
return false;
|
||||
|
||||
if ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rules for using a bridge to control a VGA descendant decoding: if a bridge
|
||||
* has only one VGA descendant then it can be used to control the VGA routing
|
||||
@ -755,12 +790,10 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
|
||||
bus = bus->parent;
|
||||
}
|
||||
|
||||
/* Deal with VGA default device. Use first enabled one
|
||||
* by default if arch doesn't have it's own hook
|
||||
*/
|
||||
if (vga_default == NULL &&
|
||||
((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
|
||||
vgaarb_info(&pdev->dev, "setting as boot VGA device\n");
|
||||
if (vga_is_boot_device(vgadev)) {
|
||||
vgaarb_info(&pdev->dev, "setting as boot VGA device%s\n",
|
||||
vga_default_device() ?
|
||||
" (overriding previous)" : "");
|
||||
vga_set_default_device(pdev);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user