diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2011-06-14 15:04:29 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2011-07-22 12:06:58 -0400 |
commit | 8d6a6a47636648754dc371b01228520a2adaf430 (patch) | |
tree | 5bab37b155798d9db8549fe6ee28499b1a5633c5 /drivers/pci | |
parent | c9b378c7cbf623649e4ca64f955f2afd12ef01b2 (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.c | 22 |
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 | ||
103 | static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) | 103 | static 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; |