All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] PCI: P2P bridge window fixes
@ 2012-07-09 20:31 Bjorn Helgaas
  2012-07-09 20:32 ` [PATCH 1/3] PCI: allow P2P bridge windows starting at PCI bus address zero Bjorn Helgaas
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Bjorn Helgaas @ 2012-07-09 20:31 UTC (permalink / raw)
  To: linux-pci; +Cc: Daniel Yeisley, Yinghai Lu, linux-kernel, David S. Miller

Two fixes here:

1) Zero is a legal P2P bridge window base and BAR value and is likely to
occur when there is an offset between bus addresses and CPU addresses.
Stop disallowing it.

2) The Intel-specific 1K I/O window granularity for P2P bridges was
implemented in a way that precluded reassignment of the window after
FINAL quirks.  Fix that.

And also replace the sparc pci_cfg_fake_ranges() with the functionally
equivalent generic version.

---

Bjorn Helgaas (3):
      PCI: allow P2P bridge windows starting at PCI bus address zero
      PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
      sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases()


 arch/sparc/kernel/pci.c  |   89 +---------------------------------------------
 drivers/pci/probe.c      |   31 +++++++++-------
 drivers/pci/quirks.c     |   39 +-------------------
 drivers/pci/setup-bus.c  |   11 +++++-
 include/linux/pci.h      |    1 +
 include/linux/pci_regs.h |    3 +-
 6 files changed, 31 insertions(+), 143 deletions(-)

-- 
Bjorn

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/3] PCI: allow P2P bridge windows starting at PCI bus address zero
  2012-07-09 20:31 [PATCH 0/3] PCI: P2P bridge window fixes Bjorn Helgaas
@ 2012-07-09 20:32 ` Bjorn Helgaas
  2012-07-09 21:11   ` Yinghai Lu
  2012-07-09 20:32 ` [PATCH 2/3] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2) Bjorn Helgaas
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Bjorn Helgaas @ 2012-07-09 20:32 UTC (permalink / raw)
  To: linux-pci; +Cc: Daniel Yeisley, Yinghai Lu, linux-kernel, David S. Miller

cd81e1ea1a4c added checks that prevent us from using P2P bridge windows
that start at PCI bus address zero.  The reason was to "prevent us from
overwriting resources that are unassigned."

But generic code should allow address zero in both BARs and bridge
windows, so I think that commit was a mistake.

Windows at bus address zero are legal and likely to exist on machines with
an offset between bus addresses and CPU addresses.  For example, in the
following hypothetical scenario, the bridge at 00:01.0 has a window at bus
address zero and the device at 01:00.0 has a BAR at bus address zero, and
I think both are perfectly valid:

    PCI host bridge to bus 0000:00
    pci_bus 0000:00: root bus resource [mem 0x100000000-0x1ffffffff] (bus address [0x00000000-0xffffffff])
    pci 0000:00:01.0: PCI bridge to [bus 01]
    pci 0000:00:01.0:   bridge window [mem 0x100000000-0x100ffffff]
    pci 0000:01:00.0: reg 10: [mem 0x100000000-0x100ffffff]

CC: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/probe.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 658ac97..9c5d2a9 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -287,7 +287,7 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
 		limit |= (io_limit_hi << 16);
 	}
 
