diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 299 |
1 files changed, 163 insertions, 136 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b1724cf31b66..a04498d390c8 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -52,27 +52,49 @@ EXPORT_SYMBOL(no_pci_devices); | |||
52 | * Some platforms allow access to legacy I/O port and ISA memory space on | 52 | * Some platforms allow access to legacy I/O port and ISA memory space on |
53 | * a per-bus basis. This routine creates the files and ties them into | 53 | * a per-bus basis. This routine creates the files and ties them into |
54 | * their associated read, write and mmap files from pci-sysfs.c | 54 | * their associated read, write and mmap files from pci-sysfs.c |
55 | * | ||
56 | * On error unwind, but don't propogate the error to the caller | ||
57 | * as it is ok to set up the PCI bus without these files. | ||
55 | */ | 58 | */ |
56 | static void pci_create_legacy_files(struct pci_bus *b) | 59 | static void pci_create_legacy_files(struct pci_bus *b) |
57 | { | 60 | { |
61 | int error; | ||
62 | |||
58 | b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2, | 63 | b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2, |
59 | GFP_ATOMIC); | 64 | GFP_ATOMIC); |
60 | if (b->legacy_io) { | 65 | if (!b->legacy_io) |
61 | b->legacy_io->attr.name = "legacy_io"; | 66 | goto kzalloc_err; |
62 | b->legacy_io->size = 0xffff; | 67 | |
63 | b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; | 68 | b->legacy_io->attr.name = "legacy_io"; |
64 | b->legacy_io->read = pci_read_legacy_io; | 69 | b->legacy_io->size = 0xffff; |
65 | b->legacy_io->write = pci_write_legacy_io; | 70 | b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; |
66 | device_create_bin_file(&b->dev, b->legacy_io); | 71 | b->legacy_io->read = pci_read_legacy_io; |
67 | 72 | b->legacy_io->write = pci_write_legacy_io; | |
68 | /* Allocated above after the legacy_io struct */ | 73 | error = device_create_bin_file(&b->dev, b->legacy_io); |
69 | b->legacy_mem = b->legacy_io + 1; | 74 | if (error) |
70 | b->legacy_mem->attr.name = "legacy_mem"; | 75 | goto legacy_io_err; |
71 | b->legacy_mem->size = 1024*1024; | 76 | |
72 | b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR; | 77 | /* Allocated above after the legacy_io struct */ |
73 | b->legacy_mem->mmap = pci_mmap_legacy_mem; | 78 | b->legacy_mem = b->legacy_io + 1; |
74 | device_create_bin_file(&b->dev, b->legacy_mem); | 79 | b->legacy_mem->attr.name = "legacy_mem"; |
75 | } | 80 | b->legacy_mem->size = 1024*1024; |
81 | b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR; | ||
82 | b->legacy_mem->mmap = pci_mmap_legacy_mem; | ||
83 | error = device_create_bin_file(&b->dev, b->legacy_mem); | ||
84 | if (error) | ||
85 | goto legacy_mem_err; | ||
86 | |||
87 | return; | ||
88 | |||
89 | legacy_mem_err: | ||
90 | device_remove_bin_file(&b->dev, b->legacy_io); | ||
91 | legacy_io_err: | ||
92 | kfree(b->legacy_io); | ||
93 | b->legacy_io = NULL; | ||
94 | kzalloc_err: | ||
95 | printk(KERN_WARNING "pci: warning: could not create legacy I/O port " | ||
96 | "and ISA memory resources to sysfs\n"); | ||
97 | return; | ||
76 | } | 98 | } |
77 | 99 | ||
78 | void pci_remove_legacy_files(struct pci_bus *b) | 100 | void pci_remove_legacy_files(struct pci_bus *b) |
@@ -163,12 +185,9 @@ static inline unsigned int pci_calc_resource_flags(unsigned int flags) | |||
163 | return IORESOURCE_MEM; | 185 | return IORESOURCE_MEM; |
164 | } | 186 | } |
165 | 187 | ||
166 | /* | 188 | static u64 pci_size(u64 base, u64 maxbase, u64 mask) |
167 | * Find the extent of a PCI decode.. | ||
168 | */ | ||
169 | static u32 pci_size(u32 base, u32 maxbase, u32 mask) | ||
170 | { | 189 | { |
171 | u32 size = mask & maxbase; /* Find the significant bits */ | 190 | u64 size = mask & maxbase; /* Find the significant bits */ |
172 | if (!size) | 191 | if (!size) |
173 | return 0; | 192 | return 0; |
174 | 193 | ||
@@ -184,135 +203,142 @@ static u32 pci_size(u32 base, u32 maxbase, u32 mask) | |||
184 | return size; | 203 | return size; |
185 | } | 204 | } |
186 | 205 | ||
187 | static u64 pci_size64(u64 base, u64 maxbase, u64 mask) | 206 | enum pci_bar_type { |
207 | pci_bar_unknown, /* Standard PCI BAR probe */ | ||
208 | pci_bar_io, /* An io port BAR */ | ||
209 | pci_bar_mem32, /* A 32-bit memory BAR */ | ||
210 | pci_bar_mem64, /* A 64-bit memory BAR */ | ||
211 | }; | ||
212 | |||
213 | static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) | ||
188 | { | 214 | { |
189 | u64 size = mask & maxbase; /* Find the significant bits */ | 215 | if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { |
190 | if (!size) | 216 | res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; |
191 | return 0; | 217 | return pci_bar_io; |
218 | } | ||
192 | 219 | ||
193 | /* Get the lowest of them to find the decode size, and | 220 | res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; |
194 | from that the extent. */ | ||
195 | size = (size & ~(size-1)) - 1; | ||
196 | 221 | ||
197 | /* base == maxbase can be valid only if the BAR has | 222 | if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64) |
198 | already been programmed with all 1s. */ | 223 | return pci_bar_mem64; |
199 | if (base == maxbase && ((base | size) & mask) != mask) | 224 | return pci_bar_mem32; |
200 | return 0; | ||
201 | |||
202 | return size; | ||
203 | } | 225 | } |
204 | 226 | ||
205 | static inline int is_64bit_memory(u32 mask) | 227 | /* |
228 | * If the type is not unknown, we assume that the lowest bit is 'enable'. | ||
229 | * Returns 1 if the BAR was 64-bit and 0 if it was 32-bit. | ||
230 | */ | ||
231 | static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | ||
232 | struct resource *res, unsigned int pos) | ||
206 | { | 233 | { |
207 | if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == | 234 | u32 l, sz, mask; |
208 | (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) | ||
209 | return 1; | ||
210 | return 0; | ||
211 | } | ||
212 | 235 | ||
213 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | 236 | mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0; |
214 | { | ||
215 | unsigned int pos, reg, next; | ||
216 | u32 l, sz; | ||
217 | struct resource *res; | ||
218 | 237 | ||
219 | for(pos=0; pos<howmany; pos = next) { | 238 | res->name = pci_name(dev); |
220 | u64 l64; | ||
221 | u64 sz64; | ||
222 | u32 raw_sz; | ||
223 | 239 | ||
224 | next = pos+1; | 240 | pci_read_config_dword(dev, pos, &l); |
225 | res = &dev->resource[pos]; | 241 | pci_write_config_dword(dev, pos, mask); |
226 | res->name = pci_name(dev); | 242 | pci_read_config_dword(dev, pos, &sz); |
227 | reg = PCI_BASE_ADDRESS_0 + (pos << 2); | 243 | pci_write_config_dword(dev, pos, l); |
228 | pci_read_config_dword(dev, reg, &l); | 244 | |
229 | pci_write_config_dword(dev, reg, ~0); | 245 | /* |
230 | pci_read_config_dword(dev, reg, &sz); | 246 | * All bits set in sz means the device isn't working properly. |
231 | pci_write_config_dword(dev, reg, l); | 247 | * If the BAR isn't implemented, all bits must be 0. If it's a |
232 | if (!sz || sz == 0xffffffff) | 248 | * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit |
233 | continue; | 249 | * 1 must be clear. |
234 | if (l == 0xffffffff) | 250 | */ |
235 | l = 0; | 251 | if (!sz || sz == 0xffffffff) |
236 | raw_sz = sz; | 252 | goto fail; |
237 | if ((l & PCI_BASE_ADDRESS_SPACE) == | 253 | |
238 | PCI_BASE_ADDRESS_SPACE_MEMORY) { | 254 | /* |
239 | sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); | 255 | * I don't know how l can have all bits set. Copied from old code. |
240 | /* | 256 | * Maybe it fixes a bug on some ancient platform. |
241 | * For 64bit prefetchable memory sz could be 0, if the | 257 | */ |
242 | * real size is bigger than 4G, so we need to check | 258 | if (l == 0xffffffff) |
243 | * szhi for that. | 259 | l = 0; |
244 | */ | 260 | |
245 | if (!is_64bit_memory(l) && !sz) | 261 | if (type == pci_bar_unknown) { |
246 | continue; | 262 | type = decode_bar(res, l); |
247 | res->start = l & PCI_BASE_ADDRESS_MEM_MASK; | 263 | res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; |
248 | res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; | 264 | if (type == pci_bar_io) { |
265 | l &= PCI_BASE_ADDRESS_IO_MASK; | ||
266 | mask = PCI_BASE_ADDRESS_IO_MASK & 0xffff; | ||
249 | } else { | 267 | } else { |
250 | sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff); | 268 | l &= PCI_BASE_ADDRESS_MEM_MASK; |
251 | if (!sz) | 269 | mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; |
252 | continue; | ||
253 | res->start = l & PCI_BASE_ADDRESS_IO_MASK; | ||
254 | res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK; | ||
255 | } | 270 | } |
256 | res->end = res->start + (unsigned long) sz; | 271 | } else { |
257 | res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; | 272 | res->flags |= (l & IORESOURCE_ROM_ENABLE); |
258 | if (is_64bit_memory(l)) { | 273 | l &= PCI_ROM_ADDRESS_MASK; |
259 | u32 szhi, lhi; | 274 | mask = (u32)PCI_ROM_ADDRESS_MASK; |
260 | 275 | } | |
261 | pci_read_config_dword(dev, reg+4, &lhi); | 276 | |
262 | pci_write_config_dword(dev, reg+4, ~0); | 277 | if (type == pci_bar_mem64) { |
263 | pci_read_config_dword(dev, reg+4, &szhi); | 278 | u64 l64 = l; |
264 | pci_write_config_dword(dev, reg+4, lhi); | 279 | u64 sz64 = sz; |
265 | sz64 = ((u64)szhi << 32) | raw_sz; | 280 | u64 mask64 = mask | (u64)~0 << 32; |
266 | l64 = ((u64)lhi << 32) | l; | 281 | |
267 | sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK); | 282 | pci_read_config_dword(dev, pos + 4, &l); |
268 | next++; | 283 | pci_write_config_dword(dev, pos + 4, ~0); |
269 | #if BITS_PER_LONG == 64 | 284 | pci_read_config_dword(dev, pos + 4, &sz); |
270 | if (!sz64) { | 285 | pci_write_config_dword(dev, pos + 4, l); |
271 | res->start = 0; | 286 | |
272 | res->end = 0; | 287 | l64 |= ((u64)l << 32); |
273 | res->flags = 0; | 288 | sz64 |= ((u64)sz << 32); |
274 | continue; | 289 | |
275 | } | 290 | sz64 = pci_size(l64, sz64, mask64); |
276 | res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK; | 291 | |
277 | res->end = res->start + sz64; | 292 | if (!sz64) |
278 | #else | 293 | goto fail; |
279 | if (sz64 > 0x100000000ULL) { | 294 | |
280 | dev_err(&dev->dev, "BAR %d: can't handle 64-bit" | 295 | if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { |
281 | " BAR\n", pos); | 296 | dev_err(&dev->dev, "can't handle 64-bit BAR\n"); |
282 | res->start = 0; | 297 | goto fail; |
283 | res->flags = 0; | 298 | } else if ((sizeof(resource_size_t) < 8) && l) { |
284 | } else if (lhi) { | 299 | /* Address above 32-bit boundary; disable the BAR */ |
285 | /* 64-bit wide address, treat as disabled */ | 300 | pci_write_config_dword(dev, pos, 0); |
286 | pci_write_config_dword(dev, reg, | 301 | pci_write_config_dword(dev, pos + 4, 0); |
287 | l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); | 302 | res->start = 0; |
288 | pci_write_config_dword(dev, reg+4, 0); | 303 | res->end = sz64; |
289 | res->start = 0; | 304 | } else { |
290 | res->end = sz; | 305 | res->start = l64; |
291 | } | 306 | res->end = l64 + sz64; |
292 | #endif | ||
293 | } | 307 | } |
308 | } else { | ||
309 | sz = pci_size(l, sz, mask); | ||
310 | |||
311 | if (!sz) | ||
312 | goto fail; | ||
313 | |||
314 | res->start = l; | ||
315 | res->end = l + sz; | ||
294 | } | 316 | } |
317 | |||
318 | out: | ||
319 | return (type == pci_bar_mem64) ? 1 : 0; | ||
320 | fail: | ||
321 | res->flags = 0; | ||
322 | goto out; | ||
323 | } | ||
324 | |||
325 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | ||
326 | { | ||
327 | unsigned int pos, reg; | ||
328 | |||
329 | for (pos = 0; pos < howmany; pos++) { | ||
330 | struct resource *res = &dev->resource[pos]; | ||
331 | reg = PCI_BASE_ADDRESS_0 + (pos << 2); | ||
332 | pos += __pci_read_base(dev, pci_bar_unknown, res, reg); | ||
333 | } | ||
334 | |||
295 | if (rom) { | 335 | if (rom) { |
336 | struct resource *res = &dev->resource[PCI_ROM_RESOURCE]; | ||
296 | dev->rom_base_reg = rom; | 337 | dev->rom_base_reg = rom; |
297 | res = &dev->resource[PCI_ROM_RESOURCE]; | 338 | res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | |
298 | res->name = pci_name(dev); | 339 | IORESOURCE_READONLY | IORESOURCE_CACHEABLE | |
299 | pci_read_config_dword(dev, rom, &l); | 340 | IORESOURCE_SIZEALIGN; |
300 | pci_write_config_dword(dev, rom, ~PCI_ROM_ADDRESS_ENABLE); | 341 | __pci_read_base(dev, pci_bar_mem32, res, rom); |
301 | pci_read_config_dword(dev, rom, &sz); | ||
302 | pci_write_config_dword(dev, rom, l); | ||
303 | if (l == 0xffffffff) | ||
304 | l = 0; | ||
305 | if (sz && sz != 0xffffffff) { | ||
306 | sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK); | ||
307 | if (sz) { | ||
308 | res->flags = (l & IORESOURCE_ROM_ENABLE) | | ||
309 | IORESOURCE_MEM | IORESOURCE_PREFETCH | | ||
310 | IORESOURCE_READONLY | IORESOURCE_CACHEABLE | | ||
311 | IORESOURCE_SIZEALIGN; | ||
312 | res->start = l & PCI_ROM_ADDRESS_MASK; | ||
313 | res->end = res->start + (unsigned long) sz; | ||
314 | } | ||
315 | } | ||
316 | } | 342 | } |
317 | } | 343 | } |
318 | 344 | ||
@@ -1053,7 +1079,8 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) | |||
1053 | } | 1079 | } |
1054 | } | 1080 | } |
1055 | 1081 | ||
1056 | if (bus->self) | 1082 | /* only one slot has pcie device */ |
1083 | if (bus->self && nr) | ||
1057 | pcie_aspm_init_link_state(bus->self); | 1084 | pcie_aspm_init_link_state(bus->self); |
1058 | 1085 | ||
1059 | return nr; | 1086 | return nr; |