PCI: rewrite PCI BAR reading code

Factor out the code to read one BAR from the loop in pci_read_bases into
a new function, __pci_read_base. The new code is slightly more
readable, better commented and removes the ifdef.

Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

authored by

Matthew Wilcox and committed by
Jesse Barnes
6ac665c6 37139074

+127 -123
+127 -123
drivers/pci/probe.c
··· 163 return IORESOURCE_MEM; 164 } 165 166 - /* 167 - * Find the extent of a PCI decode.. 168 - */ 169 - static u32 pci_size(u32 base, u32 maxbase, u32 mask) 170 - { 171 - u32 size = mask & maxbase; /* Find the significant bits */ 172 - if (!size) 173 - return 0; 174 - 175 - /* Get the lowest of them to find the decode size, and 176 - from that the extent. */ 177 - size = (size & ~(size-1)) - 1; 178 - 179 - /* base == maxbase can be valid only if the BAR has 180 - already been programmed with all 1s. */ 181 - if (base == maxbase && ((base | size) & mask) != mask) 182 - return 0; 183 - 184 - return size; 185 - } 186 - 187 - static u64 pci_size64(u64 base, u64 maxbase, u64 mask) 188 { 189 u64 size = mask & maxbase; /* Find the significant bits */ 190 if (!size) ··· 181 return size; 182 } 183 184 - static inline int is_64bit_memory(u32 mask) 185 { 186 - if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == 187 - (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) 188 - return 1; 189 - return 0; 190 } 191 192 static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) 193 { 194 - unsigned int pos, reg, next; 195 - u32 l, sz; 196 - struct resource *res; 197 198 - for(pos=0; pos<howmany; pos = next) { 199 - u64 l64; 200 - u64 sz64; 201 - u32 raw_sz; 202 - 203 - next = pos+1; 204 - res = &dev->resource[pos]; 205 - res->name = pci_name(dev); 206 reg = PCI_BASE_ADDRESS_0 + (pos << 2); 207 - pci_read_config_dword(dev, reg, &l); 208 - pci_write_config_dword(dev, reg, ~0); 209 - pci_read_config_dword(dev, reg, &sz); 210 - pci_write_config_dword(dev, reg, l); 211 - if (!sz || sz == 0xffffffff) 212 - continue; 213 - if (l == 0xffffffff) 214 - l = 0; 215 - raw_sz = sz; 216 - if ((l & PCI_BASE_ADDRESS_SPACE) == 217 - PCI_BASE_ADDRESS_SPACE_MEMORY) { 218 - sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); 219 - /* 220 - * For 64bit prefetchable memory sz could be 0, if the 221 - * real size is bigger than 4G, so we need to check 222 - * szhi for that. 223 - */ 224 - if (!is_64bit_memory(l) && !sz) 225 - continue; 226 - res->start = l & PCI_BASE_ADDRESS_MEM_MASK; 227 - res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; 228 - } else { 229 - sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff); 230 - if (!sz) 231 - continue; 232 - res->start = l & PCI_BASE_ADDRESS_IO_MASK; 233 - res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK; 234 - } 235 - res->end = res->start + (unsigned long) sz; 236 - res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; 237 - if (is_64bit_memory(l)) { 238 - u32 szhi, lhi; 239 - 240 - pci_read_config_dword(dev, reg+4, &lhi); 241 - pci_write_config_dword(dev, reg+4, ~0); 242 - pci_read_config_dword(dev, reg+4, &szhi); 243 - pci_write_config_dword(dev, reg+4, lhi); 244 - sz64 = ((u64)szhi << 32) | raw_sz; 245 - l64 = ((u64)lhi << 32) | l; 246 - sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK); 247 - next++; 248 - #if BITS_PER_LONG == 64 249 - if (!sz64) { 250 - res->start = 0; 251 - res->end = 0; 252 - res->flags = 0; 253 - continue; 254 - } 255 - res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK; 256 - res->end = res->start + sz64; 257 - #else 258 - if (sz64 > 0x100000000ULL) { 259 - dev_err(&dev->dev, "BAR %d: can't handle 64-bit" 260 - " BAR\n", pos); 261 - res->start = 0; 262 - res->flags = 0; 263 - } else if (lhi) { 264 - /* 64-bit wide address, treat as disabled */ 265 - pci_write_config_dword(dev, reg, 266 - l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); 267 - pci_write_config_dword(dev, reg+4, 0); 268 - res->start = 0; 269 - res->end = sz; 270 - } 271 - #endif 272 - } 273 } 274 if (rom) { 275 dev->rom_base_reg = rom; 276 - res = &dev->resource[PCI_ROM_RESOURCE]; 277 - res->name = pci_name(dev); 278 - pci_read_config_dword(dev, rom, &l); 279 - pci_write_config_dword(dev, rom, ~PCI_ROM_ADDRESS_ENABLE); 280 - pci_read_config_dword(dev, rom, &sz); 281 - pci_write_config_dword(dev, rom, l); 282 - if (l == 0xffffffff) 283 - l = 0; 284 - if (sz && sz != 0xffffffff) { 285 - sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK); 286 - if (sz) { 287 - res->flags = (l & IORESOURCE_ROM_ENABLE) | 288 - IORESOURCE_MEM | IORESOURCE_PREFETCH | 289 - IORESOURCE_READONLY | IORESOURCE_CACHEABLE | 290 - IORESOURCE_SIZEALIGN; 291 - res->start = l & PCI_ROM_ADDRESS_MASK; 292 - res->end = res->start + (unsigned long) sz; 293 - } 294 - } 295 } 296 } 297
··· 163 return IORESOURCE_MEM; 164 } 165 166 + static u64 pci_size(u64 base, u64 maxbase, u64 mask) 167 { 168 u64 size = mask & maxbase; /* Find the significant bits */ 169 if (!size) ··· 202 return size; 203 } 204 205 + enum pci_bar_type { 206 + pci_bar_unknown, /* Standard PCI BAR probe */ 207 + pci_bar_io, /* An io port BAR */ 208 + pci_bar_mem32, /* A 32-bit memory BAR */ 209 + pci_bar_mem64, /* A 64-bit memory BAR */ 210 + }; 211 + 212 + static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) 213 { 214 + if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { 215 + res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; 216 + return pci_bar_io; 217 + } 218 + 219 + res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; 220 + 221 + if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64) 222 + return pci_bar_mem64; 223 + return pci_bar_mem32; 224 + } 225 + 226 + /* 227 + * If the type is not unknown, we assume that the lowest bit is 'enable'. 228 + * Returns 1 if the BAR was 64-bit and 0 if it was 32-bit. 229 + */ 230 + static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, 231 + struct resource *res, unsigned int pos) 232 + { 233 + u32 l, sz, mask; 234 + 235 + mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0; 236 + 237 + res->name = pci_name(dev); 238 + 239 + pci_read_config_dword(dev, pos, &l); 240 + pci_write_config_dword(dev, pos, mask); 241 + pci_read_config_dword(dev, pos, &sz); 242 + pci_write_config_dword(dev, pos, l); 243 + 244 + /* 245 + * All bits set in sz means the device isn't working properly. 246 + * If the BAR isn't implemented, all bits must be 0. If it's a 247 + * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit 248 + * 1 must be clear. 249 + */ 250 + if (!sz || sz == 0xffffffff) 251 + goto fail; 252 + 253 + /* 254 + * I don't know how l can have all bits set. Copied from old code. 255 + * Maybe it fixes a bug on some ancient platform. 256 + */ 257 + if (l == 0xffffffff) 258 + l = 0; 259 + 260 + if (type == pci_bar_unknown) { 261 + type = decode_bar(res, l); 262 + res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; 263 + if (type == pci_bar_io) { 264 + l &= PCI_BASE_ADDRESS_IO_MASK; 265 + mask = PCI_BASE_ADDRESS_IO_MASK & 0xffff; 266 + } else { 267 + l &= PCI_BASE_ADDRESS_MEM_MASK; 268 + mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; 269 + } 270 + } else { 271 + res->flags |= (l & IORESOURCE_ROM_ENABLE); 272 + l &= PCI_ROM_ADDRESS_MASK; 273 + mask = (u32)PCI_ROM_ADDRESS_MASK; 274 + } 275 + 276 + if (type == pci_bar_mem64) { 277 + u64 l64 = l; 278 + u64 sz64 = sz; 279 + u64 mask64 = mask | (u64)~0 << 32; 280 + 281 + pci_read_config_dword(dev, pos + 4, &l); 282 + pci_write_config_dword(dev, pos + 4, ~0); 283 + pci_read_config_dword(dev, pos + 4, &sz); 284 + pci_write_config_dword(dev, pos + 4, l); 285 + 286 + l64 |= ((u64)l << 32); 287 + sz64 |= ((u64)sz << 32); 288 + 289 + sz64 = pci_size(l64, sz64, mask64); 290 + 291 + if (!sz64) 292 + goto fail; 293 + 294 + if ((BITS_PER_LONG < 64) && (sz64 > 0x100000000ULL)) { 295 + dev_err(&dev->dev, "can't handle 64-bit BAR\n"); 296 + goto fail; 297 + } else if ((BITS_PER_LONG < 64) && l) { 298 + /* Address above 32-bit boundary; disable the BAR */ 299 + pci_write_config_dword(dev, pos, 0); 300 + pci_write_config_dword(dev, pos + 4, 0); 301 + res->start = 0; 302 + res->end = sz64; 303 + } else { 304 + res->start = l64; 305 + res->end = l64 + sz64; 306 + } 307 + } else { 308 + sz = pci_size(l, sz, mask); 309 + 310 + if (!sz) 311 + goto fail; 312 + 313 + res->start = l; 314 + res->end = l + sz; 315 + } 316 + 317 + out: 318 + return (type == pci_bar_mem64) ? 1 : 0; 319 + fail: 320 + res->flags = 0; 321 + goto out; 322 } 323 324 static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) 325 { 326 + unsigned int pos, reg; 327 328 + for (pos = 0; pos < howmany; pos++) { 329 + struct resource *res = &dev->resource[pos]; 330 reg = PCI_BASE_ADDRESS_0 + (pos << 2); 331 + pos += __pci_read_base(dev, pci_bar_unknown, res, reg); 332 } 333 + 334 if (rom) { 335 + struct resource *res = &dev->resource[PCI_ROM_RESOURCE]; 336 dev->rom_base_reg = rom; 337 + res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | 338 + IORESOURCE_READONLY | IORESOURCE_CACHEABLE | 339 + IORESOURCE_SIZEALIGN; 340 + __pci_read_base(dev, pci_bar_mem32, res, rom); 341 } 342 } 343