-	if (base && base <= limit) {
+	if (base <= limit) {
 		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
 		res2.flags = res->flags;
 		region.start = base;
@@ -314,7 +314,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
 	pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
 	base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
 	limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
-	if (base && base <= limit) {
+	if (base <= limit) {
 		res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
 		region.start = base;
 		region.end = limit + 0xfffff;
@@ -360,7 +360,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
 #endif
 		}
 	}
-	if (base && base <= limit) {
+	if (base <= limit) {
 		res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
 					 IORESOURCE_MEM | IORESOURCE_PREFETCH;
 		if (res->flags & PCI_PREF_RANGE_TYPE_64)


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/3] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
  2012-07-09 20:31 [PATCH 0/3] PCI: P2P bridge window fixes Bjorn Helgaas
  2012-07-09 20:32 ` [PATCH 1/3] PCI: allow P2P bridge windows starting at PCI bus address zero Bjorn Helgaas
@ 2012-07-09 20:32 ` Bjorn Helgaas
  2012-07-09 21:43   ` Yinghai Lu
  2012-07-09 20:32   ` Bjorn Helgaas
  2012-07-10  3:24 ` [PATCH 0/3] PCI: P2P bridge window fixes Bjorn Helgaas
  3 siblings, 1 reply; 13+ messages in thread
From: Bjorn Helgaas @ 2012-07-09 20:32 UTC (permalink / raw)
  To: linux-pci; +Cc: Daniel Yeisley, Yinghai Lu, linux-kernel, David S. Miller

9d265124d051 and 15a260d53f7c added quirks for P2P bridges that support
I/O windows that start/end at 1K boundaries, not just the 4K boundaries
defined by the PCI spec.  For details, see the IOBL_ADR register and the
EN1K bit in the CNF register in the Intel 82870P2 (P64H2).

These quirks complicate the code that reads P2P bridge windows
(pci_read_bridge_io() and pci_cfg_fake_ranges()) because the bridge
I/O resource is updated in the HEADER quirk, in pci_read_bridge_io(),
in pci_setup_bridge(), and again in the FINAL quirk.  This is confusing
and makes it impossible to reassign the bridge windows after FINAL
quirks are run.

This patch adds support for 1K windows in the generic paths, so the
HEADER quirk only has to enable this support.  The FINAL quirk, which
used to undo damage done by pci_setup_bridge(), is no longer needed.

This removes "if (!res->start) res->start = ..." from pci_read_bridge_io();
that was part of 9d265124d051 to avoid overwriting the resource filled in
by the quirk.  Since pci_read_bridge_io() itself now knows about
granularity, the quirk no longer updates the resource and this test is no
longer needed.

Note that the bridge window assignment code, e.g., pbus_size_io(), should
pay attention to dev->io_window_1k, too, but I didn't fix that.

Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/probe.c      |   25 ++++++++++++++-----------
 drivers/pci/quirks.c     |   39 +--------------------------------------
 drivers/pci/setup-bus.c  |   11 +++++++++--
 include/linux/pci.h      |    1 +
 include/linux/pci_regs.h |    3 ++-
 5 files changed, 27 insertions(+), 52 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 9c5d2a9..ef24cf7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -269,15 +269,23 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
 {
 	struct pci_dev *dev = child->self;
 	u8 io_base_lo, io_limit_lo;
-	unsigned long base, limit;
+	unsigned long io_mask, io_granularity, base, limit;
 	struct pci_bus_region region;
-	struct resource *res, res2;
+	struct resource *res;
+
+	io_mask = PCI_IO_RANGE_MASK;
+	io_granularity = 0x1000;
+	if (dev->io_window_1k) {
+		/* Support 1K I/O space granularity */
+		io_mask = PCI_IO_1K_RANGE_MASK;
+		io_granularity = 0x400;
+	}
 
 	res = child->resource[0];
 	pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
 	pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
-	base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
-	limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
+	base = (io_base_lo & io_mask) << 8;
+	limit = (io_limit_lo & io_mask) << 8;
 
 	if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
 		u16 io_base_hi, io_limit_hi;
@@ -289,14 +297,9 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
 
 	if (base <= limit) {
 		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
-		res2.flags = res->flags;
 		region.start = base;
-		region.end = limit + 0xfff;
-		pcibios_bus_to_resource(dev, &res2, &region);
-		if (!res->start)
-			res->start = res2.start;
-		if (!res->end)
-			res->end = res2.end;
+		region.end = limit + io_granularity - 1;
+		pcibios_bus_to_resource(dev, res, &region);
 		dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
 	}
 }
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 2a75216..356846b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1938,53 +1938,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1
 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;
 
 	pci_read_config_word(dev, 0x40, &en1k);
 
 	if (en1k & 0x200) {
 		dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n");
-
-		pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
-		pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
-		base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
-		limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
-
-		if (base <= limit) {
-			res->start = base;
-			res->end = limit + 0x3ff;
-		}
+		dev->io_window_1k = 1;
 	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	0x1460,		quirk_p64h2_1k_io);
 
-/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2
- * The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge()
- * in drivers/pci/setup-bus.c
- */
-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;
-
-	pci_read_config_word(dev, 0x40, &en1k);
-
-	if (en1k & 0x200) {
-		pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr);
-
-		iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00);
-
-		if (iobl_adr != iobl_adr_1k) {
-			dev_info(&dev->dev, "Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity\n",
-				iobl_adr,iobl_adr_1k);
-			pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k);
-		}
-	}
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x1460,		quirk_p64h2_1k_io_fix_iobl);
-
 /* Under some circumstances, AER is not linked with extended capabilities.
  * Force it to be linked by setting the corresponding control bit in the
  * config space.
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 8fa2d4b..dad5425 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -469,16 +469,23 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
 	struct pci_dev *bridge = bus->self;
 	struct resource *res;
 	struct pci_bus_region region;
+	unsigned long io_mask;
+	u8 io_base_lo, io_limit_lo;
 	u32 l, io_upper16;
 
+	io_mask = PCI_IO_RANGE_MASK;
+	if (bridge->io_window_1k)
+		io_mask = PCI_IO_1K_RANGE_MASK;
+
 	/* Set up the top and bottom of the PCI I/O segment for this bus. */
 	res = bus->resource[0];
 	pcibios_resource_to_bus(bridge, &region, res);
 	if (res->flags & IORESOURCE_IO) {
 		pci_read_config_dword(bridge, PCI_IO_BASE, &l);
 		l &= 0xffff0000;
-		l |= (region.start >> 8) & 0x00f0;
-		l |= region.end & 0xf000;
+		io_base_lo = (region.start >> 8) & io_mask;
+		io_limit_lo = (region.end >> 8) & io_mask;
+		l |= ((u32) io_limit_lo << 8) | io_base_lo;
 		/* Set up upper 16 bits of I/O base/limit. */
 		io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
 		dev_info(&bridge->dev, "  bridge window %pR\n", res);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d8c379d..89b46fd 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -324,6 +324,7 @@ struct pci_dev {
 	unsigned int    is_hotplug_bridge:1;
 	unsigned int    __aer_firmware_first_valid:1;
 	unsigned int	__aer_firmware_first:1;
+	unsigned int	io_window_1k:1;	/* Intel P2P bridge 1K I/O windows */
 	pci_dev_flags_t dev_flags;
 	atomic_t	enable_cnt;	/* pci_enable_device has been called */
 
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index 4b608f5..88c9ea5 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -125,7 +125,8 @@
 #define  PCI_IO_RANGE_TYPE_MASK	0x0fUL	/* I/O bridging type */
 #define  PCI_IO_RANGE_TYPE_16	0x00
 #define  PCI_IO_RANGE_TYPE_32	0x01
-#define  PCI_IO_RANGE_MASK	(~0x0fUL)
+#define  PCI_IO_RANGE_MASK	(~0x0fUL) /* Standard 4K I/O windows */
+#define  PCI_IO_1K_RANGE_MASK	(~0x03UL) /* Intel 1K I/O windows */
 #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
 #define PCI_MEMORY_BASE		0x20	/* Memory range behind */
 #define PCI_MEMORY_LIMIT	0x22


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/3] sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases()
  2012-07-09 20:31 [PATCH 0/3] PCI: P2P bridge window fixes Bjorn Helgaas
@ 2012-07-09 20:32   ` Bjorn Helgaas
  2012-07-09 20:32 ` [PATCH 2/3] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2) Bjorn Helgaas
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Bjorn Helgaas @ 2012-07-09 20:32 UTC (permalink / raw)
  To: linux-pci
  Cc: sparclinux, Daniel Yeisley, Yinghai Lu, linux-kernel, David S. Miller

The generic code to read P2P bridge windows is functionally equivalent
to the sparc-specific pci_cfg_fake_ranges(), so use the generic code.

The "if (!res->start) res->start = ..." removed from the I/O window code
here was an artifact of the Intel 1K window support from 9d265124d051 and
is no longer necessary (it probably was just cloned from x86 and was never
useful on sparc).

CC: "David S. Miller" <davem@davemloft.net>
CC: sparclinux@vger.kernel.org
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/sparc/kernel/pci.c |   89 +----------------------------------------------
 1 files changed, 1 insertions(+), 88 deletions(-)

diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index fdaf218..fa53d55 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -375,93 +375,6 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
 	*last_p = last;
 }
 
-/* For PCI bus devices which lack a 'ranges' property we interrogate
- * the config space values to set the resources, just like the generic
- * Linux PCI probing code does.
- */
-static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
-					  struct pci_bus *bus,
-					  struct pci_pbm_info *pbm)
-{
-	struct pci_bus_region region;
-	struct resource *res, res2;
-	u8 io_base_lo, io_limit_lo;
-	u16 mem_base_lo, mem_limit_lo;
-	unsigned long base, limit;
-
-	pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
-	pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
-	base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
-	limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
-
-	if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
-		u16 io_base_hi, io_limit_hi;
-
-		pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
-		pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
-		base |= (io_base_hi << 16);
-		limit |= (io_limit_hi << 16);
-	}
-
-	res = bus->resource[0];
-	if (base <= limit) {
-		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
-		res2.flags = res->flags;
-		region.start = base;
-		region.end = limit + 0xfff;
-		pcibios_bus_to_resource(dev, &res2, &region);
-		if (!res->start)
-			res->start = res2.start;
-		if (!res->end)
-			res->end = res2.end;
-	}
-
-	pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
-	pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
-	base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
-	limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
-
-	res = bus->resource[1];
-	if (base <= limit) {
-		res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
-			      IORESOURCE_MEM);
-		region.start = base;
-		region.end = limit + 0xfffff;
-		pcibios_bus_to_resource(dev, res, &region);
-	}
-
-	pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
-	pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
-	base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
-	limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
-
-	if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
-		u32 mem_base_hi, mem_limit_hi;
-
-		pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
-		pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
-
-		/*
-		 * Some bridges set the base > limit by default, and some
-		 * (broken) BIOSes do not initialize them.  If we find
-		 * this, just assume they are not being used.
-		 */
-		if (mem_base_hi <= mem_limit_hi) {
-			base |= ((long) mem_base_hi) << 32;
-			limit |= ((long) mem_limit_hi) << 32;
-		}
-	}
-
-	res = bus->resource[2];
-	if (base <= limit) {
-		res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
-			      IORESOURCE_MEM | IORESOURCE_PREFETCH);
-		region.start = base;
-		region.end = limit + 0xfffff;
-		pcibios_bus_to_resource(dev, res, &region);
-	}
-}
-
 /* Cook up fake bus resources for SUNW,simba PCI bridges which lack
  * a proper 'ranges' property.
  */
@@ -550,7 +463,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
 		apb_fake_ranges(dev, bus, pbm);
 		goto after_ranges;
 	} else if (ranges == NULL) {
-		pci_cfg_fake_ranges(dev, bus, pbm);
+		pci_read_bridge_bases(bus);
 		goto after_ranges;
 	}
 	i = 1;


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/3] sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases()
@ 2012-07-09 20:32   ` Bjorn Helgaas
  0 siblings, 0 replies; 13+ messages in thread
From: Bjorn Helgaas @ 2012-07-09 20:32 UTC (permalink / raw)
  To: linux-pci
  Cc: sparclinux, Daniel Yeisley, Yinghai Lu, linux-kernel, David S. Miller

The generic code to read P2P bridge windows is functionally equivalent
to the sparc-specific pci_cfg_fake_ranges(), so use the generic code.

The "if (!res->start) res->start = ..." removed from the I/O window code
here was an artifact of the Intel 1K window support from 9d265124d051 and
is no longer necessary (it probably was just cloned from x86 and was never
useful on sparc).

CC: "David S. Miller" <davem@davemloft.net>
CC: sparclinux@vger.kernel.org
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/sparc/kernel/pci.c |   89 +----------------------------------------------
 1 files changed, 1 insertions(+), 88 deletions(-)

diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index fdaf218..fa53d55 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -375,93 +375,6 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
 	*last_p = last;
 }
 
-/* For PCI bus devices which lack a 'ranges' property we interrogate
- * the config space values to set the resources, just like the generic
- * Linux PCI probing code does.
- */
-static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
-					  struct pci_bus *bus,
-					  struct pci_pbm_info *pbm)
-{
-	struct pci_bus_region region;
-	struct resource *res, res2;
-	u8 io_base_lo, io_limit_lo;
-	u16 mem_base_lo, mem_limit_lo;
-	unsigned long base, limit;
-
-	pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
-	pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
-	base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
-	limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
-
-	if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) = PCI_IO_RANGE_TYPE_32) {
-		u16 io_base_hi, io_limit_hi;
-
-		pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
-		pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
-		base |= (io_base_hi << 16);
-		limit |= (io_limit_hi << 16);
-	}
-
-	res = bus->resource[0];
-	if (base <= limit) {
-		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
-		res2.flags = res->flags;
-		region.start = base;
-		region.end = limit + 0xfff;
-		pcibios_bus_to_resource(dev, &res2, &region);
-		if (!res->start)
-			res->start = res2.start;
-		if (!res->end)
-			res->end = res2.end;
-	}
-
-	pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
-	pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
-	base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
-	limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
-
-	res = bus->resource[1];
-	if (base <= limit) {
-		res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
-			      IORESOURCE_MEM);
-		region.start = base;
-		region.end = limit + 0xfffff;
-		pcibios_bus_to_resource(dev, res, &region);
-	}
-
-	pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
-	pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
-	base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
-	limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
-
-	if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) = PCI_PREF_RANGE_TYPE_64) {
-		u32 mem_base_hi, mem_limit_hi;
-
-		pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
-		pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
-
-		/*
-		 * Some bridges set the base > limit by default, and some
-		 * (broken) BIOSes do not initialize them.  If we find
-		 * this, just assume they are not being used.
-		 */
-		if (mem_base_hi <= mem_limit_hi) {
-			base |= ((long) mem_base_hi) << 32;
-			limit |= ((long) mem_limit_hi) << 32;
-		}
-	}
-
-	res = bus->resource[2];
-	if (base <= limit) {
-		res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
-			      IORESOURCE_MEM | IORESOURCE_PREFETCH);
-		region.start = base;
-		region.end = limit + 0xfffff;
-		pcibios_bus_to_resource(dev, res, &region);
-	}
-}
-
 /* Cook up fake bus resources for SUNW,simba PCI bridges which lack
  * a proper 'ranges' property.
  */
