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

Merge tag 'please-pull-root_bus_hotplug' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux

Pull ia64 IOH hotplug fixes from Tony Luck:
"Series to fix IOH hotplug in ia64"

* tag 'please-pull-root_bus_hotplug' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux:
PCI: Replace printks with appropriate pr_*()
PCI/IA64: introduce probe_pci_root_info() to manage _CRS resource
PCI/IA64: Add host bridge resource release for _CRS path
PCI/IA64: fix memleak for create pci root bus fail
PCI/IA64: Allocate pci_root_info instead of using stack
PCI/IA64: embed pci hostbridge resources into pci_root_info
PCI/IA64: SN: use normal resource instead of pci_window
PCI/IA64: SN: remove sn_pci_window_fixup()

+195 -163
+4 -6
arch/ia64/include/asm/pci.h
··· 89 89 #define pci_legacy_read platform_pci_legacy_read 90 90 #define pci_legacy_write platform_pci_legacy_write 91 91 92 - struct pci_window { 93 - struct resource resource; 94 - u64 offset; 92 + struct iospace_resource { 93 + struct list_head list; 94 + struct resource res; 95 95 }; 96 96 97 97 struct pci_controller { ··· 100 100 int segment; 101 101 int node; /* nearest node with memory or -1 for global allocation */ 102 102 103 - unsigned int windows; 104 - struct pci_window *window; 105 - 106 103 void *platform_data; 107 104 }; 105 + 108 106 109 107 #define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata) 110 108 #define pci_domain_nr(busdev) (PCI_CONTROLLER(busdev)->segment)
+165 -74
arch/ia64/pci/pci.c
··· 134 134 struct acpi_device *bridge; 135 135 struct pci_controller *controller; 136 136 struct list_head resources; 137 + struct resource *res; 138 + resource_size_t *res_offset; 139 + unsigned int res_num; 140 + struct list_head io_resources; 137 141 char *name; 138 142 }; 139 143 ··· 157 153 return i; 158 154 159 155 if (num_io_spaces == MAX_IO_SPACES) { 160 - printk(KERN_ERR "PCI: Too many IO port spaces " 156 + pr_err("PCI: Too many IO port spaces " 161 157 "(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES); 162 158 return ~0; 163 159 } ··· 172 168 static u64 add_io_space(struct pci_root_info *info, 173 169 struct acpi_resource_address64 *addr) 174 170 { 171 + struct iospace_resource *iospace; 175 172 struct resource *resource; 176 173 char *name; 177 174 unsigned long base, min, max, base_port; 178 175 unsigned int sparse = 0, space_nr, len; 179 176 180 - resource = kzalloc(sizeof(*resource), GFP_KERNEL); 181 - if (!resource) { 182 - printk(KERN_ERR "PCI: No memory for %s I/O port space\n", 183 - info->name); 177 + len = strlen(info->name) + 32; 178 + iospace = kzalloc(sizeof(*iospace) + len, GFP_KERNEL); 179 + if (!iospace) { 180 + dev_err(&info->bridge->dev, 181 + "PCI: No memory for %s I/O port space\n", 182 + info->name); 184 183 goto out; 185 184 } 186 185 187 - len = strlen(info->name) + 32; 188 - name = kzalloc(len, GFP_KERNEL); 189 - if (!name) { 190 - printk(KERN_ERR "PCI: No memory for %s I/O port space name\n", 191 - info->name); 192 - goto free_resource; 193 - } 186 + name = (char *)(iospace + 1); 194 187 195 188 min = addr->minimum; 196 189 max = min + addr->address_length - 1; ··· 196 195 197 196 space_nr = new_space(addr->translation_offset, sparse); 198 197 if (space_nr == ~0) 199 - goto free_name; 198 + goto free_resource; 200 199 201 200 base = __pa(io_space[space_nr].mmio_base); 202 201 base_port = IO_SPACE_BASE(space_nr); ··· 211 210 if (space_nr == 0) 212 211 sparse = 1; 213 212 213 + resource = &iospace->res; 214 214 resource->name = name; 215 215 resource->flags = IORESOURCE_MEM; 216 216 resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min); 217 217 resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max); 218 - insert_resource(&iomem_resource, resource); 218 + if (insert_resource(&iomem_resource, resource)) { 219 + dev_err(&info->bridge->dev, 220 + "can't allocate host bridge io space resource %pR\n", 221 + resource); 222 + goto free_resource; 223 + } 219 224 225 + list_add_tail(&iospace->list, &info->io_resources); 220 226 return base_port; 221 227 222 - free_name: 223 - kfree(name); 224 228 free_resource: 225 - kfree(resource); 229 + kfree(iospace); 226 230 out: 227 231 return ~0; 228 232 } ··· 271 265 static acpi_status add_window(struct acpi_resource *res, void *data) 272 266 { 273 267 struct pci_root_info *info = data; 274 - struct pci_window *window; 268 + struct resource *resource; 275 269 struct acpi_resource_address64 addr; 276 270 acpi_status status; 277 271 unsigned long flags, offset = 0; ··· 295 289 } else 296 290 return AE_OK; 297 291 298 - window = &info->controller->window[info->controller->windows++]; 299 - window->resource.name = info->name; 300 - window->resource.flags = flags; 301 - window->resource.start = addr.minimum + offset; 302 - window->resource.end = window->resource.start + addr.address_length - 1; 303 - window->offset = offset; 292 + resource = &info->res[info->res_num]; 293 + resource->name = info->name; 294 + resource->flags = flags; 295 + resource->start = addr.minimum + offset; 296 + resource->end = resource->start + addr.address_length - 1; 297 + info->res_offset[info->res_num] = offset; 304 298 305 - if (insert_resource(root, &window->resource)) { 299 + if (insert_resource(root, resource)) { 306 300 dev_err(&info->bridge->dev, 307 301 "can't allocate host bridge window %pR\n", 308 - &window->resource); 302 + resource); 309 303 } else { 310 304 if (offset) 311 305 dev_info(&info->bridge->dev, "host bridge window %pR " 312 306 "(PCI address [%#llx-%#llx])\n", 313 - &window->resource, 314 - window->resource.start - offset, 315 - window->resource.end - offset); 307 + resource, 308 + resource->start - offset, 309 + resource->end - offset); 316 310 else 317 311 dev_info(&info->bridge->dev, 318 - "host bridge window %pR\n", 319 - &window->resource); 312 + "host bridge window %pR\n", resource); 320 313 } 321 - 322 314 /* HP's firmware has a hack to work around a Windows bug. 323 315 * Ignore these tiny memory ranges */ 324 - if (!((window->resource.flags & IORESOURCE_MEM) && 325 - (window->resource.end - window->resource.start < 16))) 326 - pci_add_resource_offset(&info->resources, &window->resource, 327 - window->offset); 316 + if (!((resource->flags & IORESOURCE_MEM) && 317 + (resource->end - resource->start < 16))) 318 + pci_add_resource_offset(&info->resources, resource, 319 + info->res_offset[info->res_num]); 328 320 321 + info->res_num++; 329 322 return AE_OK; 323 + } 324 + 325 + static void free_pci_root_info_res(struct pci_root_info *info) 326 + { 327 + struct iospace_resource *iospace, *tmp; 328 + 329 + list_for_each_entry_safe(iospace, tmp, &info->io_resources, list) 330 + kfree(iospace); 331 + 332 + kfree(info->name); 333 + kfree(info->res); 334 + info->res = NULL; 335 + kfree(info->res_offset); 336 + info->res_offset = NULL; 337 + info->res_num = 0; 338 + kfree(info->controller); 339 + info->controller = NULL; 340 + } 341 + 342 + static void __release_pci_root_info(struct pci_root_info *info) 343 + { 344 + int i; 345 + struct resource *res; 346 + struct iospace_resource *iospace; 347 + 348 + list_for_each_entry(iospace, &info->io_resources, list) 349 + release_resource(&iospace->res); 350 + 351 + for (i = 0; i < info->res_num; i++) { 352 + res = &info->res[i]; 353 + 354 + if (!res->parent) 355 + continue; 356 + 357 + if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO))) 358 + continue; 359 + 360 + release_resource(res); 361 + } 362 + 363 + free_pci_root_info_res(info); 364 + kfree(info); 365 + } 366 + 367 + static void release_pci_root_info(struct pci_host_bridge *bridge) 368 + { 369 + struct pci_root_info *info = bridge->release_data; 370 + 371 + __release_pci_root_info(info); 372 + } 373 + 374 + static int 375 + probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, 376 + int busnum, int domain) 377 + { 378 + char *name; 379 + 380 + name = kmalloc(16, GFP_KERNEL); 381 + if (!name) 382 + return -ENOMEM; 383 + 384 + sprintf(name, "PCI Bus %04x:%02x", domain, busnum); 385 + info->bridge = device; 386 + info->name = name; 387 + 388 + acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, 389 + &info->res_num); 390 + if (info->res_num) { 391 + info->res = 392 + kzalloc_node(sizeof(*info->res) * info->res_num, 393 + GFP_KERNEL, info->controller->node); 394 + if (!info->res) { 395 + kfree(name); 396 + return -ENOMEM; 397 + } 398 + 399 + info->res_offset = 400 + kzalloc_node(sizeof(*info->res_offset) * info->res_num, 401 + GFP_KERNEL, info->controller->node); 402 + if (!info->res_offset) { 403 + kfree(name); 404 + kfree(info->res); 405 + info->res = NULL; 406 + return -ENOMEM; 407 + } 408 + 409 + info->res_num = 0; 410 + acpi_walk_resources(device->handle, METHOD_NAME__CRS, 411 + add_window, info); 412 + } else 413 + kfree(name); 414 + 415 + return 0; 330 416 } 331 417 332 418 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) ··· 427 329 int domain = root->segment; 428 330 int bus = root->secondary.start; 429 331 struct pci_controller *controller; 430 - unsigned int windows = 0; 431 - struct pci_root_info info; 332 + struct pci_root_info *info = NULL; 333 + int busnum = root->secondary.start; 432 334 struct pci_bus *pbus; 433 - char *name; 434 - int pxm; 335 + int pxm, ret; 435 336 436 337 controller = alloc_pci_controller(domain); 437 338 if (!controller) 438 - goto out1; 339 + return NULL; 439 340 440 341 controller->acpi_handle = device->handle; 441 342 ··· 444 347 controller->node = pxm_to_node(pxm); 445 348 #endif 446 349 447 - INIT_LIST_HEAD(&info.resources); 448 - /* insert busn resource at first */ 449 - pci_add_resource(&info.resources, &root->secondary); 450 - acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, 451 - &windows); 452 - if (windows) { 453 - controller->window = 454 - kzalloc_node(sizeof(*controller->window) * windows, 455 - GFP_KERNEL, controller->node); 456 - if (!controller->window) 457 - goto out2; 458 - 459 - name = kmalloc(16, GFP_KERNEL); 460 - if (!name) 461 - goto out3; 462 - 463 - sprintf(name, "PCI Bus %04x:%02x", domain, bus); 464 - info.bridge = device; 465 - info.controller = controller; 466 - info.name = name; 467 - acpi_walk_resources(device->handle, METHOD_NAME__CRS, 468 - add_window, &info); 350 + info = kzalloc(sizeof(*info), GFP_KERNEL); 351 + if (!info) { 352 + dev_err(&device->dev, 353 + "pci_bus %04x:%02x: ignored (out of memory)\n", 354 + domain, busnum); 355 + kfree(controller); 356 + return NULL; 469 357 } 358 + 359 + info->controller = controller; 360 + INIT_LIST_HEAD(&info->io_resources); 361 + INIT_LIST_HEAD(&info->resources); 362 + 363 + ret = probe_pci_root_info(info, device, busnum, domain); 364 + if (ret) { 365 + kfree(info->controller); 366 + kfree(info); 367 + return NULL; 368 + } 369 + /* insert busn resource at first */ 370 + pci_add_resource(&info->resources, &root->secondary); 470 371 /* 471 372 * See arch/x86/pci/acpi.c. 472 373 * The desired pci bus might already be scanned in a quirk. We ··· 472 377 * such quirk. So we just ignore the case now. 473 378 */ 474 379 pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller, 475 - &info.resources); 380 + &info->resources); 476 381 if (!pbus) { 477 - pci_free_resource_list(&info.resources); 382 + pci_free_resource_list(&info->resources); 383 + __release_pci_root_info(info); 478 384 return NULL; 479 385 } 480 386 387 + pci_set_host_bridge_release(to_pci_host_bridge(pbus->bridge), 388 + release_pci_root_info, info); 481 389 pci_scan_child_bus(pbus); 482 390 return pbus; 483 - 484 - out3: 485 - kfree(controller->window); 486 - out2: 487 - kfree(controller); 488 - out1: 489 - return NULL; 490 391 } 491 392 492 393 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) ··· 782 691 783 692 status = ia64_pal_cache_summary(&levels, &unique_caches); 784 693 if (status != 0) { 785 - printk(KERN_ERR "%s: ia64_pal_cache_summary() failed " 694 + pr_err("%s: ia64_pal_cache_summary() failed " 786 695 "(status=%ld)\n", __func__, status); 787 696 return; 788 697 } ··· 790 699 status = ia64_pal_cache_config_info(levels - 1, 791 700 /* cache_type (data_or_unified)= */ 2, &cci); 792 701 if (status != 0) { 793 - printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed " 702 + pr_err("%s: ia64_pal_cache_config_info() failed " 794 703 "(status=%ld)\n", __func__, status); 795 704 return; 796 705 }
+26 -83
arch/ia64/sn/kernel/io_init.c
··· 118 118 } 119 119 120 120 /* 121 - * sn_pci_legacy_window_fixup - Create PCI controller windows for 121 + * sn_pci_legacy_window_fixup - Setup PCI resources for 122 122 * legacy IO and MEM space. This needs to 123 123 * be done here, as the PROM does not have 124 124 * ACPI support defining the root buses 125 125 * and their resources (_CRS), 126 126 */ 127 127 static void 128 - sn_legacy_pci_window_fixup(struct pci_controller *controller, 129 - u64 legacy_io, u64 legacy_mem) 128 + sn_legacy_pci_window_fixup(struct resource *res, 129 + u64 legacy_io, u64 legacy_mem) 130 130 { 131 - controller->window = kcalloc(2, sizeof(struct pci_window), 132 - GFP_KERNEL); 133 - BUG_ON(controller->window == NULL); 134 - controller->window[0].offset = legacy_io; 135 - controller->window[0].resource.name = "legacy_io"; 136 - controller->window[0].resource.flags = IORESOURCE_IO; 137 - controller->window[0].resource.start = legacy_io; 138 - controller->window[0].resource.end = 139 - controller->window[0].resource.start + 0xffff; 140 - controller->window[0].resource.parent = &ioport_resource; 141 - controller->window[1].offset = legacy_mem; 142 - controller->window[1].resource.name = "legacy_mem"; 143 - controller->window[1].resource.flags = IORESOURCE_MEM; 144 - controller->window[1].resource.start = legacy_mem; 145 - controller->window[1].resource.end = 146 - controller->window[1].resource.start + (1024 * 1024) - 1; 147 - controller->window[1].resource.parent = &iomem_resource; 148 - controller->windows = 2; 149 - } 150 - 151 - /* 152 - * sn_pci_window_fixup() - Create a pci_window for each device resource. 153 - * It will setup pci_windows for use by 154 - * pcibios_bus_to_resource(), pcibios_resource_to_bus(), 155 - * etc. 156 - */ 157 - static void 158 - sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, 159 - s64 * pci_addrs) 160 - { 161 - struct pci_controller *controller = PCI_CONTROLLER(dev->bus); 162 - unsigned int i; 163 - unsigned int idx; 164 - unsigned int new_count; 165 - struct pci_window *new_window; 166 - 167 - if (count == 0) 168 - return; 169 - idx = controller->windows; 170 - new_count = controller->windows + count; 171 - new_window = kcalloc(new_count, sizeof(struct pci_window), GFP_KERNEL); 172 - BUG_ON(new_window == NULL); 173 - if (controller->window) { 174 - memcpy(new_window, controller->window, 175 - sizeof(struct pci_window) * controller->windows); 176 - kfree(controller->window); 177 - } 178 - 179 - /* Setup a pci_window for each device resource. */ 180 - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { 181 - if (pci_addrs[i] == -1) 182 - continue; 183 - 184 - new_window[idx].offset = dev->resource[i].start - pci_addrs[i]; 185 - new_window[idx].resource = dev->resource[i]; 186 - idx++; 187 - } 188 - 189 - controller->windows = new_count; 190 - controller->window = new_window; 131 + res[0].name = "legacy_io"; 132 + res[0].flags = IORESOURCE_IO; 133 + res[0].start = legacy_io; 134 + res[0].end = res[0].start + 0xffff; 135 + res[0].parent = &ioport_resource; 136 + res[1].name = "legacy_mem"; 137 + res[1].flags = IORESOURCE_MEM; 138 + res[1].start = legacy_mem; 139 + res[1].end = res[1].start + (1024 * 1024) - 1; 140 + res[1].parent = &iomem_resource; 191 141 } 192 142 193 143 /* ··· 149 199 void 150 200 sn_io_slot_fixup(struct pci_dev *dev) 151 201 { 152 - unsigned int count = 0; 153 202 int idx; 154 - s64 pci_addrs[PCI_ROM_RESOURCE + 1]; 155 203 unsigned long addr, end, size, start; 156 204 struct pcidev_info *pcidev_info; 157 205 struct sn_irq_info *sn_irq_info; ··· 177 229 for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { 178 230 179 231 if (!pcidev_info->pdi_pio_mapped_addr[idx]) { 180 - pci_addrs[idx] = -1; 181 232 continue; 182 233 } 183 234 ··· 184 237 end = dev->resource[idx].end; 185 238 size = end - start; 186 239 if (size == 0) { 187 - pci_addrs[idx] = -1; 188 240 continue; 189 241 } 190 - pci_addrs[idx] = start; 191 - count++; 192 242 addr = pcidev_info->pdi_pio_mapped_addr[idx]; 193 243 addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; 194 244 dev->resource[idx].start = addr; ··· 220 276 IORESOURCE_ROM_BIOS_COPY; 221 277 } 222 278 } 223 - /* Create a pci_window in the pci_controller struct for 224 - * each device resource. 225 - */ 226 - if (count > 0) 227 - sn_pci_window_fixup(dev, count, pci_addrs); 228 279 229 280 sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); 230 281 } ··· 236 297 s64 status = 0; 237 298 struct pci_controller *controller; 238 299 struct pcibus_bussoft *prom_bussoft_ptr; 300 + struct resource *res; 239 301 LIST_HEAD(resources); 240 - int i; 241 302 242 303 status = sal_get_pcibus_info((u64) segment, (u64) busnum, 243 304 (u64) ia64_tpa(&prom_bussoft_ptr)); ··· 249 310 BUG_ON(!controller); 250 311 controller->segment = segment; 251 312 313 + res = kcalloc(2, sizeof(struct resource), GFP_KERNEL); 314 + BUG_ON(!res); 315 + 252 316 /* 253 317 * Temporarily save the prom_bussoft_ptr for use by sn_bus_fixup(). 254 318 * (platform_data will be overwritten later in sn_common_bus_fixup()) 255 319 */ 256 320 controller->platform_data = prom_bussoft_ptr; 257 321 258 - sn_legacy_pci_window_fixup(controller, 259 - prom_bussoft_ptr->bs_legacy_io, 260 - prom_bussoft_ptr->bs_legacy_mem); 261 - for (i = 0; i < controller->windows; i++) 262 - pci_add_resource_offset(&resources, 263 - &controller->window[i].resource, 264 - controller->window[i].offset); 322 + sn_legacy_pci_window_fixup(res, 323 + prom_bussoft_ptr->bs_legacy_io, 324 + prom_bussoft_ptr->bs_legacy_mem); 325 + pci_add_resource_offset(&resources, &res[0], 326 + prom_bussoft_ptr->bs_legacy_io); 327 + pci_add_resource_offset(&resources, &res[1], 328 + prom_bussoft_ptr->bs_legacy_mem); 329 + 265 330 bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller, 266 331 &resources); 267 332 if (bus == NULL) ··· 276 333 return; 277 334 278 335 error_return: 279 - 336 + kfree(res); 280 337 kfree(controller); 281 338 return; 282 339 }