[PATCH] acpi hotplug: convert acpiphp to use generic resource code

This patch converts acpiphp to use the generic PCI resource assignment code.
It's quite large, but most of it is deleting the acpiphp_pci and acpiphp_res
files. It's tested on an hp Integrity rx8620 (which won't work without this
patch). Testers with other hardware welcomed.

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Rajesh Shah and committed by
Greg Kroah-Hartman
42f49a6a 4ce448e5

+136 -1532
+1 -3
drivers/pci/hotplug/Makefile
··· 36 36 ibmphp_hpc.o 37 37 38 38 acpiphp-objs := acpiphp_core.o \ 39 - acpiphp_glue.o \ 40 - acpiphp_pci.o \ 41 - acpiphp_res.o 39 + acpiphp_glue.o 42 40 43 41 rpaphp-objs := rpaphp_core.o \ 44 42 rpaphp_pci.o \
+2 -45
drivers/pci/hotplug/acpiphp.h
··· 7 7 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) 8 8 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) 9 9 * Copyright (C) 2002,2003 NEC Corporation 10 + * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com) 11 + * Copyright (C) 2003-2005 Hewlett Packard 10 12 * 11 13 * All rights reserved. 12 14 * ··· 54 52 55 53 struct acpiphp_bridge; 56 54 struct acpiphp_slot; 57 - struct pci_resource; 58 55 59 56 /* 60 57 * struct slot - slot information for each *physical* slot ··· 64 63 struct list_head slot_list; 65 64 66 65 struct acpiphp_slot *acpi_slot; 67 - }; 68 - 69 - /* 70 - * struct pci_resource - describes pci resource (mem, pfmem, io, bus) 71 - */ 72 - struct pci_resource { 73 - struct pci_resource * next; 74 - u64 base; 75 - u32 length; 76 66 }; 77 67 78 68 /** ··· 93 101 int type; 94 102 int nr_slots; 95 103 96 - u8 seg; 97 - u8 bus; 98 - u8 sub; 99 - 100 104 u32 flags; 101 105 102 106 /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */ ··· 105 117 struct hpp_param hpp; 106 118 107 119 spinlock_t res_lock; 108 - 109 - /* available resources on this bus */ 110 - struct pci_resource *mem_head; 111 - struct pci_resource *p_mem_head; 112 - struct pci_resource *io_head; 113 - struct pci_resource *bus_head; 114 120 }; 115 121 116 122 ··· 145 163 146 164 u8 function; /* pci function# */ 147 165 u32 flags; /* see below */ 148 - 149 - /* resources used for this function */ 150 - struct pci_resource *mem_head; 151 - struct pci_resource *p_mem_head; 152 - struct pci_resource *io_head; 153 - struct pci_resource *bus_head; 154 166 }; 155 167 156 168 /** ··· 218 242 extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); 219 243 extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); 220 244 extern u32 acpiphp_get_address (struct acpiphp_slot *slot); 221 - 222 - /* acpiphp_pci.c */ 223 - extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn); 224 - extern int acpiphp_configure_slot (struct acpiphp_slot *slot); 225 - extern int acpiphp_configure_function (struct acpiphp_func *func); 226 - extern void acpiphp_unconfigure_function (struct acpiphp_func *func); 227 - extern int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge); 228 - extern int acpiphp_init_func_resource (struct acpiphp_func *func); 229 - 230 - /* acpiphp_res.c */ 231 - extern struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size); 232 - extern struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size); 233 - extern struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size); 234 - extern int acpiphp_resource_sort_and_combine (struct pci_resource **head); 235 - extern struct pci_resource *acpiphp_make_resource (u64 base, u32 length); 236 - extern void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to); 237 - extern void acpiphp_free_resource (struct pci_resource **res); 238 - extern void acpiphp_dump_resource (struct acpiphp_bridge *bridge); /* debug */ 239 - extern void acpiphp_dump_func_resource (struct acpiphp_func *func); /* debug */ 240 245 241 246 /* variables */ 242 247 extern int acpiphp_debug;
+5 -4
drivers/pci/hotplug/acpiphp_core.c
··· 7 7 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) 8 8 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) 9 9 * Copyright (C) 2002,2003 NEC Corporation 10 + * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com) 11 + * Copyright (C) 2003-2005 Hewlett Packard 10 12 * 11 13 * All rights reserved. 12 14 * ··· 55 53 static int num_slots; 56 54 static struct acpiphp_attention_info *attention_info; 57 55 58 - #define DRIVER_VERSION "0.4" 59 - #define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>" 56 + #define DRIVER_VERSION "0.5" 57 + #define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>, Matthew Wilcox <willy@hp.com>" 60 58 #define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver" 61 59 62 60 MODULE_AUTHOR(DRIVER_AUTHOR); ··· 283 281 /** 284 282 * get_address - get pci address of a slot 285 283 * @hotplug_slot: slot to get status 286 - * @busdev: pointer to struct pci_busdev (seg, bus, dev) 287 - * 284 + * @value: pointer to struct pci_busdev (seg, bus, dev) 288 285 */ 289 286 static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) 290 287 {
+128 -331
drivers/pci/hotplug/acpiphp_glue.c
··· 4 4 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) 5 5 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) 6 6 * Copyright (C) 2002,2003 NEC Corporation 7 + * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com) 8 + * Copyright (C) 2003-2005 Hewlett Packard 7 9 * 8 10 * All rights reserved. 9 11 * ··· 26 24 * 27 25 * Send feedback to <t-kochi@bq.jp.nec.com> 28 26 * 27 + */ 28 + 29 + /* 30 + * Lifetime rules for pci_dev: 31 + * - The one in acpiphp_func has its refcount elevated by pci_get_slot() 32 + * when the driver is loaded or when an insertion event occurs. It loses 33 + * a refcount when its ejected or the driver unloads. 34 + * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() 35 + * when the bridge is scanned and it loses a refcount when the bridge 36 + * is removed. 29 37 */ 30 38 31 39 #include <linux/init.h> ··· 190 178 191 179 bridge->nr_slots++; 192 180 193 - dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n", 194 - slot->bridge->bus, slot->device, slot->sun); 181 + dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", 182 + slot->sun, pci_domain_nr(bridge->pci_bus), 183 + bridge->pci_bus->number, slot->device); 195 184 } 196 185 197 186 newfunc->slot = slot; 198 187 list_add_tail(&newfunc->sibling, &slot->funcs); 199 188 200 189 /* associate corresponding pci_dev */ 201 - newfunc->pci_dev = pci_find_slot(bridge->bus, 190 + newfunc->pci_dev = pci_get_slot(bridge->pci_bus, 202 191 PCI_DEVFN(device, function)); 203 192 if (newfunc->pci_dev) { 204 - if (acpiphp_init_func_resource(newfunc) < 0) { 205 - kfree(newfunc); 206 - return AE_ERROR; 207 - } 208 193 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); 209 194 } 210 195 ··· 235 226 return count; 236 227 } 237 228 238 - 239 - /* decode ACPI _CRS data and convert into our internal resource list 240 - * TBD: _TRA, etc. 241 - */ 242 - static acpi_status 243 - decode_acpi_resource(struct acpi_resource *resource, void *context) 244 - { 245 - struct acpiphp_bridge *bridge = (struct acpiphp_bridge *) context; 246 - struct acpi_resource_address64 address; 247 - struct pci_resource *res; 248 - 249 - if (resource->id != ACPI_RSTYPE_ADDRESS16 && 250 - resource->id != ACPI_RSTYPE_ADDRESS32 && 251 - resource->id != ACPI_RSTYPE_ADDRESS64) 252 - return AE_OK; 253 - 254 - acpi_resource_to_address64(resource, &address); 255 - 256 - if (address.producer_consumer == ACPI_PRODUCER && address.address_length > 0) { 257 - dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type, 258 - (unsigned long long)address.min_address_range, 259 - (unsigned long long)address.max_address_range); 260 - res = acpiphp_make_resource(address.min_address_range, 261 - address.address_length); 262 - if (!res) { 263 - err("out of memory\n"); 264 - return AE_OK; 265 - } 266 - 267 - switch (address.resource_type) { 268 - case ACPI_MEMORY_RANGE: 269 - if (address.attribute.memory.cache_attribute == ACPI_PREFETCHABLE_MEMORY) { 270 - res->next = bridge->p_mem_head; 271 - bridge->p_mem_head = res; 272 - } else { 273 - res->next = bridge->mem_head; 274 - bridge->mem_head = res; 275 - } 276 - break; 277 - case ACPI_IO_RANGE: 278 - res->next = bridge->io_head; 279 - bridge->io_head = res; 280 - break; 281 - case ACPI_BUS_NUMBER_RANGE: 282 - res->next = bridge->bus_head; 283 - bridge->bus_head = res; 284 - break; 285 - default: 286 - /* invalid type */ 287 - kfree(res); 288 - break; 289 - } 290 - } 291 - 292 - return AE_OK; 293 - } 294 229 295 230 /* decode ACPI 2.0 _HPP hot plug parameters */ 296 231 static void decode_hpp(struct acpiphp_bridge *bridge) ··· 299 346 /* decode ACPI 2.0 _HPP (hot plug parameters) */ 300 347 decode_hpp(bridge); 301 348 302 - /* subtract all resources already allocated */ 303 - acpiphp_detect_pci_resource(bridge); 304 - 305 349 /* register all slot objects under this bridge */ 306 350 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, 307 351 register_slot, bridge, NULL); ··· 314 364 } 315 365 316 366 list_add(&bridge->list, &bridge_list); 317 - 318 - dbg("Bridge resource:\n"); 319 - acpiphp_dump_resource(bridge); 320 367 } 321 368 322 369 323 370 /* allocate and initialize host bridge data structure */ 324 - static void add_host_bridge(acpi_handle *handle, int seg, int bus) 371 + static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) 325 372 { 326 - acpi_status status; 327 373 struct acpiphp_bridge *bridge; 328 374 329 375 bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); ··· 330 384 331 385 bridge->type = BRIDGE_TYPE_HOST; 332 386 bridge->handle = handle; 333 - bridge->seg = seg; 334 - bridge->bus = bus; 335 387 336 - bridge->pci_bus = pci_find_bus(seg, bus); 388 + bridge->pci_bus = pci_bus; 337 389 338 390 spin_lock_init(&bridge->res_lock); 339 - 340 - /* to be overridden when we decode _CRS */ 341 - bridge->sub = bridge->bus; 342 - 343 - /* decode resources */ 344 - 345 - status = acpi_walk_resources(handle, METHOD_NAME__CRS, 346 - decode_acpi_resource, bridge); 347 - 348 - if (ACPI_FAILURE(status)) { 349 - err("failed to decode bridge resources\n"); 350 - kfree(bridge); 351 - return; 352 - } 353 - 354 - acpiphp_resource_sort_and_combine(&bridge->io_head); 355 - acpiphp_resource_sort_and_combine(&bridge->mem_head); 356 - acpiphp_resource_sort_and_combine(&bridge->p_mem_head); 357 - acpiphp_resource_sort_and_combine(&bridge->bus_head); 358 - 359 - dbg("ACPI _CRS resource:\n"); 360 - acpiphp_dump_resource(bridge); 361 - 362 - if (bridge->bus_head) { 363 - bridge->bus = bridge->bus_head->base; 364 - bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1; 365 - } 366 391 367 392 init_bridge_misc(bridge); 368 393 } 369 394 370 395 371 396 /* allocate and initialize PCI-to-PCI bridge data structure */ 372 - static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int fn) 397 + static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) 373 398 { 374 399 struct acpiphp_bridge *bridge; 375 - u8 tmp8; 376 - u16 tmp16; 377 - u64 base64, limit64; 378 - u32 base, limit, base32u, limit32u; 379 400 380 401 bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); 381 402 if (bridge == NULL) { ··· 354 441 355 442 bridge->type = BRIDGE_TYPE_P2P; 356 443 bridge->handle = handle; 357 - bridge->seg = seg; 358 444 359 - bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn)); 360 - if (!bridge->pci_dev) { 361 - err("Can't get pci_dev\n"); 362 - kfree(bridge); 363 - return; 364 - } 365 - 366 - bridge->pci_bus = bridge->pci_dev->subordinate; 445 + bridge->pci_dev = pci_dev_get(pci_dev); 446 + bridge->pci_bus = pci_dev->subordinate; 367 447 if (!bridge->pci_bus) { 368 448 err("This is not a PCI-to-PCI bridge!\n"); 369 - kfree(bridge); 370 - return; 449 + goto err; 371 450 } 372 451 373 452 spin_lock_init(&bridge->res_lock); 374 453 375 - bridge->bus = bridge->pci_bus->number; 376 - bridge->sub = bridge->pci_bus->subordinate; 377 - 378 - /* 379 - * decode resources under this P2P bridge 380 - */ 381 - 382 - /* I/O resources */ 383 - pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8); 384 - base = tmp8; 385 - pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8); 386 - limit = tmp8; 387 - 388 - switch (base & PCI_IO_RANGE_TYPE_MASK) { 389 - case PCI_IO_RANGE_TYPE_16: 390 - base = (base << 8) & 0xf000; 391 - limit = ((limit << 8) & 0xf000) + 0xfff; 392 - bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); 393 - if (!bridge->io_head) { 394 - err("out of memory\n"); 395 - kfree(bridge); 396 - return; 397 - } 398 - dbg("16bit I/O range: %04x-%04x\n", 399 - (u32)bridge->io_head->base, 400 - (u32)(bridge->io_head->base + bridge->io_head->length - 1)); 401 - break; 402 - case PCI_IO_RANGE_TYPE_32: 403 - pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16); 404 - base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000); 405 - pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16); 406 - limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff; 407 - bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); 408 - if (!bridge->io_head) { 409 - err("out of memory\n"); 410 - kfree(bridge); 411 - return; 412 - } 413 - dbg("32bit I/O range: %08x-%08x\n", 414 - (u32)bridge->io_head->base, 415 - (u32)(bridge->io_head->base + bridge->io_head->length - 1)); 416 - break; 417 - case 0x0f: 418 - dbg("I/O space unsupported\n"); 419 - break; 420 - default: 421 - warn("Unknown I/O range type\n"); 422 - } 423 - 424 - /* Memory resources (mandatory for P2P bridge) */ 425 - pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16); 426 - base = (tmp16 & 0xfff0) << 16; 427 - pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16); 428 - limit = ((tmp16 & 0xfff0) << 16) | 0xfffff; 429 - bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1); 430 - if (!bridge->mem_head) { 431 - err("out of memory\n"); 432 - kfree(bridge); 433 - return; 434 - } 435 - dbg("32bit Memory range: %08x-%08x\n", 436 - (u32)bridge->mem_head->base, 437 - (u32)(bridge->mem_head->base + bridge->mem_head->length-1)); 438 - 439 - /* Prefetchable Memory resources (optional) */ 440 - pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16); 441 - base = tmp16; 442 - pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16); 443 - limit = tmp16; 444 - 445 - switch (base & PCI_MEMORY_RANGE_TYPE_MASK) { 446 - case PCI_PREF_RANGE_TYPE_32: 447 - base = (base & 0xfff0) << 16; 448 - limit = ((limit & 0xfff0) << 16) | 0xfffff; 449 - bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1); 450 - if (!bridge->p_mem_head) { 451 - err("out of memory\n"); 452 - kfree(bridge); 453 - return; 454 - } 455 - dbg("32bit Prefetchable memory range: %08x-%08x\n", 456 - (u32)bridge->p_mem_head->base, 457 - (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1)); 458 - break; 459 - case PCI_PREF_RANGE_TYPE_64: 460 - pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u); 461 - pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u); 462 - base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16); 463 - limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff; 464 - 465 - bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1); 466 - if (!bridge->p_mem_head) { 467 - err("out of memory\n"); 468 - kfree(bridge); 469 - return; 470 - } 471 - dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n", 472 - (u32)(bridge->p_mem_head->base >> 32), 473 - (u32)(bridge->p_mem_head->base & 0xffffffff), 474 - (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32), 475 - (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) & 0xffffffff)); 476 - break; 477 - case 0x0f: 478 - break; 479 - default: 480 - warn("Unknown prefetchale memory type\n"); 481 - } 482 - 483 454 init_bridge_misc(bridge); 455 + return; 456 + err: 457 + pci_dev_put(pci_dev); 458 + kfree(bridge); 459 + return; 484 460 } 485 461 486 462 ··· 379 577 { 380 578 acpi_status status; 381 579 acpi_handle dummy_handle; 382 - unsigned long *segbus = context; 383 580 unsigned long tmp; 384 - int seg, bus, device, function; 581 + int device, function; 385 582 struct pci_dev *dev; 386 - 387 - /* get PCI address */ 388 - seg = (*segbus >> 8) & 0xff; 389 - bus = *segbus & 0xff; 583 + struct pci_bus *pci_bus = context; 390 584 391 585 status = acpi_get_handle(handle, "_ADR", &dummy_handle); 392 586 if (ACPI_FAILURE(status)) ··· 397 599 device = (tmp >> 16) & 0xffff; 398 600 function = tmp & 0xffff; 399 601 400 - dev = pci_find_slot(bus, PCI_DEVFN(device, function)); 602 + dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function)); 401 603 402 - if (!dev) 403 - return AE_OK; 404 - 405 - if (!dev->subordinate) 406 - return AE_OK; 604 + if (!dev || !dev->subordinate) 605 + goto out; 407 606 408 607 /* check if this bridge has ejectable slots */ 409 608 if (detect_ejectable_slots(handle) > 0) { 410 609 dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); 411 - add_p2p_bridge(handle, seg, bus, device, function); 610 + add_p2p_bridge(handle, dev); 412 611 } 413 612 613 + out: 614 + pci_dev_put(dev); 414 615 return AE_OK; 415 616 } 416 617 ··· 421 624 unsigned long tmp; 422 625 int seg, bus; 423 626 acpi_handle dummy_handle; 627 + struct pci_bus *pci_bus; 424 628 425 629 /* if the bridge doesn't have _STA, we assume it is always there */ 426 630 status = acpi_get_handle(handle, "_STA", &dummy_handle); ··· 451 653 bus = 0; 452 654 } 453 655 454 - /* check if this bridge has ejectable slots */ 455 - if (detect_ejectable_slots(handle) > 0) { 456 - dbg("found PCI host-bus bridge with hot-pluggable slots\n"); 457 - add_host_bridge(handle, seg, bus); 656 + pci_bus = pci_find_bus(seg, bus); 657 + if (!pci_bus) { 658 + err("Can't find bus %04x:%02x\n", seg, bus); 458 659 return 0; 459 660 } 460 661 461 - tmp = seg << 8 | bus; 662 + /* check if this bridge has ejectable slots */ 663 + if (detect_ejectable_slots(handle) > 0) { 664 + dbg("found PCI host-bus bridge with hot-pluggable slots\n"); 665 + add_host_bridge(handle, pci_bus); 666 + return 0; 667 + } 462 668 463 669 /* search P2P bridges under this host bridge */ 464 670 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, 465 - find_p2p_bridge, &tmp, NULL); 671 + find_p2p_bridge, pci_bus, NULL); 466 672 467 673 if (ACPI_FAILURE(status)) 468 674 warn("find_p2p_bridge faied (error code = 0x%x)\n",status); ··· 474 672 return 0; 475 673 } 476 674 675 + static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) 676 + { 677 + struct list_head *head; 678 + list_for_each(head, &bridge_list) { 679 + struct acpiphp_bridge *bridge = list_entry(head, 680 + struct acpiphp_bridge, list); 681 + if (bridge->handle == handle) 682 + return bridge; 683 + } 684 + 685 + return NULL; 686 + } 477 687 478 688 static void remove_bridge(acpi_handle handle) 479 689 { 480 - /* No-op for now .. */ 690 + struct list_head *list, *tmp; 691 + struct acpiphp_bridge *bridge; 692 + struct acpiphp_slot *slot; 693 + acpi_status status; 694 + 695 + bridge = acpiphp_handle_to_bridge(handle); 696 + if (!bridge) { 697 + err("Could not find bridge for handle %p\n", handle); 698 + return; 699 + } 700 + 701 + status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, 702 + handle_hotplug_event_bridge); 703 + if (ACPI_FAILURE(status)) 704 + err("failed to remove notify handler\n"); 705 + 706 + slot = bridge->slots; 707 + while (slot) { 708 + struct acpiphp_slot *next = slot->next; 709 + list_for_each_safe (list, tmp, &slot->funcs) { 710 + struct acpiphp_func *func; 711 + func = list_entry(list, struct acpiphp_func, sibling); 712 + status = acpi_remove_notify_handler(func->handle, 713 + ACPI_SYSTEM_NOTIFY, 714 + handle_hotplug_event_func); 715 + if (ACPI_FAILURE(status)) 716 + err("failed to remove notify handler\n"); 717 + pci_dev_put(func->pci_dev); 718 + list_del(list); 719 + kfree(func); 720 + } 721 + kfree(slot); 722 + slot = next; 723 + } 724 + 725 + pci_dev_put(bridge->pci_dev); 726 + list_del(&bridge->list); 727 + kfree(bridge); 481 728 } 482 729 483 730 ··· 633 782 */ 634 783 static int enable_device(struct acpiphp_slot *slot) 635 784 { 636 - u8 bus; 637 785 struct pci_dev *dev; 638 - struct pci_bus *child; 786 + struct pci_bus *bus = slot->bridge->pci_bus; 639 787 struct list_head *l; 640 788 struct acpiphp_func *func; 641 789 int retval = 0; 642 - int num; 790 + int num, max, pass; 643 791 644 792 if (slot->flags & SLOT_ENABLED) 645 793 goto err_exit; 646 794 647 795 /* sanity check: dev should be NULL when hot-plugged in */ 648 - dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0)); 796 + dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); 649 797 if (dev) { 650 798 /* This case shouldn't happen */ 651 799 err("pci_dev structure already exists.\n"); 800 + pci_dev_put(dev); 652 801 retval = -1; 653 802 goto err_exit; 654 803 } 655 804 656 - /* allocate resources to device */ 657 - retval = acpiphp_configure_slot(slot); 658 - if (retval) 659 - goto err_exit; 660 - 661 - /* returned `dev' is the *first function* only! */ 662 - num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0)); 663 - if (num) 664 - pci_bus_add_devices(slot->bridge->pci_bus); 665 - dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0)); 666 - 667 - if (!dev) { 805 + num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); 806 + if (num == 0) { 668 807 err("No new device found\n"); 669 808 retval = -1; 670 809 goto err_exit; 671 810 } 672 811 673 - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 674 - pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus); 675 - child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus); 676 - pci_do_scan_bus(child); 812 + max = bus->secondary; 813 + for (pass = 0; pass < 2; pass++) { 814 + list_for_each_entry(dev, &bus->devices, bus_list) { 815 + if (PCI_SLOT(dev->devfn) != slot->device) 816 + continue; 817 + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 818 + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) 819 + max = pci_scan_bridge(bus, dev, max, pass); 820 + } 677 821 } 822 + 823 + pci_bus_assign_resources(bus); 824 + pci_bus_add_devices(bus); 678 825 679 826 /* associate pci_dev to our representation */ 680 827 list_for_each (l, &slot->funcs) { 681 828 func = list_entry(l, struct acpiphp_func, sibling); 682 - 683 - func->pci_dev = pci_find_slot(slot->bridge->bus, 684 - PCI_DEVFN(slot->device, 829 + func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 685 830 func->function)); 686 - if (!func->pci_dev) 687 - continue; 688 - 689 - /* configure device */ 690 - retval = acpiphp_configure_function(func); 691 - if (retval) 692 - goto err_exit; 693 831 } 694 832 695 833 slot->flags |= SLOT_ENABLED; 696 - 697 - dbg("Available resources:\n"); 698 - acpiphp_dump_resource(slot->bridge); 699 834 700 835 err_exit: 701 836 return retval; ··· 703 866 704 867 list_for_each (l, &slot->funcs) { 705 868 func = list_entry(l, struct acpiphp_func, sibling); 869 + if (!func->pci_dev) 870 + continue; 706 871 707 - if (func->pci_dev) 708 - acpiphp_unconfigure_function(func); 872 + pci_remove_bus_device(func->pci_dev); 873 + pci_dev_put(func->pci_dev); 874 + func->pci_dev = NULL; 709 875 } 710 876 711 877 slot->flags &= (~SLOT_ENABLED); ··· 956 1116 */ 957 1117 void __exit acpiphp_glue_exit(void) 958 1118 { 959 - struct list_head *l1, *l2, *n1, *n2; 960 - struct acpiphp_bridge *bridge; 961 - struct acpiphp_slot *slot, *next; 962 - struct acpiphp_func *func; 963 - acpi_status status; 964 - 965 - list_for_each_safe (l1, n1, &bridge_list) { 966 - bridge = (struct acpiphp_bridge *)l1; 967 - slot = bridge->slots; 968 - while (slot) { 969 - next = slot->next; 970 - list_for_each_safe (l2, n2, &slot->funcs) { 971 - func = list_entry(l2, struct acpiphp_func, sibling); 972 - acpiphp_free_resource(&func->io_head); 973 - acpiphp_free_resource(&func->mem_head); 974 - acpiphp_free_resource(&func->p_mem_head); 975 - acpiphp_free_resource(&func->bus_head); 976 - status = acpi_remove_notify_handler(func->handle, 977 - ACPI_SYSTEM_NOTIFY, 978 - handle_hotplug_event_func); 979 - if (ACPI_FAILURE(status)) 980 - err("failed to remove notify handler\n"); 981 - kfree(func); 982 - } 983 - kfree(slot); 984 - slot = next; 985 - } 986 - status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, 987 - handle_hotplug_event_bridge); 988 - if (ACPI_FAILURE(status)) 989 - err("failed to remove notify handler\n"); 990 - 991 - acpiphp_free_resource(&bridge->io_head); 992 - acpiphp_free_resource(&bridge->mem_head); 993 - acpiphp_free_resource(&bridge->p_mem_head); 994 - acpiphp_free_resource(&bridge->bus_head); 995 - 996 - kfree(bridge); 997 - } 998 - 999 1119 acpi_pci_unregister_driver(&acpi_pci_hp_driver); 1000 1120 } 1001 1121 ··· 973 1173 974 1174 list_for_each (node, &bridge_list) { 975 1175 bridge = (struct acpiphp_bridge *)node; 976 - dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots); 1176 + dbg("Bus %04x:%02x has %d slot%s\n", 1177 + pci_domain_nr(bridge->pci_bus), 1178 + bridge->pci_bus->number, bridge->nr_slots, 1179 + bridge->nr_slots == 1 ? "" : "s"); 977 1180 num_slots += bridge->nr_slots; 978 1181 } 979 1182 980 - dbg("Total %dslots\n", num_slots); 1183 + dbg("Total %d slots\n", num_slots); 981 1184 return num_slots; 982 1185 } 983 1186 ··· 1077 1274 if (retval) 1078 1275 goto err_exit; 1079 1276 1080 - acpiphp_resource_sort_and_combine(&slot->bridge->io_head); 1081 - acpiphp_resource_sort_and_combine(&slot->bridge->mem_head); 1082 - acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head); 1083 - acpiphp_resource_sort_and_combine(&slot->bridge->bus_head); 1084 - dbg("Available resources:\n"); 1085 - acpiphp_dump_resource(slot->bridge); 1086 - 1087 1277 err_exit: 1088 1278 up(&slot->crit_sect); 1089 1279 return retval; ··· 1131 1335 u32 acpiphp_get_address(struct acpiphp_slot *slot) 1132 1336 { 1133 1337 u32 address; 1338 + struct pci_bus *pci_bus = slot->bridge->pci_bus; 1134 1339 1135 - address = ((slot->bridge->seg) << 16) | 1136 - ((slot->bridge->bus) << 8) | 1340 + address = (pci_domain_nr(pci_bus) << 16) | 1341 + (pci_bus->number << 8) | 1137 1342 slot->device; 1138 1343 1139 1344 return address;
-449
drivers/pci/hotplug/acpiphp_pci.c
··· 1 - /* 2 - * ACPI PCI HotPlug PCI configuration space management 3 - * 4 - * Copyright (C) 1995,2001 Compaq Computer Corporation 5 - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 6 - * Copyright (C) 2001,2002 IBM Corp. 7 - * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com) 8 - * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) 9 - * Copyright (C) 2002 NEC Corporation 10 - * 11 - * All rights reserved. 12 - * 13 - * This program is free software; you can redistribute it and/or modify 14 - * it under the terms of the GNU General Public License as published by 15 - * the Free Software Foundation; either version 2 of the License, or (at 16 - * your option) any later version. 17 - * 18 - * This program is distributed in the hope that it will be useful, but 19 - * WITHOUT ANY WARRANTY; without even the implied warranty of 20 - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 21 - * NON INFRINGEMENT. See the GNU General Public License for more 22 - * details. 23 - * 24 - * You should have received a copy of the GNU General Public License 25 - * along with this program; if not, write to the Free Software 26 - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 - * 28 - * Send feedback to <t-kochi@bq.jp.nec.com> 29 - * 30 - */ 31 - 32 - #include <linux/init.h> 33 - #include <linux/module.h> 34 - 35 - #include <linux/kernel.h> 36 - #include <linux/pci.h> 37 - #include <linux/acpi.h> 38 - #include "../pci.h" 39 - #include "pci_hotplug.h" 40 - #include "acpiphp.h" 41 - 42 - #define MY_NAME "acpiphp_pci" 43 - 44 - 45 - /* allocate mem/pmem/io resource to a new function */ 46 - static int init_config_space (struct acpiphp_func *func) 47 - { 48 - u32 bar, len; 49 - u32 address[] = { 50 - PCI_BASE_ADDRESS_0, 51 - PCI_BASE_ADDRESS_1, 52 - PCI_BASE_ADDRESS_2, 53 - PCI_BASE_ADDRESS_3, 54 - PCI_BASE_ADDRESS_4, 55 - PCI_BASE_ADDRESS_5, 56 - 0 57 - }; 58 - int count; 59 - struct acpiphp_bridge *bridge; 60 - struct pci_resource *res; 61 - struct pci_bus *pbus; 62 - int bus, device, function; 63 - unsigned int devfn; 64 - u16 tmp; 65 - 66 - bridge = func->slot->bridge; 67 - pbus = bridge->pci_bus; 68 - bus = bridge->bus; 69 - device = func->slot->device; 70 - function = func->function; 71 - devfn = PCI_DEVFN(device, function); 72 - 73 - for (count = 0; address[count]; count++) { /* for 6 BARs */ 74 - pci_bus_write_config_dword(pbus, devfn, 75 - address[count], 0xFFFFFFFF); 76 - pci_bus_read_config_dword(pbus, devfn, address[count], &bar); 77 - 78 - if (!bar) /* This BAR is not implemented */ 79 - continue; 80 - 81 - dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar); 82 - 83 - if (bar & PCI_BASE_ADDRESS_SPACE_IO) { 84 - /* This is IO */ 85 - 86 - len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF); 87 - len = len & ~(len - 1); 88 - 89 - dbg("len in IO %x, BAR %d\n", len, count); 90 - 91 - spin_lock(&bridge->res_lock); 92 - res = acpiphp_get_io_resource(&bridge->io_head, len); 93 - spin_unlock(&bridge->res_lock); 94 - 95 - if (!res) { 96 - err("cannot allocate requested io for %02x:%02x.%d len %x\n", 97 - bus, device, function, len); 98 - return -1; 99 - } 100 - pci_bus_write_config_dword(pbus, devfn, 101 - address[count], 102 - (u32)res->base); 103 - res->next = func->io_head; 104 - func->io_head = res; 105 - 106 - } else { 107 - /* This is Memory */ 108 - if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) { 109 - /* pfmem */ 110 - 111 - len = bar & 0xFFFFFFF0; 112 - len = ~len + 1; 113 - 114 - dbg("len in PFMEM %x, BAR %d\n", len, count); 115 - 116 - spin_lock(&bridge->res_lock); 117 - res = acpiphp_get_resource(&bridge->p_mem_head, len); 118 - spin_unlock(&bridge->res_lock); 119 - 120 - if (!res) { 121 - err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n", 122 - bus, device, function, len); 123 - return -1; 124 - } 125 - 126 - pci_bus_write_config_dword(pbus, devfn, 127 - address[count], 128 - (u32)res->base); 129 - 130 - if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ 131 - dbg("inside the pfmem 64 case, count %d\n", count); 132 - count += 1; 133 - pci_bus_write_config_dword(pbus, devfn, 134 - address[count], 135 - (u32)(res->base >> 32)); 136 - } 137 - 138 - res->next = func->p_mem_head; 139 - func->p_mem_head = res; 140 - 141 - } else { 142 - /* regular memory */ 143 - 144 - len = bar & 0xFFFFFFF0; 145 - len = ~len + 1; 146 - 147 - dbg("len in MEM %x, BAR %d\n", len, count); 148 - 149 - spin_lock(&bridge->res_lock); 150 - res = acpiphp_get_resource(&bridge->mem_head, len); 151 - spin_unlock(&bridge->res_lock); 152 - 153 - if (!res) { 154 - err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n", 155 - bus, device, function, len); 156 - return -1; 157 - } 158 - 159 - pci_bus_write_config_dword(pbus, devfn, 160 - address[count], 161 - (u32)res->base); 162 - 163 - if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { 164 - /* takes up another dword */ 165 - dbg("inside mem 64 case, reg. mem, count %d\n", count); 166 - count += 1; 167 - pci_bus_write_config_dword(pbus, devfn, 168 - address[count], 169 - (u32)(res->base >> 32)); 170 - } 171 - 172 - res->next = func->mem_head; 173 - func->mem_head = res; 174 - 175 - } 176 - } 177 - } 178 - 179 - /* disable expansion rom */ 180 - pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000); 181 - 182 - /* set PCI parameters from _HPP */ 183 - pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE, 184 - bridge->hpp.cache_line_size); 185 - pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER, 186 - bridge->hpp.latency_timer); 187 - 188 - pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp); 189 - if (bridge->hpp.enable_SERR) 190 - tmp |= PCI_COMMAND_SERR; 191 - if (bridge->hpp.enable_PERR) 192 - tmp |= PCI_COMMAND_PARITY; 193 - pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp); 194 - 195 - return 0; 196 - } 197 - 198 - /* detect_used_resource - subtract resource under dev from bridge */ 199 - static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev) 200 - { 201 - int count; 202 - 203 - dbg("Device %s\n", pci_name(dev)); 204 - 205 - for (count = 0; count < DEVICE_COUNT_RESOURCE; count++) { 206 - struct pci_resource *res; 207 - struct pci_resource **head; 208 - unsigned long base = dev->resource[count].start; 209 - unsigned long len = dev->resource[count].end - base + 1; 210 - unsigned long flags = dev->resource[count].flags; 211 - 212 - if (!flags) 213 - continue; 214 - 215 - dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base, 216 - base + len - 1, flags); 217 - 218 - if (flags & IORESOURCE_IO) { 219 - head = &bridge->io_head; 220 - } else if (flags & IORESOURCE_PREFETCH) { 221 - head = &bridge->p_mem_head; 222 - } else { 223 - head = &bridge->mem_head; 224 - } 225 - 226 - spin_lock(&bridge->res_lock); 227 - res = acpiphp_get_resource_with_base(head, base, len); 228 - spin_unlock(&bridge->res_lock); 229 - if (res) 230 - kfree(res); 231 - } 232 - 233 - return 0; 234 - } 235 - 236 - 237 - /** 238 - * acpiphp_detect_pci_resource - detect resources under bridge 239 - * @bridge: detect all resources already used under this bridge 240 - * 241 - * collect all resources already allocated for all devices under a bridge. 242 - */ 243 - int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge) 244 - { 245 - struct list_head *l; 246 - struct pci_dev *dev; 247 - 248 - list_for_each (l, &bridge->pci_bus->devices) { 249 - dev = pci_dev_b(l); 250 - detect_used_resource(bridge, dev); 251 - } 252 - 253 - return 0; 254 - } 255 - 256 - 257 - /** 258 - * acpiphp_init_slot_resource - gather resource usage information of a slot 259 - * @slot: ACPI slot object to be checked, should have valid pci_dev member 260 - * 261 - * TBD: PCI-to-PCI bridge case 262 - * use pci_dev->resource[] 263 - */ 264 - int acpiphp_init_func_resource (struct acpiphp_func *func) 265 - { 266 - u64 base; 267 - u32 bar, len; 268 - u32 address[] = { 269 - PCI_BASE_ADDRESS_0, 270 - PCI_BASE_ADDRESS_1, 271 - PCI_BASE_ADDRESS_2, 272 - PCI_BASE_ADDRESS_3, 273 - PCI_BASE_ADDRESS_4, 274 - PCI_BASE_ADDRESS_5, 275 - 0 276 - }; 277 - int count; 278 - struct pci_resource *res; 279 - struct pci_dev *dev; 280 - 281 - dev = func->pci_dev; 282 - dbg("Hot-pluggable device %s\n", pci_name(dev)); 283 - 284 - for (count = 0; address[count]; count++) { /* for 6 BARs */ 285 - pci_read_config_dword(dev, address[count], &bar); 286 - 287 - if (!bar) /* This BAR is not implemented */ 288 - continue; 289 - 290 - pci_write_config_dword(dev, address[count], 0xFFFFFFFF); 291 - pci_read_config_dword(dev, address[count], &len); 292 - 293 - if (len & PCI_BASE_ADDRESS_SPACE_IO) { 294 - /* This is IO */ 295 - base = bar & 0xFFFFFFFC; 296 - len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF); 297 - len = len & ~(len - 1); 298 - 299 - dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1); 300 - 301 - res = acpiphp_make_resource(base, len); 302 - if (!res) 303 - goto no_memory; 304 - 305 - res->next = func->io_head; 306 - func->io_head = res; 307 - 308 - } else { 309 - /* This is Memory */ 310 - base = bar & 0xFFFFFFF0; 311 - if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) { 312 - /* pfmem */ 313 - 314 - len &= 0xFFFFFFF0; 315 - len = ~len + 1; 316 - 317 - if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ 318 - dbg("prefetch mem 64\n"); 319 - count += 1; 320 - } 321 - dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1); 322 - res = acpiphp_make_resource(base, len); 323 - if (!res) 324 - goto no_memory; 325 - 326 - res->next = func->p_mem_head; 327 - func->p_mem_head = res; 328 - 329 - } else { 330 - /* regular memory */ 331 - 332 - len &= 0xFFFFFFF0; 333 - len = ~len + 1; 334 - 335 - if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { 336 - /* takes up another dword */ 337 - dbg("mem 64\n"); 338 - count += 1; 339 - } 340 - dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1); 341 - res = acpiphp_make_resource(base, len); 342 - if (!res) 343 - goto no_memory; 344 - 345 - res->next = func->mem_head; 346 - func->mem_head = res; 347 - 348 - } 349 - } 350 - 351 - pci_write_config_dword(dev, address[count], bar); 352 - } 353 - #if 1 354 - acpiphp_dump_func_resource(func); 355 - #endif 356 - 357 - return 0; 358 - 359 - no_memory: 360 - err("out of memory\n"); 361 - acpiphp_free_resource(&func->io_head); 362 - acpiphp_free_resource(&func->mem_head); 363 - acpiphp_free_resource(&func->p_mem_head); 364 - 365 - return -1; 366 - } 367 - 368 - 369 - /** 370 - * acpiphp_configure_slot - allocate PCI resources 371 - * @slot: slot to be configured 372 - * 373 - * initializes a PCI functions on a device inserted 374 - * into the slot 375 - * 376 - */ 377 - int acpiphp_configure_slot (struct acpiphp_slot *slot) 378 - { 379 - struct acpiphp_func *func; 380 - struct list_head *l; 381 - u8 hdr; 382 - u32 dvid; 383 - int retval = 0; 384 - int is_multi = 0; 385 - 386 - pci_bus_read_config_byte(slot->bridge->pci_bus, 387 - PCI_DEVFN(slot->device, 0), 388 - PCI_HEADER_TYPE, &hdr); 389 - 390 - if (hdr & 0x80) 391 - is_multi = 1; 392 - 393 - list_for_each (l, &slot->funcs) { 394 - func = list_entry(l, struct acpiphp_func, sibling); 395 - if (is_multi || func->function == 0) { 396 - pci_bus_read_config_dword(slot->bridge->pci_bus, 397 - PCI_DEVFN(slot->device, 398 - func->function), 399 - PCI_VENDOR_ID, &dvid); 400 - if (dvid != 0xffffffff) { 401 - retval = init_config_space(func); 402 - if (retval) 403 - break; 404 - } 405 - } 406 - } 407 - 408 - return retval; 409 - } 410 - 411 - /** 412 - * acpiphp_configure_function - configure PCI function 413 - * @func: function to be configured 414 - * 415 - * initializes a PCI functions on a device inserted 416 - * into the slot 417 - * 418 - */ 419 - int acpiphp_configure_function (struct acpiphp_func *func) 420 - { 421 - /* all handled by the pci core now */ 422 - return 0; 423 - } 424 - 425 - /** 426 - * acpiphp_unconfigure_function - unconfigure PCI function 427 - * @func: function to be unconfigured 428 - * 429 - */ 430 - void acpiphp_unconfigure_function (struct acpiphp_func *func) 431 - { 432 - struct acpiphp_bridge *bridge; 433 - 434 - /* if pci_dev is NULL, ignore it */ 435 - if (!func->pci_dev) 436 - return; 437 - 438 - pci_remove_bus_device(func->pci_dev); 439 - 440 - /* free all resources */ 441 - bridge = func->slot->bridge; 442 - 443 - spin_lock(&bridge->res_lock); 444 - acpiphp_move_resource(&func->io_head, &bridge->io_head); 445 - acpiphp_move_resource(&func->mem_head, &bridge->mem_head); 446 - acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head); 447 - acpiphp_move_resource(&func->bus_head, &bridge->bus_head); 448 - spin_unlock(&bridge->res_lock); 449 - }
-700
drivers/pci/hotplug/acpiphp_res.c
··· 1 - /* 2 - * ACPI PCI HotPlug Utility functions 3 - * 4 - * Copyright (C) 1995,2001 Compaq Computer Corporation 5 - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 6 - * Copyright (C) 2001 IBM Corp. 7 - * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) 8 - * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com) 9 - * Copyright (C) 2002 NEC Corporation 10 - * 11 - * All rights reserved. 12 - * 13 - * This program is free software; you can redistribute it and/or modify 14 - * it under the terms of the GNU General Public License as published by 15 - * the Free Software Foundation; either version 2 of the License, or (at 16 - * your option) any later version. 17 - * 18 - * This program is distributed in the hope that it will be useful, but 19 - * WITHOUT ANY WARRANTY; without even the implied warranty of 20 - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 21 - * NON INFRINGEMENT. See the GNU General Public License for more 22 - * details. 23 - * 24 - * You should have received a copy of the GNU General Public License 25 - * along with this program; if not, write to the Free Software 26 - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 - * 28 - * Send feedback to <gregkh@us.ibm.com>, <t-kochi@bq.jp.nec.com> 29 - * 30 - */ 31 - 32 - #include <linux/init.h> 33 - #include <linux/module.h> 34 - 35 - #include <linux/kernel.h> 36 - #include <linux/types.h> 37 - #include <linux/proc_fs.h> 38 - #include <linux/sysctl.h> 39 - #include <linux/pci.h> 40 - #include <linux/smp.h> 41 - #include <linux/smp_lock.h> 42 - 43 - #include <linux/string.h> 44 - #include <linux/mm.h> 45 - #include <linux/errno.h> 46 - #include <linux/ioport.h> 47 - #include <linux/slab.h> 48 - #include <linux/interrupt.h> 49 - #include <linux/timer.h> 50 - 51 - #include <linux/ioctl.h> 52 - #include <linux/fcntl.h> 53 - 54 - #include <linux/list.h> 55 - 56 - #include "pci_hotplug.h" 57 - #include "acpiphp.h" 58 - 59 - #define MY_NAME "acpiphp_res" 60 - 61 - 62 - /* 63 - * sort_by_size - sort nodes by their length, smallest first 64 - */ 65 - static int sort_by_size(struct pci_resource **head) 66 - { 67 - struct pci_resource *current_res; 68 - struct pci_resource *next_res; 69 - int out_of_order = 1; 70 - 71 - if (!(*head)) 72 - return 1; 73 - 74 - if (!((*head)->next)) 75 - return 0; 76 - 77 - while (out_of_order) { 78 - out_of_order = 0; 79 - 80 - /* Special case for swapping list head */ 81 - if (((*head)->next) && 82 - ((*head)->length > (*head)->next->length)) { 83 - out_of_order++; 84 - current_res = *head; 85 - *head = (*head)->next; 86 - current_res->next = (*head)->next; 87 - (*head)->next = current_res; 88 - } 89 - 90 - current_res = *head; 91 - 92 - while (current_res->next && current_res->next->next) { 93 - if (current_res->next->length > current_res->next->next->length) { 94 - out_of_order++; 95 - next_res = current_res->next; 96 - current_res->next = current_res->next->next; 97 - current_res = current_res->next; 98 - next_res->next = current_res->next; 99 - current_res->next = next_res; 100 - } else 101 - current_res = current_res->next; 102 - } 103 - } /* End of out_of_order loop */ 104 - 105 - return 0; 106 - } 107 - 108 - #if 0 109 - /* 110 - * sort_by_max_size - sort nodes by their length, largest first 111 - */ 112 - static int sort_by_max_size(struct pci_resource **head) 113 - { 114 - struct pci_resource *current_res; 115 - struct pci_resource *next_res; 116 - int out_of_order = 1; 117 - 118 - if (!(*head)) 119 - return 1; 120 - 121 - if (!((*head)->next)) 122 - return 0; 123 - 124 - while (out_of_order) { 125 - out_of_order = 0; 126 - 127 - /* Special case for swapping list head */ 128 - if (((*head)->next) && 129 - ((*head)->length < (*head)->next->length)) { 130 - out_of_order++; 131 - current_res = *head; 132 - *head = (*head)->next; 133 - current_res->next = (*head)->next; 134 - (*head)->next = current_res; 135 - } 136 - 137 - current_res = *head; 138 - 139 - while (current_res->next && current_res->next->next) { 140 - if (current_res->next->length < current_res->next->next->length) { 141 - out_of_order++; 142 - next_res = current_res->next; 143 - current_res->next = current_res->next->next; 144 - current_res = current_res->next; 145 - next_res->next = current_res->next; 146 - current_res->next = next_res; 147 - } else 148 - current_res = current_res->next; 149 - } 150 - } /* End of out_of_order loop */ 151 - 152 - return 0; 153 - } 154 - #endif 155 - 156 - /** 157 - * get_io_resource - get resource for I/O ports 158 - * 159 - * this function sorts the resource list by size and then 160 - * returns the first node of "size" length that is not in the 161 - * ISA aliasing window. If it finds a node larger than "size" 162 - * it will split it up. 163 - * 164 - * size must be a power of two. 165 - * 166 - * difference from get_resource is handling of ISA aliasing space. 167 - * 168 - */ 169 - struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size) 170 - { 171 - struct pci_resource *prevnode; 172 - struct pci_resource *node; 173 - struct pci_resource *split_node; 174 - u64 temp_qword; 175 - 176 - if (!(*head)) 177 - return NULL; 178 - 179 - if (acpiphp_resource_sort_and_combine(head)) 180 - return NULL; 181 - 182 - if (sort_by_size(head)) 183 - return NULL; 184 - 185 - for (node = *head; node; node = node->next) { 186 - if (node->length < size) 187 - continue; 188 - 189 - if (node->base & (size - 1)) { 190 - /* this one isn't base aligned properly 191 - so we'll make a new entry and split it up */ 192 - temp_qword = (node->base | (size-1)) + 1; 193 - 194 - /* Short circuit if adjusted size is too small */ 195 - if ((node->length - (temp_qword - node->base)) < size) 196 - continue; 197 - 198 - split_node = acpiphp_make_resource(node->base, temp_qword - node->base); 199 - 200 - if (!split_node) 201 - return NULL; 202 - 203 - node->base = temp_qword; 204 - node->length -= split_node->length; 205 - 206 - /* Put it in the list */ 207 - split_node->next = node->next; 208 - node->next = split_node; 209 - } /* End of non-aligned base */ 210 - 211 - /* Don't need to check if too small since we already did */ 212 - if (node->length > size) { 213 - /* this one is longer than we need 214 - so we'll make a new entry and split it up */ 215 - split_node = acpiphp_make_resource(node->base + size, node->length - size); 216 - 217 - if (!split_node) 218 - return NULL; 219 - 220 - node->length = size; 221 - 222 - /* Put it in the list */ 223 - split_node->next = node->next; 224 - node->next = split_node; 225 - } /* End of too big on top end */ 226 - 227 - /* For IO make sure it's not in the ISA aliasing space */ 228 - if ((node->base & 0x300L) && !(node->base & 0xfffff000)) 229 - continue; 230 - 231 - /* If we got here, then it is the right size 232 - Now take it out of the list */ 233 - if (*head == node) { 234 - *head = node->next; 235 - } else { 236 - prevnode = *head; 237 - while (prevnode->next != node) 238 - prevnode = prevnode->next; 239 - 240 - prevnode->next = node->next; 241 - } 242 - node->next = NULL; 243 - /* Stop looping */ 244 - break; 245 - } 246 - 247 - return node; 248 - } 249 - 250 - 251 - #if 0 252 - /** 253 - * get_max_resource - get the largest resource 254 - * 255 - * Gets the largest node that is at least "size" big from the 256 - * list pointed to by head. It aligns the node on top and bottom 257 - * to "size" alignment before returning it. 258 - */ 259 - static struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size) 260 - { 261 - struct pci_resource *max; 262 - struct pci_resource *temp; 263 - struct pci_resource *split_node; 264 - u64 temp_qword; 265 - 266 - if (!(*head)) 267 - return NULL; 268 - 269 - if (acpiphp_resource_sort_and_combine(head)) 270 - return NULL; 271 - 272 - if (sort_by_max_size(head)) 273 - return NULL; 274 - 275 - for (max = *head;max; max = max->next) { 276 - 277 - /* If not big enough we could probably just bail, 278 - instead we'll continue to the next. */ 279 - if (max->length < size) 280 - continue; 281 - 282 - if (max->base & (size - 1)) { 283 - /* this one isn't base aligned properly 284 - so we'll make a new entry and split it up */ 285 - temp_qword = (max->base | (size-1)) + 1; 286 - 287 - /* Short circuit if adjusted size is too small */ 288 - if ((max->length - (temp_qword - max->base)) < size) 289 - continue; 290 - 291 - split_node = acpiphp_make_resource(max->base, temp_qword - max->base); 292 - 293 - if (!split_node) 294 - return NULL; 295 - 296 - max->base = temp_qword; 297 - max->length -= split_node->length; 298 - 299 - /* Put it next in the list */ 300 - split_node->next = max->next; 301 - max->next = split_node; 302 - } 303 - 304 - if ((max->base + max->length) & (size - 1)) { 305 - /* this one isn't end aligned properly at the top 306 - so we'll make a new entry and split it up */ 307 - temp_qword = ((max->base + max->length) & ~(size - 1)); 308 - 309 - split_node = acpiphp_make_resource(temp_qword, 310 - max->length + max->base - temp_qword); 311 - 312 - if (!split_node) 313 - return NULL; 314 - 315 - max->length -= split_node->length; 316 - 317 - /* Put it in the list */ 318 - split_node->next = max->next; 319 - max->next = split_node; 320 - } 321 - 322 - /* Make sure it didn't shrink too much when we aligned it */ 323 - if (max->length < size) 324 - continue; 325 - 326 - /* Now take it out of the list */ 327 - temp = (struct pci_resource*) *head; 328 - if (temp == max) { 329 - *head = max->next; 330 - } else { 331 - while (temp && temp->next != max) { 332 - temp = temp->next; 333 - } 334 - 335 - temp->next = max->next; 336 - } 337 - 338 - max->next = NULL; 339 - return max; 340 - } 341 - 342 - /* If we get here, we couldn't find one */ 343 - return NULL; 344 - } 345 - #endif 346 - 347 - /** 348 - * get_resource - get resource (mem, pfmem) 349 - * 350 - * this function sorts the resource list by size and then 351 - * returns the first node of "size" length. If it finds a node 352 - * larger than "size" it will split it up. 353 - * 354 - * size must be a power of two. 355 - * 356 - */ 357 - struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size) 358 - { 359 - struct pci_resource *prevnode; 360 - struct pci_resource *node; 361 - struct pci_resource *split_node; 362 - u64 temp_qword; 363 - 364 - if (!(*head)) 365 - return NULL; 366 - 367 - if (acpiphp_resource_sort_and_combine(head)) 368 - return NULL; 369 - 370 - if (sort_by_size(head)) 371 - return NULL; 372 - 373 - for (node = *head; node; node = node->next) { 374 - dbg("%s: req_size =%x node=%p, base=%x, length=%x\n", 375 - __FUNCTION__, size, node, (u32)node->base, node->length); 376 - if (node->length < size) 377 - continue; 378 - 379 - if (node->base & (size - 1)) { 380 - dbg("%s: not aligned\n", __FUNCTION__); 381 - /* this one isn't base aligned properly 382 - so we'll make a new entry and split it up */ 383 - temp_qword = (node->base | (size-1)) + 1; 384 - 385 - /* Short circuit if adjusted size is too small */ 386 - if ((node->length - (temp_qword - node->base)) < size) 387 - continue; 388 - 389 - split_node = acpiphp_make_resource(node->base, temp_qword - node->base); 390 - 391 - if (!split_node) 392 - return NULL; 393 - 394 - node->base = temp_qword; 395 - node->length -= split_node->length; 396 - 397 - /* Put it in the list */ 398 - split_node->next = node->next; 399 - node->next = split_node; 400 - } /* End of non-aligned base */ 401 - 402 - /* Don't need to check if too small since we already did */ 403 - if (node->length > size) { 404 - dbg("%s: too big\n", __FUNCTION__); 405 - /* this one is longer than we need 406 - so we'll make a new entry and split it up */ 407 - split_node = acpiphp_make_resource(node->base + size, node->length - size); 408 - 409 - if (!split_node) 410 - return NULL; 411 - 412 - node->length = size; 413 - 414 - /* Put it in the list */ 415 - split_node->next = node->next; 416 - node->next = split_node; 417 - } /* End of too big on top end */ 418 - 419 - dbg("%s: got one!!!\n", __FUNCTION__); 420 - /* If we got here, then it is the right size 421 - Now take it out of the list */ 422 - if (*head == node) { 423 - *head = node->next; 424 - } else { 425 - prevnode = *head; 426 - while (prevnode->next != node) 427 - prevnode = prevnode->next; 428 - 429 - prevnode->next = node->next; 430 - } 431 - node->next = NULL; 432 - /* Stop looping */ 433 - break; 434 - } 435 - return node; 436 - } 437 - 438 - /** 439 - * get_resource_with_base - get resource with specific base address 440 - * 441 - * this function 442 - * returns the first node of "size" length located at specified base address. 443 - * If it finds a node larger than "size" it will split it up. 444 - * 445 - * size must be a power of two. 446 - * 447 - */ 448 - struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size) 449 - { 450 - struct pci_resource *prevnode; 451 - struct pci_resource *node; 452 - struct pci_resource *split_node; 453 - u64 temp_qword; 454 - 455 - if (!(*head)) 456 - return NULL; 457 - 458 - if (acpiphp_resource_sort_and_combine(head)) 459 - return NULL; 460 - 461 - for (node = *head; node; node = node->next) { 462 - dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n", 463 - (u32)base, size, node, (u32)node->base, node->length); 464 - if (node->base > base) 465 - continue; 466 - 467 - if ((node->base + node->length) < (base + size)) 468 - continue; 469 - 470 - if (node->base < base) { 471 - dbg(": split 1\n"); 472 - /* this one isn't base aligned properly 473 - so we'll make a new entry and split it up */ 474 - temp_qword = base; 475 - 476 - /* Short circuit if adjusted size is too small */ 477 - if ((node->length - (temp_qword - node->base)) < size) 478 - continue; 479 - 480 - split_node = acpiphp_make_resource(node->base, temp_qword - node->base); 481 - 482 - if (!split_node) 483 - return NULL; 484 - 485 - node->base = temp_qword; 486 - node->length -= split_node->length; 487 - 488 - /* Put it in the list */ 489 - split_node->next = node->next; 490 - node->next = split_node; 491 - } 492 - 493 - dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n", 494 - (u32)base, size, node, (u32)node->base, node->length); 495 - 496 - /* Don't need to check if too small since we already did */ 497 - if (node->length > size) { 498 - dbg(": split 2\n"); 499 - /* this one is longer than we need 500 - so we'll make a new entry and split it up */ 501 - split_node = acpiphp_make_resource(node->base + size, node->length - size); 502 - 503 - if (!split_node) 504 - return NULL; 505 - 506 - node->length = size; 507 - 508 - /* Put it in the list */ 509 - split_node->next = node->next; 510 - node->next = split_node; 511 - } /* End of too big on top end */ 512 - 513 - dbg(": got one!!!\n"); 514 - /* If we got here, then it is the right size 515 - Now take it out of the list */ 516 - if (*head == node) { 517 - *head = node->next; 518 - } else { 519 - prevnode = *head; 520 - while (prevnode->next != node) 521 - prevnode = prevnode->next; 522 - 523 - prevnode->next = node->next; 524 - } 525 - node->next = NULL; 526 - /* Stop looping */ 527 - break; 528 - } 529 - return node; 530 - } 531 - 532 - 533 - /** 534 - * acpiphp_resource_sort_and_combine 535 - * 536 - * Sorts all of the nodes in the list in ascending order by 537 - * their base addresses. Also does garbage collection by 538 - * combining adjacent nodes. 539 - * 540 - * returns 0 if success 541 - */ 542 - int acpiphp_resource_sort_and_combine (struct pci_resource **head) 543 - { 544 - struct pci_resource *node1; 545 - struct pci_resource *node2; 546 - int out_of_order = 1; 547 - 548 - if (!(*head)) 549 - return 1; 550 - 551 - dbg("*head->next = %p\n",(*head)->next); 552 - 553 - if (!(*head)->next) 554 - return 0; /* only one item on the list, already sorted! */ 555 - 556 - dbg("*head->base = 0x%x\n",(u32)(*head)->base); 557 - dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base); 558 - while (out_of_order) { 559 - out_of_order = 0; 560 - 561 - /* Special case for swapping list head */ 562 - if (((*head)->next) && 563 - ((*head)->base > (*head)->next->base)) { 564 - node1 = *head; 565 - (*head) = (*head)->next; 566 - node1->next = (*head)->next; 567 - (*head)->next = node1; 568 - out_of_order++; 569 - } 570 - 571 - node1 = (*head); 572 - 573 - while (node1->next && node1->next->next) { 574 - if (node1->next->base > node1->next->next->base) { 575 - out_of_order++; 576 - node2 = node1->next; 577 - node1->next = node1->next->next; 578 - node1 = node1->next; 579 - node2->next = node1->next; 580 - node1->next = node2; 581 - } else 582 - node1 = node1->next; 583 - } 584 - } /* End of out_of_order loop */ 585 - 586 - node1 = *head; 587 - 588 - while (node1 && node1->next) { 589 - if ((node1->base + node1->length) == node1->next->base) { 590 - /* Combine */ 591 - dbg("8..\n"); 592 - node1->length += node1->next->length; 593 - node2 = node1->next; 594 - node1->next = node1->next->next; 595 - kfree(node2); 596 - } else 597 - node1 = node1->next; 598 - } 599 - 600 - return 0; 601 - } 602 - 603 - 604 - /** 605 - * acpiphp_make_resource - make resource structure 606 - * @base: base address of a resource 607 - * @length: length of a resource 608 - */ 609 - struct pci_resource *acpiphp_make_resource (u64 base, u32 length) 610 - { 611 - struct pci_resource *res; 612 - 613 - res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 614 - if (res) { 615 - memset(res, 0, sizeof(struct pci_resource)); 616 - res->base = base; 617 - res->length = length; 618 - } 619 - 620 - return res; 621 - } 622 - 623 - 624 - /** 625 - * acpiphp_move_resource - move linked resources from one to another 626 - * @from: head of linked resource list 627 - * @to: head of linked resource list 628 - */ 629 - void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to) 630 - { 631 - struct pci_resource *tmp; 632 - 633 - while (*from) { 634 - tmp = (*from)->next; 635 - (*from)->next = *to; 636 - *to = *from; 637 - *from = tmp; 638 - } 639 - 640 - /* *from = NULL is guaranteed */ 641 - } 642 - 643 - 644 - /** 645 - * acpiphp_free_resource - free all linked resources 646 - * @res: head of linked resource list 647 - */ 648 - void acpiphp_free_resource (struct pci_resource **res) 649 - { 650 - struct pci_resource *tmp; 651 - 652 - while (*res) { 653 - tmp = (*res)->next; 654 - kfree(*res); 655 - *res = tmp; 656 - } 657 - 658 - /* *res = NULL is guaranteed */ 659 - } 660 - 661 - 662 - /* debug support functions; will go away sometime :) */ 663 - static void dump_resource(struct pci_resource *head) 664 - { 665 - struct pci_resource *p; 666 - int cnt; 667 - 668 - p = head; 669 - cnt = 0; 670 - 671 - while (p) { 672 - dbg("[%02d] %08x - %08x\n", 673 - cnt++, (u32)p->base, (u32)p->base + p->length - 1); 674 - p = p->next; 675 - } 676 - } 677 - 678 - void acpiphp_dump_resource(struct acpiphp_bridge *bridge) 679 - { 680 - dbg("I/O resource:\n"); 681 - dump_resource(bridge->io_head); 682 - dbg("MEM resource:\n"); 683 - dump_resource(bridge->mem_head); 684 - dbg("PMEM resource:\n"); 685 - dump_resource(bridge->p_mem_head); 686 - dbg("BUS resource:\n"); 687 - dump_resource(bridge->bus_head); 688 - } 689 - 690 - void acpiphp_dump_func_resource(struct acpiphp_func *func) 691 - { 692 - dbg("I/O resource:\n"); 693 - dump_resource(func->io_head); 694 - dbg("MEM resource:\n"); 695 - dump_resource(func->mem_head); 696 - dbg("PMEM resource:\n"); 697 - dump_resource(func->p_mem_head); 698 - dbg("BUS resource:\n"); 699 - dump_resource(func->bus_head); 700 - }