@@ -550,7 +463,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
 		apb_fake_ranges(dev, bus, pbm);
 		goto after_ranges;
 	} else if (ranges = NULL) {
-		pci_cfg_fake_ranges(dev, bus, pbm);
+		pci_read_bridge_bases(bus);
 		goto after_ranges;
 	}
 	i = 1;


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] PCI: allow P2P bridge windows starting at PCI bus address zero
  2012-07-09 20:32 ` [PATCH 1/3] PCI: allow P2P bridge windows starting at PCI bus address zero Bjorn Helgaas
@ 2012-07-09 21:11   ` Yinghai Lu
  0 siblings, 0 replies; 13+ messages in thread
From: Yinghai Lu @ 2012-07-09 21:11 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: linux-pci, Daniel Yeisley, linux-kernel, David S. Miller

On Mon, Jul 9, 2012 at 1:32 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> cd81e1ea1a4c added checks that prevent us from using P2P bridge windows
> that start at PCI bus address zero.  The reason was to "prevent us from
> overwriting resources that are unassigned."
>
> But generic code should allow address zero in both BARs and bridge
> windows, so I think that commit was a mistake.
>
> Windows at bus address zero are legal and likely to exist on machines with
> an offset between bus addresses and CPU addresses.  For example, in the
> following hypothetical scenario, the bridge at 00:01.0 has a window at bus
> address zero and the device at 01:00.0 has a BAR at bus address zero, and
> I think both are perfectly valid:
>
>     PCI host bridge to bus 0000:00
>     pci_bus 0000:00: root bus resource [mem 0x100000000-0x1ffffffff] (bus address [0x00000000-0xffffffff])
>     pci 0000:00:01.0: PCI bridge to [bus 01]
>     pci 0000:00:01.0:   bridge window [mem 0x100000000-0x100ffffff]
>     pci 0000:01:00.0: reg 10: [mem 0x100000000-0x100ffffff]
>
> CC: Yinghai Lu <yinghai@kernel.org>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Acked-by: Yinghai Lu <yinghai@kernel.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases()
  2012-07-09 20:32   ` Bjorn Helgaas
@ 2012-07-09 21:25     ` David Miller
  -1 siblings, 0 replies; 13+ messages in thread
