From patchwork Fri Feb 12 17:00:23 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Helgaas X-Patchwork-Id: 78934 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1CH1g1K009987 for ; Fri, 12 Feb 2010 17:01:45 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757398Ab0BLRAw (ORCPT ); Fri, 12 Feb 2010 12:00:52 -0500 Received: from g4t0015.houston.hp.com ([15.201.24.18]:43389 "EHLO g4t0015.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757436Ab0BLRAZ (ORCPT ); Fri, 12 Feb 2010 12:00:25 -0500 Received: from g4t0018.houston.hp.com (g4t0018.houston.hp.com [16.234.32.27]) by g4t0015.houston.hp.com (Postfix) with ESMTP id 9799B8380; Fri, 12 Feb 2010 17:00:23 +0000 (UTC) Received: from ldl (ldl.fc.hp.com [15.11.146.30]) by g4t0018.houston.hp.com (Postfix) with ESMTP id 514481007E; Fri, 12 Feb 2010 17:00:23 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl (Postfix) with ESMTP id 3CC2BCF000F; Fri, 12 Feb 2010 10:00:23 -0700 (MST) Received: from ldl ([127.0.0.1]) by localhost (ldl.fc.hp.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id kvalmV1GMnTf; Fri, 12 Feb 2010 10:00:23 -0700 (MST) Received: from eh.fc.hp.com (eh.fc.hp.com [15.11.146.105]) by ldl (Postfix) with ESMTP id 1F060CF0009; Fri, 12 Feb 2010 10:00:23 -0700 (MST) Received: from bob.kio (localhost [127.0.0.1]) by eh.fc.hp.com (Postfix) with ESMTP id 04A5B26396; Fri, 12 Feb 2010 10:00:23 -0700 (MST) Subject: [PATCH v3 7/7] PCI: reference bridge window resources explicitly To: Jesse Barnes From: Bjorn Helgaas Cc: Matthew Garrett , Tony Luck , linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org, Peter Haight , Gary Hade , linux-kernel@vger.kernel.org, linuxppc-dev@ozlabs.org, linux-am33-list@redhat.com, Yinghai Lu , linux-alpha@vger.kernel.org, Ingo Molnar , Linus Torvalds , Larry Finger Date: Fri, 12 Feb 2010 10:00:23 -0700 Message-ID: <20100212170022.19522.81135.stgit@bob.kio> In-Reply-To: <20100212165532.19522.47240.stgit@bob.kio> References: <20100212165532.19522.47240.stgit@bob.kio> User-Agent: StGit/0.15 MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 12 Feb 2010 17:01:45 +0000 (UTC) diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 155a2bf..044a4bd 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -99,7 +99,7 @@ int pcibios_unmap_io_space(struct pci_bus *bus) */ if (bridge) { #ifdef CONFIG_PPC_STD_MMU_64 - struct resource *res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0]; + struct resource *res = &bridge->resource[PCI_BRIDGE_IO_WINDOW]; #endif pr_debug("IO unmapping for PCI-PCI bridge %s\n", @@ -146,7 +146,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) * thus HPTEs will be faulted in when needed */ if (bridge) { - struct resource *res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0]; + struct resource *res = &bridge->resource[PCI_BRIDGE_IO_WINDOW]; pr_debug("IO mapping for PCI-PCI bridge %s\n", pci_name(bridge)); diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 521ad52..39487c3 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -256,19 +256,22 @@ void __devinit of_scan_pci_bridge(struct device_node *node, if (flags == 0 || size == 0) continue; if (flags & IORESOURCE_IO) { - res = &dev->resource[PCI_BRIDGE_RESOURCES + 0]; + res = &dev->resource[PCI_BRIDGE_IO_WINDOW]; if (res->flags) { printk(KERN_ERR "PCI: ignoring extra I/O range" " for bridge %s\n", node->full_name); continue; } } else { - if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { + if (i == 1) + res = &dev->resource[PCI_BRIDGE_MEM_WINDOW]; + else if (i == 2) + res = &dev->resource[PCI_BRIDGE_PREF_MEM_WINDOW]; + else { printk(KERN_ERR "PCI: too many memory ranges" " for bridge %s\n", node->full_name); continue; } - res = &dev->resource[PCI_BRIDGE_RESOURCES + i]; ++i; } res->start = of_read_number(&ranges[1], 2); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 04e7e97..6d693fb 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -289,7 +289,7 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) unsigned long base, limit; struct resource *res; - res = &dev->resource[PCI_BRIDGE_RESOURCES + 0]; + res = &dev->resource[PCI_BRIDGE_IO_WINDOW]; pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); @@ -325,7 +325,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child) unsigned long base, limit; struct resource *res; - res = &dev->resource[PCI_BRIDGE_RESOURCES + 1]; + res = &dev->resource[PCI_BRIDGE_MEM_WINDOW]; pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); @@ -350,7 +350,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) unsigned long base, limit; struct resource *res; - res = &dev->resource[PCI_BRIDGE_RESOURCES + 2]; + res = &dev->resource[PCI_BRIDGE_PREF_MEM_WINDOW]; pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 790eb69..197c6c6 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1907,7 +1907,7 @@ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) u16 en1k; u8 io_base_lo, io_limit_lo; unsigned long base, limit; - struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; + struct resource *res = &dev->resource[PCI_BRIDGE_IO_WINDOW]; pci_read_config_word(dev, 0x40, &en1k); @@ -1934,7 +1934,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev) { u16 en1k, iobl_adr, iobl_adr_1k; - struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; + struct resource *res = &dev->resource[PCI_BRIDGE_IO_WINDOW]; pci_read_config_word(dev, 0x40, &en1k); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8a3b512..182fe54 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -324,8 +324,7 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) struct pci_dev *bridge = bus->self; struct resource *b_res; - b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; - b_res[1].flags |= IORESOURCE_MEM; + bridge->resource[PCI_BRIDGE_MEM_WINDOW].flags |= IORESOURCE_MEM; pci_read_config_word(bridge, PCI_IO_BASE, &io); if (!io) { @@ -334,12 +333,15 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) pci_write_config_word(bridge, PCI_IO_BASE, 0x0); } if (io) - b_res[0].flags |= IORESOURCE_IO; + bridge->resource[PCI_BRIDGE_IO_WINDOW].flags |= IORESOURCE_IO; + /* DECchip 21050 pass 2 errata: the bridge may miss an address disconnect boundary by one PCI data phase. Workaround: do not use prefetching on this device. */ if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001) return; + + b_res = &bridge->resource[PCI_BRIDGE_PREF_MEM_WINDOW]; pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); if (!pmem) { pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, @@ -348,16 +350,16 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); } if (pmem) { - b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; + b_res->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { - b_res[2].flags |= IORESOURCE_MEM_64; - b_res[2].flags |= PCI_PREF_RANGE_TYPE_64; + b_res->flags |= IORESOURCE_MEM_64; + b_res->flags |= PCI_PREF_RANGE_TYPE_64; } } /* double check if bridge does support 64 bit pref */ - if (b_res[2].flags & IORESOURCE_MEM_64) { + if (b_res->flags & IORESOURCE_MEM_64) { u32 mem_base_hi, tmp; pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &mem_base_hi); @@ -365,7 +367,7 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) 0xffffffff); pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp); if (!tmp) - b_res[2].flags &= ~IORESOURCE_MEM_64; + b_res->flags &= ~IORESOURCE_MEM_64; pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, mem_base_hi); } @@ -544,20 +546,22 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, static void pci_bus_size_cardbus(struct pci_bus *bus) { struct pci_dev *bridge = bus->self; - struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; + struct resource *b_res; u16 ctrl; /* * Reserve some resources for CardBus. We reserve * a fixed amount of bus space for CardBus bridges. */ - b_res[0].start = 0; - b_res[0].end = pci_cardbus_io_size - 1; - b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; + b_res = &bridge->resource[PCI_CB_BRIDGE_IO_0_WINDOW]; + b_res->start = 0; + b_res->end = pci_cardbus_io_size - 1; + b_res->flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; - b_res[1].start = 0; - b_res[1].end = pci_cardbus_io_size - 1; - b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; + b_res = &bridge->resource[PCI_CB_BRIDGE_IO_1_WINDOW]; + b_res->start = 0; + b_res->end = pci_cardbus_io_size - 1; + b_res->flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; /* * Check whether prefetchable memory is supported @@ -576,17 +580,20 @@ static void pci_bus_size_cardbus(struct pci_bus *bus) * twice the size. */ if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) { - b_res[2].start = 0; - b_res[2].end = pci_cardbus_mem_size - 1; - b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN; - - b_res[3].start = 0; - b_res[3].end = pci_cardbus_mem_size - 1; - b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; + b_res = &bridge->resource[PCI_CB_BRIDGE_MEM_0_WINDOW]; + b_res->start = 0; + b_res->end = pci_cardbus_mem_size - 1; + b_res->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN; + + b_res = &bridge->resource[PCI_CB_BRIDGE_MEM_1_WINDOW]; + b_res->start = 0; + b_res->end = pci_cardbus_mem_size - 1; + b_res->flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; } else { - b_res[3].start = 0; - b_res[3].end = pci_cardbus_mem_size * 2 - 1; - b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; + b_res = &bridge->resource[PCI_CB_BRIDGE_MEM_1_WINDOW]; + b_res->start = 0; + b_res->end = pci_cardbus_mem_size * 2 - 1; + b_res->flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; } } diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 9c5a80e..dc55592 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -673,7 +673,7 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type struct pci_bus_region region; unsigned mask; - res = dev->resource + PCI_BRIDGE_RESOURCES + nr; + res = &dev->resource[nr]; /* Already allocated? */ if (res->parent) return 0; @@ -690,7 +690,7 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type region.end = config_readl(socket, addr_end) | ~mask; if (region.start && region.end > region.start && !override_bios) { pcibios_bus_to_resource(dev, res, ®ion); - if (pci_claim_resource(dev, PCI_BRIDGE_RESOURCES + nr) == 0) + if (pci_claim_resource(dev, nr) == 0) return 0; dev_printk(KERN_INFO, &dev->dev, "Preassigned resource %d busy or not available, " @@ -731,32 +731,39 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type static void yenta_allocate_resources(struct yenta_socket *socket) { int program = 0; - program += yenta_allocate_res(socket, 0, IORESOURCE_IO, - PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); - program += yenta_allocate_res(socket, 1, IORESOURCE_IO, - PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); - program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH, + program += yenta_allocate_res(socket, PCI_CB_BRIDGE_IO_0_WINDOW, + IORESOURCE_IO, PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); + program += yenta_allocate_res(socket, PCI_CB_BRIDGE_IO_1_WINDOW, + IORESOURCE_IO, PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); + program += yenta_allocate_res(socket, PCI_CB_BRIDGE_MEM_0_WINDOW, + IORESOURCE_MEM|IORESOURCE_PREFETCH, PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); - program += yenta_allocate_res(socket, 3, IORESOURCE_MEM, + program += yenta_allocate_res(socket, PCI_CB_BRIDGE_MEM_1_WINDOW, + IORESOURCE_MEM, PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); if (program) pci_setup_cardbus(socket->dev->subordinate); } +static void yenta_free_resource(struct yenta_socket *socket, int nr) +{ + struct resource *res; + + res = &socket->dev->resource[nr]; + if (res->start != 0 && res->end != 0) + release_resource(res); + res->start = res->end = res->flags = 0; +} /* * Free the bridge mappings for the device.. */ static void yenta_free_resources(struct yenta_socket *socket) { - int i; - for (i = 0; i < 4; i++) { - struct resource *res; - res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; - if (res->start != 0 && res->end != 0) - release_resource(res); - res->start = res->end = res->flags = 0; - } + yenta_free_resource(socket, PCI_CB_BRIDGE_IO_0_WINDOW); + yenta_free_resource(socket, PCI_CB_BRIDGE_IO_1_WINDOW); + yenta_free_resource(socket, PCI_CB_BRIDGE_MEM_0_WINDOW); + yenta_free_resource(socket, PCI_CB_BRIDGE_MEM_1_WINDOW); } diff --git a/include/linux/pci.h b/include/linux/pci.h index 44e2f0e..edcabd6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -101,7 +101,16 @@ enum { #endif /* resources assigned to buses behind the bridge */ -#define PCI_BRIDGE_RESOURCE_NUM 4 +#define PCI_BRIDGE_IO_WINDOW (PCI_BRIDGE_RESOURCES + 0) +#define PCI_BRIDGE_MEM_WINDOW (PCI_BRIDGE_RESOURCES + 1) +#define PCI_BRIDGE_PREF_MEM_WINDOW (PCI_BRIDGE_RESOURCES + 2) + +#define PCI_CB_BRIDGE_IO_0_WINDOW (PCI_BRIDGE_RESOURCES + 0) +#define PCI_CB_BRIDGE_IO_1_WINDOW (PCI_BRIDGE_RESOURCES + 1) +#define PCI_CB_BRIDGE_MEM_0_WINDOW (PCI_BRIDGE_RESOURCES + 2) +#define PCI_CB_BRIDGE_MEM_1_WINDOW (PCI_BRIDGE_RESOURCES + 3) + +#define PCI_BRIDGE_RESOURCE_NUM 4 /* max of P2P, cardbus */ PCI_BRIDGE_RESOURCES, PCI_BRIDGE_RESOURCE_END = PCI_BRIDGE_RESOURCES +