Skip to content

Commit

Permalink
PCI: fix X server auto probe fail when both ast and etnaviv drm present
Browse files Browse the repository at this point in the history
According to PCI-to-PCI bridge spec, bit 3 of Bridge Control Register
is VGA Enable bit which modifies the response by the bridge to VGA
compatible addresses.

The Bridge Control register provides extensions to the Command register
that are specific to a bridge. The Bridge Control register provides
many of the same controls for the secondary interface that are provided
by the Command register for the primary interface. There are some bits
that affect the operation of both interfaces of the bridge.

If the VGA Enable bit is set, the bridge will positively decode
and forward the following accesses on the primary interface to
the secondary interface (and, conversely, block the forwarding
of these addresses from the secondary to primary interface)

Forwarding of these accesses is qualified by the I/O Enable and
Memory Enable bits in the Command register.) The default state of
this bit after reset must be 0.

Bit 3 of Bridge Control Register is VGA Enable bit which modifies the
response by the bridge to VGA compatible addresses.

 when 0: do not forward VGA compatible memory and I/O addresses from
         the primary to secondary interface (addresses defined below)
         unless they are enabled for forwarding by the defined I/O
 when 1: forward VGA compatible memory and I/O addresses (addresses
         defined below) from the primary interface to the secondary
		 interface (if the I/O Enable and Memory Enable bits are set)
         independent of the I/O and memory address ranges and
         independent of the ISA Enable bit

 * memory accesses in the range 000A 0000h to 000B FFFFh

 * I/O addresses in the first 64 KB of the I/O address space
   (AD[31:16] are 0000h) where AD[9:: 0] are in the ranges
   3B0h to 3BBh and 3C0h to 3DFh (inclusive of ISA address
   aliases - AD[15::10] are not decoded)

If the VGA Enable bit is set, forwarding of these accesses is
independent of the I/O address range and memory address ranges
defined by the I/O Base and Limit registers, the Memory Base
and Limit registers, and the Prefetchable Memory Base and Limit
registers of the bridge.

Forwarding of these accesses is also independent of the settings
of the ISA Enable bit (in the Bridge Control register) or VGA
Palette Snoop bits (in the Command register).

The AST2500 hardware we are using do not set the VGA Enable bit on
its bridge control reg, this cause vgaarb subsystem don't think the
VGA card behind this pridge as a valid boot vga device which made
X server choose wrong video card to use when multiple video card
present in the system.

Its seems more vgaarb's fault than the ast2500 bmc itself.
even through bit 3 of Bridge Control Register is 0, it should still
allow to forward the accesses when the addresses is in the range of
IO/MEM Base and Limit registers.

Nevertheless, in order to support loongson CPU product line, we
provide a workaround to this bug for the Sugon L620-G30 and Sugon
L820-G30 server.

see similar bug:

https://patchwork.kernel.org/project/linux-pci/patch/[email protected]/

Signed-off-by: suijingfeng <[email protected]>
Signed-off-by: Yanteng Si <[email protected]>
  • Loading branch information
Yanteng Si committed May 20, 2024
1 parent 96efc16 commit 570765a
Showing 1 changed file with 48 additions and 0 deletions.
48 changes: 48 additions & 0 deletions drivers/pci/controller/pci-loongson.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/pci_ids.h>
#include <linux/pci-acpi.h>
#include <linux/pci-ecam.h>
#include <linux/vgaarb.h>

#include "../pci.h"

Expand Down Expand Up @@ -223,6 +224,53 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, 0x7a25, loongson_display_quirk);
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
PCI_BASE_CLASS_DISPLAY, 16, loongson_display_quirk);

static void pci_fixup_aspeed(struct pci_dev *pdev)
{
struct pci_dev *bridge;
struct pci_bus *bus;
struct pci_dev *vdevp = NULL;
u16 config;

bus = pdev->bus;
bridge = bus->self;

/* Is VGA routed to us? */
if (bridge && (pci_is_bridge(bridge))) {
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &config);

/* Yes, this bridge is PCI bridge-to-bridge spec compliant,
* just return!
*/
if (config & PCI_BRIDGE_CTL_VGA)
return;

dev_warn(&pdev->dev, "VGA bridge control is not enabled\n");
}

/* Just return if the system already have a default device */
if (vga_default_device())
return;

/* No default vga device */
while ((vdevp = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, vdevp))) {
if (vdevp->vendor != 0x1a03) {
/* Have other vga devcie in the system, do nothing */
dev_info(&pdev->dev,
"Another boot vga device: 0x%x:0x%x\n",
vdevp->vendor, vdevp->device);
return;
}
}

vga_set_default_device(pdev);

dev_info(&pdev->dev,
"Boot vga device set as 0x%x:0x%x\n",
pdev->vendor, pdev->device);
}
DECLARE_PCI_FIXUP_CLASS_FINAL(0x1a03, 0x2000,
PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_aspeed);

static struct loongson_pci *pci_bus_to_loongson_pci(struct pci_bus *bus)
{
struct pci_config_window *cfg;
Expand Down

0 comments on commit 570765a

Please sign in to comment.