From: David Miller @ 2012-07-09 21:25 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, sparclinux, dan.yeisley, yinghai, linux-kernel

From: Bjorn Helgaas <bhelgaas@google.com>
Date: Mon, 09 Jul 2012 14:32:14 -0600

> The generic code to read P2P bridge windows is functionally equivalent
> to the sparc-specific pci_cfg_fake_ranges(), so use the generic code.
> 
> The "if (!res->start) res->start = ..." removed from the I/O window code
> here was an artifact of the Intel 1K window support from 9d265124d051 and
> is no longer necessary (it probably was just cloned from x86 and was never
> useful on sparc).
> 
> CC: "David S. Miller" <davem@davemloft.net>
> CC: sparclinux@vger.kernel.org
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases()
@ 2012-07-09 21:25     ` David Miller
  0 siblings, 0 replies; 13+ messages in thread
From: David Miller @ 2012-07-09 21:25 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, sparclinux, dan.yeisley, yinghai, linux-kernel

From: Bjorn Helgaas <bhelgaas@google.com>
Date: Mon, 09 Jul 2012 14:32:14 -0600

> The generic code to read P2P bridge windows is functionally equivalent
> to the sparc-specific pci_cfg_fake_ranges(), so use the generic code.
> 
> The "if (!res->start) res->start = ..." removed from the I/O window code
> here was an artifact of the Intel 1K window support from 9d265124d051 and
> is no longer necessary (it probably was just cloned from x86 and was never
> useful on sparc).
> 
> CC: "David S. Miller" <davem@davemloft.net>
> CC: sparclinux@vger.kernel.org
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
  2012-07-09 20:32 ` [PATCH 2/3] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2) Bjorn Helgaas
