* [PATCH] PCI: Don't reject 64bit mmio on 32bit/PAE mode
@ 2014-11-14 3:59 Yinghai Lu
2014-11-15 0:26 ` Bjorn Helgaas
0 siblings, 1 reply; 2+ messages in thread
From: Yinghai Lu @ 2014-11-14 3:59 UTC (permalink / raw)
To: Bjorn Helgaas, Andrew Morton, H. Peter Anvin, Ingo Molnar
Cc: linux-pci, linux-kernel, Yinghai Lu
Aaron reported 32bit/PAE mode, has problem with 64bit resource.
[ 6.610012] pci 0000:03:00.0: reg 0x10: [mem 0x383fffc00000-0x383fffdfffff 64bit pref]
[ 6.622195] pci 0000:03:00.0: reg 0x20: [mem 0x383fffe04000-0x383fffe07fff 64bit pref]
[ 6.656112] pci 0000:03:00.1: reg 0x10: [mem 0x383fffa00000-0x383fffbfffff 64bit pref]
[ 6.668293] pci 0000:03:00.1: reg 0x20: [mem 0x383fffe00000-0x383fffe03fff 64bit pref]
[ 6.702055] pci 0000:00:02.2: PCI bridge to [bus 03-04]
[ 6.706434] pci 0000:00:02.2: bridge window [io 0x1000-0x1fff]
[ 6.711783] pci 0000:00:02.2: bridge window [mem 0x91900000-0x91cfffff]
[ 6.717906] pci 0000:00:02.2: can't handle 64-bit address space for bridge
So the kernel reject 64bit mmio on pci pref bridge that is assigned by
firmware.
When 32bit PAE is enabled, we could support 64bit mmio.
but BITS_PER_LONG==64 checking could reject firmware assigned mmio that
is above 4G. On x86 32bit always has BITS_PER_LONG equal to 32.
We could use CONFIG_ARCH_DMA_ADDR_T_64BIT or dma_addr_t size checking instead.
Use dma_addr_t size checking to avoid using MARCO.
Also need to change to use dma_addr_t instead of unsigned long
for base/limit to avoid overflow.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=88131
Reported-by: Aaron Ma <mapengyu@gmail.com>
Tested-by: Aaron Ma <mapengyu@gmail.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/probe.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
Index: linux-2.6/drivers/pci/probe.c
===================================================================
--- linux-2.6.orig/drivers/pci/probe.c
+++ linux-2.6/drivers/pci/probe.c
@@ -406,15 +406,15 @@ static void pci_read_bridge_mmio_pref(st
{
struct pci_dev *dev = child->self;
u16 mem_base_lo, mem_limit_lo;
- unsigned long base, limit;
+ dma_addr_t base, limit;
struct pci_bus_region region;
struct resource *res;
res = child->resource[2];
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 = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
- limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
+ base = ((dma_addr_t) mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
+ limit = ((dma_addr_t) 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;
@@ -428,15 +428,15 @@ static void pci_read_bridge_mmio_pref(st
* this, just assume they are not being used.
*/
if (mem_base_hi <= mem_limit_hi) {
-#if BITS_PER_LONG == 64
- base |= ((unsigned long) mem_base_hi) << 32;
- limit |= ((unsigned long) mem_limit_hi) << 32;
-#else
- if (mem_base_hi || mem_limit_hi) {
- dev_err(&dev->dev, "can't handle 64-bit address space for bridge\n");
- return;
+ if (sizeof(dma_addr_t) < 8) {
+ if (mem_base_hi || mem_limit_hi) {
+ dev_err(&dev->dev, "can't handle 64-bit address space for bridge\n");
+ return;
+ }
+ } else {
+ base |= ((dma_addr_t) mem_base_hi) << 32;
+ limit |= ((dma_addr_t) mem_limit_hi) << 32;
}
-#endif
}
}
if (base <= limit) {
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] PCI: Don't reject 64bit mmio on 32bit/PAE mode
2014-11-14 3:59 [PATCH] PCI: Don't reject 64bit mmio on 32bit/PAE mode Yinghai Lu
@ 2014-11-15 0:26 ` Bjorn Helgaas
0 siblings, 0 replies; 2+ messages in thread
From: Bjorn Helgaas @ 2014-11-15 0:26 UTC (permalink / raw)
To: Yinghai Lu
Cc: Andrew Morton, H. Peter Anvin, Ingo Molnar, linux-pci,
linux-kernel
On Thu, Nov 13, 2014 at 07:59:10PM -0800, Yinghai Lu wrote:
> Aaron reported 32bit/PAE mode, has problem with 64bit resource.
>
> [ 6.610012] pci 0000:03:00.0: reg 0x10: [mem 0x383fffc00000-0x383fffdfffff 64bit pref]
> [ 6.622195] pci 0000:03:00.0: reg 0x20: [mem 0x383fffe04000-0x383fffe07fff 64bit pref]
> [ 6.656112] pci 0000:03:00.1: reg 0x10: [mem 0x383fffa00000-0x383fffbfffff 64bit pref]
> [ 6.668293] pci 0000:03:00.1: reg 0x20: [mem 0x383fffe00000-0x383fffe03fff 64bit pref]
> [ 6.702055] pci 0000:00:02.2: PCI bridge to [bus 03-04]
> [ 6.706434] pci 0000:00:02.2: bridge window [io 0x1000-0x1fff]
> [ 6.711783] pci 0000:00:02.2: bridge window [mem 0x91900000-0x91cfffff]
> [ 6.717906] pci 0000:00:02.2: can't handle 64-bit address space for bridge
>
> So the kernel reject 64bit mmio on pci pref bridge that is assigned by
> firmware.
>
> When 32bit PAE is enabled, we could support 64bit mmio.
> but BITS_PER_LONG==64 checking could reject firmware assigned mmio that
> is above 4G. On x86 32bit always has BITS_PER_LONG equal to 32.
>
> We could use CONFIG_ARCH_DMA_ADDR_T_64BIT or dma_addr_t size checking instead.
> Use dma_addr_t size checking to avoid using MARCO.
>
> Also need to change to use dma_addr_t instead of unsigned long
> for base/limit to avoid overflow.
>
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=88131
> Reported-by: Aaron Ma <mapengyu@gmail.com>
> Tested-by: Aaron Ma <mapengyu@gmail.com>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Applied to for-linus for v3.18, thanks!
> ---
> drivers/pci/probe.c | 22 +++++++++++-----------
> 1 file changed, 11 insertions(+), 11 deletions(-)
>
> Index: linux-2.6/drivers/pci/probe.c
> ===================================================================
> --- linux-2.6.orig/drivers/pci/probe.c
> +++ linux-2.6/drivers/pci/probe.c
> @@ -406,15 +406,15 @@ static void pci_read_bridge_mmio_pref(st
> {
> struct pci_dev *dev = child->self;
> u16 mem_base_lo, mem_limit_lo;
> - unsigned long base, limit;
> + dma_addr_t base, limit;
> struct pci_bus_region region;
> struct resource *res;
>
> res = child->resource[2];
> 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 = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
> - limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
> + base = ((dma_addr_t) mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
> + limit = ((dma_addr_t) 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;
> @@ -428,15 +428,15 @@ static void pci_read_bridge_mmio_pref(st
> * this, just assume they are not being used.
> */
> if (mem_base_hi <= mem_limit_hi) {
> -#if BITS_PER_LONG == 64
> - base |= ((unsigned long) mem_base_hi) << 32;
> - limit |= ((unsigned long) mem_limit_hi) << 32;
> -#else
> - if (mem_base_hi || mem_limit_hi) {
> - dev_err(&dev->dev, "can't handle 64-bit address space for bridge\n");
> - return;
> + if (sizeof(dma_addr_t) < 8) {
> + if (mem_base_hi || mem_limit_hi) {
> + dev_err(&dev->dev, "can't handle 64-bit address space for bridge\n");
> + return;
> + }
> + } else {
> + base |= ((dma_addr_t) mem_base_hi) << 32;
> + limit |= ((dma_addr_t) mem_limit_hi) << 32;
> }
> -#endif
> }
> }
> if (base <= limit) {
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-11-15 0:26 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-14 3:59 [PATCH] PCI: Don't reject 64bit mmio on 32bit/PAE mode Yinghai Lu
2014-11-15 0:26 ` Bjorn Helgaas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).