commit fbeed946be827b46f6801332ef0fdc9b00939e81 Author: Bjorn Helgaas Date: Tue May 24 06:48:22 2011 -0600 PCI: pass pci_dev to decode_bar() for use in dev_warn() Pass in pci_dev pointer for future use in warning messages. Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 44cbbba..770b632 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -136,7 +136,8 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask) return size; } -static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) +static inline enum pci_bar_type decode_bar(struct pci_dev *dev, + struct resource *res, u32 bar) { if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; @@ -200,7 +201,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, l = 0; if (type == pci_bar_unknown) { - type = decode_bar(res, l); + type = decode_bar(dev, res, l); res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; if (type == pci_bar_io) { l &= PCI_BASE_ADDRESS_IO_MASK; commit 5d20e2d046be6867188986eef4b4cd6ec9f27882 Author: Bjorn Helgaas Date: Fri May 20 08:36:30 2011 -0600 PCI: don't treat mem BAR type "11" (reserved) as 64-bit BAR The low four bits of a a memory BAR are "ptt0" where p=1 for prefetchable BARs, and tt is as follows: 00 32-bit BAR, anywhere in lower 4GB 01 anywhere below 1MB (reserved as of PCI 2.2) 10 64-bit BAR 11 reserved Prior to e354597cce, we treated "0100" as a 64-bit BAR and all others as 32-bit BARs. This was obviously wrong because prefetchable 64-bit BARs ("1100") were treated as 32-bit BARs. The e354597cce fix, which appeared in 2.6.28, was to treat "x1x0" as 64-bit BARs, but this unintentionally changed our handling of reserved type "x110" from 32-bit to 64-bit. Hardware should not be using the "11" type, but if it did happen to use it for a 32-bit BAR, it worked before e354597cce and didn't work afterwards. Jan has a piece of such hardware. This patch returns to treating the reserved "11" type as a 32-bit BAR and adds a warning if we see it. It also logs a note if we see a 1M BAR. This is not a warning, because such hardware conforms to pre-PCI 2.2 spec, but I think it's worth noting because Linux ignores the 1M restriction if it ever has to assign the BAR. CC: Peter Chubb Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=35952 Reported-by: Jan Zwiegers Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 770b632..602b2c4 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -139,16 +139,31 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask) static inline enum pci_bar_type decode_bar(struct pci_dev *dev, struct resource *res, u32 bar) { + u32 mem_type; + if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; return pci_bar_io; } - res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; - - if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) + res->flags = bar & PCI_BASE_ADDRESS_MEM_PREFETCH; + + mem_type = bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK; + switch (mem_type) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + return pci_bar_mem32; + case PCI_BASE_ADDRESS_MEM_TYPE_1M: + dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n"); + return pci_bar_mem32; + case PCI_BASE_ADDRESS_MEM_TYPE_64: + res->flags |= PCI_BASE_ADDRESS_MEM_TYPE_64; return pci_bar_mem64; - return pci_bar_mem32; + default: + dev_warn(&dev->dev, + "mem unknown type %x treated as 32-bit BAR\n", + mem_type); + return pci_bar_mem32; + } } /**