@ 2012-07-09 21:43   ` Yinghai Lu
  2012-07-09 22:21     ` Bjorn Helgaas
  0 siblings, 1 reply; 13+ messages in thread
From: Yinghai Lu @ 2012-07-09 21:43 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: linux-pci, Daniel Yeisley, linux-kernel, David S. Miller

[-- Attachment #1: Type: text/plain, Size: 475 bytes --]

On Mon, Jul 9, 2012 at 1:32 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>
> Note that the bridge window assignment code, e.g., pbus_size_io(), should
> pay attention to dev->io_window_1k, too, but I didn't fix that.

Please check attached patch that will fix pbus_size_io.

You may fold the patch in your patch, or could split your patch to
two. First one
only add io_window_1k, and second one will use io_window_1k. Then could put my
patch between them.

Thanks

Yinghai

[-- Attachment #2: io_window_1k.patch --]
[-- Type: application/octet-stream, Size: 2427 bytes --]

Subject: [PATCH] PCI: update pbus_size_io() to support io_window_1k

So if children device alignment is small than 1k, we could use 1k as bridge
alignment.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 drivers/pci/setup-bus.c |   22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

Index: linux-2.6/drivers/pci/setup-bus.c
===================================================================
--- linux-2.6.orig/drivers/pci/setup-bus.c
+++ linux-2.6/drivers/pci/setup-bus.c
@@ -717,10 +717,13 @@ static void pbus_size_io(struct pci_bus
 	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
 	unsigned long size = 0, size0 = 0, size1 = 0;
 	resource_size_t children_add_size = 0;
+	resource_size_t min_align = 4096, align;
 
 	if (!b_res)
  		return;
 
+	if (bus->self->io_window_1k)
+		min_align = 1024;
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		int i;
 
@@ -738,17 +741,25 @@ static void pbus_size_io(struct pci_bus
 			else
 				size1 += r_size;
 
+			align = pci_resource_alignment(dev, r);
+			if (align > min_align)
+				min_align = align;
+
 			if (realloc_head)
 				children_add_size += get_res_add_size(realloc_head, r);
 		}
 	}
+
+	if (min_align > 4096)
+		min_align = 4096;
+
 	size0 = calculate_iosize(size, min_size, size1,
-			resource_size(b_res), 4096);
+			resource_size(b_res), min_align);
 	if (children_add_size > add_size)
 		add_size = children_add_size;
 	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
 		calculate_iosize(size, min_size, add_size + size1,
-			resource_size(b_res), 4096);
+			resource_size(b_res), min_align);
 	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
@@ -757,12 +768,13 @@ static void pbus_size_io(struct pci_bus
 		b_res->flags = 0;
 		return;
 	}
-	/* Alignment of the IO window is always 4K */
-	b_res->start = 4096;
+	/* Alignment of the IO window should be 4K, but could be 1K sometimes */
+	b_res->start = min_align;
 	b_res->end = b_res->start + size0 - 1;
 	b_res->flags |= IORESOURCE_STARTALIGN;
 	if (size1 > size0 && realloc_head) {
-		add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
+		add_to_list(realloc_head, bus->self, b_res, size1-size0,
+				 min_align);
 		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
 				 "%pR to %pR add_size %lx\n", b_res,
 				 &bus->busn_res, size1-size0);

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
  2012-07-09 21:43   ` Yinghai Lu
@ 2012-07-09 22:21     ` Bjorn Helgaas
  2012-07-09 23:50       ` Yinghai Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Bjorn Helgaas @ 2012-07-09 22:21 UTC (permalink / raw)
  To: Yinghai Lu; +Cc: linux-pci, Daniel Yeisley, linux-kernel, David S. Miller

On Mon, Jul 9, 2012 at 3:43 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Mon, Jul 9, 2012 at 1:32 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>>
>> Note that the bridge window assignment code, e.g., pbus_size_io(), should
>> pay attention to dev->io_window_1k, too, but I didn't fix that.
>
> Please check attached patch that will fix pbus_size_io.

Thanks for posting this again.  I had looked for it, but couldn't find it.

> You may fold the patch in your patch, or could split your patch to
> two. First one
> only add io_window_1k, and second one will use io_window_1k. Then could put my
> patch between them.

What bad things would happen if I just appended your patch to the end
of this series?  Would that break bisection in some scenario?

Bjorn

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
  2012-07-09 22:21     ` Bjorn Helgaas
