aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2013-11-27 19:24:50 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-12-13 10:44:30 -0500
commit5b764b834ea925b7fc87df4a87a0fde95acbecb9 (patch)
treebc373ac83ea818d5c3a208a267400f6f5a4b15b8 /drivers/pci/setup-bus.c
parentd2f54d9b3ee32bc006a7ff25d716b32feba4b522 (diff)
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: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 80350299a6ea..2e344a5581ae 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -538,7 +538,8 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
538 struct pci_bus_region region; 538 struct pci_bus_region region;
539 unsigned long io_mask; 539 unsigned long io_mask;
540 u8 io_base_lo, io_limit_lo; 540 u8 io_base_lo, io_limit_lo;
541 u32 l, io_upper16; 541 u16 l;
542 u32 io_upper16;
542 543
543 io_mask = PCI_IO_RANGE_MASK; 544 io_mask = PCI_IO_RANGE_MASK;
544 if (bridge->io_window_1k) 545 if (bridge->io_window_1k)
@@ -548,11 +549,10 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
548 res = bus->resource[0]; 549 res = bus->resource[0];
549 pcibios_resource_to_bus(bridge, &region, res); 550 pcibios_resource_to_bus(bridge, &region, res);
550 if (res->flags & IORESOURCE_IO) { 551 if (res->flags & IORESOURCE_IO) {
551 pci_read_config_dword(bridge, PCI_IO_BASE, &l); 552 pci_read_config_word(bridge, PCI_IO_BASE, &l);
552 l &= 0xffff0000;
553 io_base_lo = (region.start >> 8) & io_mask; 553 io_base_lo = (region.start >> 8) & io_mask;
554 io_limit_lo = (region.end >> 8) & io_mask; 554 io_limit_lo = (region.end >> 8) & io_mask;
555 l |= ((u32) io_limit_lo << 8) | io_base_lo; 555 l = ((u16) io_limit_lo << 8) | io_base_lo;
556 /* Set up upper 16 bits of I/O base/limit. */ 556 /* Set up upper 16 bits of I/O base/limit. */
557 io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); 557 io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
558 dev_info(&bridge->dev, " bridge window %pR\n", res); 558 dev_info(&bridge->dev, " bridge window %pR\n", res);
@@ -564,7 +564,7 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
564 /* Temporarily disable the I/O range before updating PCI_IO_BASE. */ 564 /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
565 pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff); 565 pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
566 /* Update lower 16 bits of I/O base/limit. */ 566 /* Update lower 16 bits of I/O base/limit. */
567 pci_write_config_dword(bridge, PCI_IO_BASE, l); 567 pci_write_config_word(bridge, PCI_IO_BASE, l);
568 /* Update upper 16 bits of I/O base/limit. */ 568 /* Update upper 16 bits of I/O base/limit. */
569 pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); 569 pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
570} 570}