Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ia64/PCI/ACPI: Use common interface to support PCI host bridge

Use common interface to simplify PCI host bridge implementation.

Tested-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Jiang Liu and committed by
Rafael J. Wysocki
02715e86 4d6b4e69

+55 -194
+55 -194
arch/ia64/pci/pci.c
··· 116 116 }; 117 117 118 118 struct pci_root_info { 119 + struct acpi_pci_root_info common; 119 120 struct pci_controller controller; 120 - struct acpi_device *bridge; 121 - struct list_head resources; 122 121 struct list_head io_resources; 123 - char name[16]; 124 122 }; 125 123 126 - static unsigned int 127 - new_space (u64 phys_base, int sparse) 124 + static unsigned int new_space(u64 phys_base, int sparse) 128 125 { 129 126 u64 mmio_base; 130 127 int i; ··· 157 160 unsigned long base, min, max, base_port; 158 161 unsigned int sparse = 0, space_nr, len; 159 162 160 - len = strlen(info->name) + 32; 163 + len = strlen(info->common.name) + 32; 161 164 iospace = resource_list_create_entry(NULL, len); 162 165 if (!iospace) { 163 166 dev_err(dev, "PCI: No memory for %s I/O port space\n", 164 - info->name); 167 + info->common.name); 165 168 return -ENOMEM; 166 169 } 167 170 ··· 176 179 max = res->end - entry->offset; 177 180 base = __pa(io_space[space_nr].mmio_base); 178 181 base_port = IO_SPACE_BASE(space_nr); 179 - snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name, 182 + snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->common.name, 180 183 base_port + min, base_port + max); 181 184 182 185 /* ··· 231 234 res->start == 0xCF8 && res->end == 0xCFF; 232 235 } 233 236 234 - static int 235 - probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, 236 - int busnum, int domain) 237 + static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci) 237 238 { 238 - int ret; 239 - struct list_head *list = &info->resources; 240 - struct resource_entry *entry, *tmp; 241 - 242 - ret = acpi_dev_get_resources(device, list, 243 - acpi_dev_filter_resource_type_cb, 244 - (void *)(IORESOURCE_IO | IORESOURCE_MEM)); 245 - if (ret < 0) 246 - dev_warn(&device->dev, 247 - "failed to parse _CRS method, error code %d\n", ret); 248 - else if (ret == 0) 249 - dev_dbg(&device->dev, 250 - "no IO and memory resources present in _CRS\n"); 251 - else 252 - resource_list_for_each_entry_safe(entry, tmp, list) { 253 - if ((entry->res->flags & IORESOURCE_DISABLED) || 254 - resource_is_pcicfg_ioport(entry->res)) 255 - resource_list_destroy_entry(entry); 256 - else 257 - entry->res->name = info->name; 258 - } 259 - 260 - return ret; 261 - } 262 - 263 - static void validate_resources(struct device *dev, struct list_head *resources, 264 - unsigned long type) 265 - { 266 - LIST_HEAD(list); 267 - struct resource *res1, *res2, *root = NULL; 268 - struct resource_entry *tmp, *entry, *entry2; 269 - 270 - BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0); 271 - root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource; 272 - 273 - list_splice_init(resources, &list); 274 - resource_list_for_each_entry_safe(entry, tmp, &list) { 275 - bool free = false; 276 - resource_size_t end; 277 - 278 - res1 = entry->res; 279 - if (!(res1->flags & type)) 280 - goto next; 281 - 282 - /* Exclude non-addressable range or non-addressable portion */ 283 - end = min(res1->end, root->end); 284 - if (end <= res1->start) { 285 - dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n", 286 - res1); 287 - free = true; 288 - goto next; 289 - } else if (res1->end != end) { 290 - dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n", 291 - res1, (unsigned long long)end + 1, 292 - (unsigned long long)res1->end); 293 - res1->end = end; 294 - } 295 - 296 - resource_list_for_each_entry(entry2, resources) { 297 - res2 = entry2->res; 298 - if (!(res2->flags & type)) 299 - continue; 300 - 301 - /* 302 - * I don't like throwing away windows because then 303 - * our resources no longer match the ACPI _CRS, but 304 - * the kernel resource tree doesn't allow overlaps. 305 - */ 306 - if (resource_overlaps(res1, res2)) { 307 - res2->start = min(res1->start, res2->start); 308 - res2->end = max(res1->end, res2->end); 309 - dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n", 310 - res2, res1); 311 - free = true; 312 - goto next; 313 - } 314 - } 315 - 316 - next: 317 - resource_list_del(entry); 318 - if (free) 319 - resource_list_free_entry(entry); 320 - else 321 - resource_list_add_tail(entry, resources); 322 - } 323 - } 324 - 325 - static void add_resources(struct pci_root_info *info, struct device *dev) 326 - { 327 - struct resource_entry *entry, *tmp; 328 - struct resource *res, *conflict, *root = NULL; 329 - struct list_head *list = &info->resources; 330 - 331 - validate_resources(dev, list, IORESOURCE_MEM); 332 - validate_resources(dev, list, IORESOURCE_IO); 333 - 334 - resource_list_for_each_entry_safe(entry, tmp, list) { 335 - res = entry->res; 336 - if (res->flags & IORESOURCE_MEM) { 337 - root = &iomem_resource; 338 - /* 339 - * HP's firmware has a hack to work around a Windows 340 - * bug. Ignore these tiny memory ranges. 341 - */ 342 - if (resource_size(res) <= 16) { 343 - resource_list_destroy_entry(entry); 344 - continue; 345 - } 346 - } else if (res->flags & IORESOURCE_IO) { 347 - root = &ioport_resource; 348 - if (add_io_space(&info->bridge->dev, info, entry)) { 349 - resource_list_destroy_entry(entry); 350 - continue; 351 - } 352 - } else { 353 - BUG_ON(res); 354 - } 355 - 356 - conflict = insert_resource_conflict(root, res); 357 - if (conflict) { 358 - dev_info(dev, 359 - "ignoring host bridge window %pR (conflicts with %s %pR)\n", 360 - res, conflict->name, conflict); 361 - resource_list_destroy_entry(entry); 362 - } 363 - } 364 - } 365 - 366 - static void __release_pci_root_info(struct pci_root_info *info) 367 - { 239 + struct device *dev = &ci->bridge->dev; 240 + struct pci_root_info *info; 368 241 struct resource *res; 369 - struct resource_entry *entry, *tentry; 242 + struct resource_entry *entry, *tmp; 243 + int status; 370 244 371 - resource_list_for_each_entry_safe(entry, tentry, &info->io_resources) { 245 + status = acpi_pci_probe_root_resources(ci); 246 + if (status > 0) { 247 + info = container_of(ci, struct pci_root_info, common); 248 + resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { 249 + res = entry->res; 250 + if (res->flags & IORESOURCE_MEM) { 251 + /* 252 + * HP's firmware has a hack to work around a 253 + * Windows bug. Ignore these tiny memory ranges. 254 + */ 255 + if (resource_size(res) <= 16) { 256 + resource_list_del(entry); 257 + insert_resource(&iomem_resource, 258 + entry->res); 259 + resource_list_add_tail(entry, 260 + &info->io_resources); 261 + } 262 + } else if (res->flags & IORESOURCE_IO) { 263 + if (resource_is_pcicfg_ioport(entry->res)) 264 + resource_list_destroy_entry(entry); 265 + else if (add_io_space(dev, info, entry)) 266 + resource_list_destroy_entry(entry); 267 + } 268 + } 269 + } 270 + 271 + return status; 272 + } 273 + 274 + static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci) 275 + { 276 + struct pci_root_info *info; 277 + struct resource_entry *entry, *tmp; 278 + 279 + info = container_of(ci, struct pci_root_info, common); 280 + resource_list_for_each_entry_safe(entry, tmp, &info->io_resources) { 372 281 release_resource(entry->res); 373 282 resource_list_destroy_entry(entry); 374 283 } 375 - 376 - resource_list_for_each_entry_safe(entry, tentry, &info->resources) { 377 - res = entry->res; 378 - if (res->parent && 379 - (res->flags & (IORESOURCE_MEM | IORESOURCE_IO))) 380 - release_resource(res); 381 - resource_list_destroy_entry(entry); 382 - } 383 - 384 284 kfree(info); 385 285 } 386 286 387 - static void release_pci_root_info(struct pci_host_bridge *bridge) 388 - { 389 - struct pci_root_info *info = bridge->release_data; 390 - 391 - __release_pci_root_info(info); 392 - } 287 + static struct acpi_pci_root_ops pci_acpi_root_ops = { 288 + .pci_ops = &pci_root_ops, 289 + .release_info = pci_acpi_root_release_info, 290 + .prepare_resources = pci_acpi_root_prepare_resources, 291 + }; 393 292 394 293 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) 395 294 { 396 295 struct acpi_device *device = root->device; 397 - int domain = root->segment; 398 - int bus = root->secondary.start; 399 296 struct pci_root_info *info; 400 - struct pci_bus *pbus; 401 - int ret; 402 297 403 298 info = kzalloc(sizeof(*info), GFP_KERNEL); 404 299 if (!info) { 405 300 dev_err(&device->dev, 406 301 "pci_bus %04x:%02x: ignored (out of memory)\n", 407 - domain, bus); 302 + root->segment, (int)root->secondary.start); 408 303 return NULL; 409 304 } 410 305 411 - info->controller.segment = domain; 306 + info->controller.segment = root->segment; 412 307 info->controller.companion = device; 413 308 info->controller.node = acpi_get_node(device->handle); 414 - info->bridge = device; 415 - INIT_LIST_HEAD(&info->resources); 416 309 INIT_LIST_HEAD(&info->io_resources); 417 - snprintf(info->name, sizeof(info->name), 418 - "PCI Bus %04x:%02x", domain, bus); 419 - 420 - ret = probe_pci_root_info(info, device, bus, domain); 421 - if (ret <= 0) { 422 - kfree(info); 423 - return NULL; 424 - } 425 - add_resources(info, &info->bridge->dev); 426 - pci_add_resource(&info->resources, &root->secondary); 427 - 428 - /* 429 - * See arch/x86/pci/acpi.c. 430 - * The desired pci bus might already be scanned in a quirk. We 431 - * should handle the case here, but it appears that IA64 hasn't 432 - * such quirk. So we just ignore the case now. 433 - */ 434 - pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, 435 - &info->controller, &info->resources); 436 - if (!pbus) { 437 - __release_pci_root_info(info); 438 - return NULL; 439 - } 440 - 441 - pci_set_host_bridge_release(to_pci_host_bridge(pbus->bridge), 442 - release_pci_root_info, info); 443 - pci_scan_child_bus(pbus); 444 - return pbus; 310 + return acpi_pci_root_create(root, &pci_acpi_root_ops, 311 + &info->common, &info->controller); 445 312 } 446 313 447 314 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)