@ 2012-07-09 23:50       ` Yinghai Lu
  0 siblings, 0 replies; 13+ messages in thread
From: Yinghai Lu @ 2012-07-09 23:50 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: linux-pci, Daniel Yeisley, linux-kernel, David S. Miller

On Mon, Jul 9, 2012 at 3:21 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:

> What bad things would happen if I just appended your patch to the end
> of this series?  Would that break bisection in some scenario?

Should be ok. it should not break bisection.
Don't think sizing is working for 1k before.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/3] PCI: P2P bridge window fixes
  2012-07-09 20:31 [PATCH 0/3] PCI: P2P bridge window fixes Bjorn Helgaas
                   ` (2 preceding siblings ...)
  2012-07-09 20:32   ` Bjorn Helgaas
@ 2012-07-10  3:24 ` Bjorn Helgaas
  2012-07-10 15:08   ` Bjorn Helgaas
  3 siblings, 1 reply; 13+ messages in thread
From: Bjorn Helgaas @ 2012-07-10  3:24 UTC (permalink / raw)
  To: linux-pci; +Cc: Yinghai Lu, linux-kernel, David S. Miller

On Mon, Jul 9, 2012 at 2:31 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> Two fixes here:
>
> 1) Zero is a legal P2P bridge window base and BAR value and is likely to
> occur when there is an offset between bus addresses and CPU addresses.
> Stop disallowing it.
>
> 2) The Intel-specific 1K I/O window granularity for P2P bridges was
> implemented in a way that precluded reassignment of the window after
> FINAL quirks.  Fix that.
>
> And also replace the sparc pci_cfg_fake_ranges() with the functionally
> equivalent generic version.
>
> ---
>
> Bjorn Helgaas (3):
>       PCI: allow P2P bridge windows starting at PCI bus address zero
>       PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
>       sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases()
>
>
>  arch/sparc/kernel/pci.c  |   89 +---------------------------------------------
>  drivers/pci/probe.c      |   31 +++++++++-------
>  drivers/pci/quirks.c     |   39 +-------------------
>  drivers/pci/setup-bus.c  |   11 +++++-
>  include/linux/pci.h      |    1 +
>  include/linux/pci_regs.h |    3 +-
>  6 files changed, 31 insertions(+), 143 deletions(-)

I applied these, as well as Yinghai's patch for 1K support in
pbus_size_io(), to my "next" branch.  Thanks, Yinghai!

Bjorn

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/3] PCI: P2P bridge window fixes
  2012-07-10  3:24 ` [PATCH 0/3] PCI: P2P bridge window fixes Bjorn Helgaas
