Commit 5b764b83 authored by Bjorn Helgaas's avatar Bjorn Helgaas

PCI: Stop clearing bridge Secondary Status when setting up I/O aperture

pci_setup_bridge_io() accessed PCI_IO_BASE and PCI_IO_LIMIT using dword
(32-bit) reads and writes, which also access the Secondary Status register.
Since the Secondary Status register is in the upper 16 bits of the dword,
and we preserved those upper 16 bits, this had the effect of clearing any
of the write-1-to-clear bits that happened to be set in the Secondary
Status register.

That's not what we want, so use word (16-bit) accesses to update only
PCI_IO_BASE and PCI_IO_LIMIT.
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent d2f54d9b
...@@ -538,7 +538,8 @@ static void pci_setup_bridge_io(struct pci_bus *bus) ...@@ -538,7 +538,8 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
struct pci_bus_region region; struct pci_bus_region region;
unsigned long io_mask; unsigned long io_mask;
u8 io_base_lo, io_limit_lo; u8 io_base_lo, io_limit_lo;
u32 l, io_upper16; u16 l;
u32 io_upper16;
io_mask = PCI_IO_RANGE_MASK; io_mask = PCI_IO_RANGE_MASK;
if (bridge->io_window_1k) if (bridge->io_window_1k)
...@@ -548,11 +549,10 @@ static void pci_setup_bridge_io(struct pci_bus *bus) ...@@ -548,11 +549,10 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
res = bus->resource[0]; res = bus->resource[0];
pcibios_resource_to_bus(bridge, &region, res); pcibios_resource_to_bus(bridge, &region, res);
if (res->flags & IORESOURCE_IO) { if (res->flags & IORESOURCE_IO) {
pci_read_config_dword(bridge, PCI_IO_BASE, &l); pci_read_config_word(bridge, PCI_IO_BASE, &l);
l &= 0xffff0000;
io_base_lo = (region.start >> 8) & io_mask; io_base_lo = (region.start >> 8) & io_mask;
io_limit_lo = (region.end >> 8) & io_mask; io_limit_lo = (region.end >> 8) & io_mask;
l |= ((u32) io_limit_lo << 8) | io_base_lo; l = ((u16) io_limit_lo << 8) | io_base_lo;
/* Set up upper 16 bits of I/O base/limit. */ /* Set up upper 16 bits of I/O base/limit. */
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
dev_info(&bridge->dev, " bridge window %pR\n", res); dev_info(&bridge->dev, " bridge window %pR\n", res);
...@@ -564,7 +564,7 @@ static void pci_setup_bridge_io(struct pci_bus *bus) ...@@ -564,7 +564,7 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
/* Temporarily disable the I/O range before updating PCI_IO_BASE. */ /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff); pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
/* Update lower 16 bits of I/O base/limit. */ /* Update lower 16 bits of I/O base/limit. */
pci_write_config_dword(bridge, PCI_IO_BASE, l); pci_write_config_word(bridge, PCI_IO_BASE, l);
/* Update upper 16 bits of I/O base/limit. */ /* Update upper 16 bits of I/O base/limit. */
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment