aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2011-06-14 15:04:29 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2011-07-22 12:06:58 -0400
commit8d6a6a47636648754dc371b01228520a2adaf430 (patch)
tree5bab37b155798d9db8549fe6ee28499b1a5633c5 /drivers/pci
parentc9b378c7cbf623649e4ca64f955f2afd12ef01b2 (diff)
PCI: treat mem BAR type "11" (reserved) as 32-bit, not 64-bit, BAR
This fixes a minor regression where broken PCI devices that use the reserved "11" memory BAR type worked before e354597cce but not after. The low four bits of 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, including prefetchable 64-bit BARs ("1100") as 32-bit BARs. The e354597cce fix, which appeared in 2.6.28, treats "x1x0" as 64-bit BARs, so the reserved "x110" types are treated as 64-bit instead of 32-bit. 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 <peterc@gelato.unsw.edu.au> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=35952 Reported-by: Jan Zwiegers <jan@radicalsystems.co.za> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/probe.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index f03ed96533d5..3e7a00a3fc81 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -100,8 +100,11 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask)
100 return size; 100 return size;
101} 101}
102 102
103static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) 103static inline enum pci_bar_type decode_bar(struct pci_dev *dev,
104 struct resource *res, u32 bar)
104{ 105{
106 u32 mem_type;
107
105 if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { 108 if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
106 res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; 109 res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK;
107 return pci_bar_io; 110 return pci_bar_io;
@@ -109,8 +112,21 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
109 112
110 res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; 113 res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
111 114
112 if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) 115 mem_type = bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
116 switch (mem_type) {
117 case PCI_BASE_ADDRESS_MEM_TYPE_32:
118 break;
119 case PCI_BASE_ADDRESS_MEM_TYPE_1M:
120 dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
121 break;
122 case PCI_BASE_ADDRESS_MEM_TYPE_64:
113 return pci_bar_mem64; 123 return pci_bar_mem64;
124 default:
125 dev_warn(&dev->dev,
126 "mem unknown type %x treated as 32-bit BAR\n",
127 mem_type);
128 break;
129 }
114 return pci_bar_mem32; 130 return pci_bar_mem32;
115} 131}
116 132
@@ -164,7 +180,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
164 l = 0; 180 l = 0;
165 181
166 if (type == pci_bar_unknown) { 182 if (type == pci_bar_unknown) {
167 type = decode_bar(res, l); 183 type = decode_bar(dev, res, l);
168 res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; 184 res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
169 if (type == pci_bar_io) { 185 if (type == pci_bar_io) {
170 l &= PCI_BASE_ADDRESS_IO_MASK; 186 l &= PCI_BASE_ADDRESS_IO_MASK;