@ 2012-07-10 15:08   ` Bjorn Helgaas
  0 siblings, 0 replies; 13+ messages in thread
From: Bjorn Helgaas @ 2012-07-10 15:08 UTC (permalink / raw)
  To: linux-pci; +Cc: Yinghai Lu, linux-kernel, David S. Miller

On Mon, Jul 9, 2012 at 9:24 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Mon, Jul 9, 2012 at 2:31 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> Two fixes here:
>>
>> 1) Zero is a legal P2P bridge window base and BAR value and is likely to
>> occur when there is an offset between bus addresses and CPU addresses.
>> Stop disallowing it.
>>
>> 2) The Intel-specific 1K I/O window granularity for P2P bridges was
>> implemented in a way that precluded reassignment of the window after
>> FINAL quirks.  Fix that.
>>
>> And also replace the sparc pci_cfg_fake_ranges() with the functionally
>> equivalent generic version.
>>
>> ---
>>
>> Bjorn Helgaas (3):
>>       PCI: allow P2P bridge windows starting at PCI bus address zero
>>       PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
>>       sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases()
>>
>>
>>  arch/sparc/kernel/pci.c  |   89 +---------------------------------------------
>>  drivers/pci/probe.c      |   31 +++++++++-------
>>  drivers/pci/quirks.c     |   39 +-------------------
>>  drivers/pci/setup-bus.c  |   11 +++++-
>>  include/linux/pci.h      |    1 +
>>  include/linux/pci_regs.h |    3 +-
>>  6 files changed, 31 insertions(+), 143 deletions(-)
>
> I applied these, as well as Yinghai's patch for 1K support in
> pbus_size_io(), to my "next" branch.  Thanks, Yinghai!

FYI, I just rebased my "next" branch to fix the authorship of
Yinghai's patch.  Only the merge of these four patches (the most
recent merge) is affected.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-07-10 15:08 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-09 20:31 [PATCH 0/3] PCI: P2P bridge window fixes Bjorn Helgaas
2012-07-09 20:32 ` [PATCH 1/3] PCI: allow P2P bridge windows starting at PCI bus address zero Bjorn Helgaas
2012-07-09 21:11   ` Yinghai Lu
2012-07-09 20:32 ` [PATCH 2/3] PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2) Bjorn Helgaas
2012-07-09 21:43   ` Yinghai Lu
2012-07-09 22:21     ` Bjorn Helgaas
2012-07-09 23:50       ` Yinghai Lu
2012-07-09 20:32 ` [PATCH 3/3] sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases() Bjorn Helgaas
2012-07-09 20:32   ` Bjorn Helgaas
2012-07-09 21:25   ` David Miller
2012-07-09 21:25     ` David Miller
2012-07-10  3:24 ` [PATCH 0/3] PCI: P2P bridge window fixes Bjorn Helgaas
2012-07-10 15:08   ` Bjorn Helgaas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.