diff options
Diffstat (limited to 'arch/sparc64/kernel/pci.c')
-rw-r--r-- | arch/sparc64/kernel/pci.c | 133 |
1 files changed, 5 insertions, 128 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 9c17591c2a79..2ff7c32ab0ce 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -359,140 +359,17 @@ void pcibios_fixup_bus(struct pci_bus *pbus) | |||
359 | pbus->resource[1] = &pbm->mem_space; | 359 | pbus->resource[1] = &pbm->mem_space; |
360 | } | 360 | } |
361 | 361 | ||
362 | int pci_claim_resource(struct pci_dev *pdev, int resource) | 362 | struct resource *pcibios_select_root(struct pci_dev *pdev, struct resource *r) |
363 | { | 363 | { |
364 | struct pci_pbm_info *pbm = pdev->bus->sysdata; | 364 | struct pci_pbm_info *pbm = pdev->bus->sysdata; |
365 | struct resource *res = &pdev->resource[resource]; | 365 | struct resource *root = NULL; |
366 | struct resource *root; | ||
367 | |||
368 | if (!pbm) | ||
369 | return -EINVAL; | ||
370 | 366 | ||
371 | if (res->flags & IORESOURCE_IO) | 367 | if (r->flags & IORESOURCE_IO) |
372 | root = &pbm->io_space; | 368 | root = &pbm->io_space; |
373 | else | 369 | if (r->flags & IORESOURCE_MEM) |
374 | root = &pbm->mem_space; | 370 | root = &pbm->mem_space; |
375 | 371 | ||
376 | pbm->parent->resource_adjust(pdev, res, root); | 372 | return root; |
377 | |||
378 | return request_resource(root, res); | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * Given the PCI bus a device resides on, try to | ||
383 | * find an acceptable resource allocation for a | ||
384 | * specific device resource.. | ||
385 | */ | ||
386 | static int pci_assign_bus_resource(const struct pci_bus *bus, | ||
387 | struct pci_dev *dev, | ||
388 | struct resource *res, | ||
389 | unsigned long size, | ||
390 | unsigned long min, | ||
391 | int resno) | ||
392 | { | ||
393 | unsigned int type_mask; | ||
394 | int i; | ||
395 | |||
396 | type_mask = IORESOURCE_IO | IORESOURCE_MEM; | ||
397 | for (i = 0 ; i < 4; i++) { | ||
398 | struct resource *r = bus->resource[i]; | ||
399 | if (!r) | ||
400 | continue; | ||
401 | |||
402 | /* type_mask must match */ | ||
403 | if ((res->flags ^ r->flags) & type_mask) | ||
404 | continue; | ||
405 | |||
406 | /* Ok, try it out.. */ | ||
407 | if (allocate_resource(r, res, size, min, -1, size, NULL, NULL) < 0) | ||
408 | continue; | ||
409 | |||
410 | /* PCI config space updated by caller. */ | ||
411 | return 0; | ||
412 | } | ||
413 | return -EBUSY; | ||
414 | } | ||
415 | |||
416 | void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) | ||
417 | { | ||
418 | /* Not implemented for sparc64... */ | ||
419 | BUG(); | ||
420 | } | ||
421 | |||
422 | int pci_assign_resource(struct pci_dev *pdev, int resource) | ||
423 | { | ||
424 | struct pcidev_cookie *pcp = pdev->sysdata; | ||
425 | struct pci_pbm_info *pbm = pcp->pbm; | ||
426 | struct resource *res = &pdev->resource[resource]; | ||
427 | unsigned long min, size; | ||
428 | int err; | ||
429 | |||
430 | if (res->flags & IORESOURCE_IO) | ||
431 | min = pbm->io_space.start + 0x400UL; | ||
432 | else | ||
433 | min = pbm->mem_space.start; | ||
434 | |||
435 | size = res->end - res->start + 1; | ||
436 | |||
437 | err = pci_assign_bus_resource(pdev->bus, pdev, res, size, min, resource); | ||
438 | |||
439 | if (err < 0) { | ||
440 | printk("PCI: Failed to allocate resource %d for %s\n", | ||
441 | resource, pci_name(pdev)); | ||
442 | } else { | ||
443 | /* Update PCI config space. */ | ||
444 | pbm->parent->base_address_update(pdev, resource); | ||
445 | } | ||
446 | |||
447 | return err; | ||
448 | } | ||
449 | |||
450 | /* Sort resources by alignment */ | ||
451 | void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) | ||
452 | { | ||
453 | int i; | ||
454 | |||
455 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||
456 | struct resource *r; | ||
457 | struct resource_list *list, *tmp; | ||
458 | unsigned long r_align; | ||
459 | |||
460 | r = &dev->resource[i]; | ||
461 | r_align = r->end - r->start; | ||
462 | |||
463 | if (!(r->flags) || r->parent) | ||
464 | continue; | ||
465 | if (!r_align) { | ||
466 | printk(KERN_WARNING "PCI: Ignore bogus resource %d " | ||
467 | "[%lx:%lx] of %s\n", | ||
468 | i, r->start, r->end, pci_name(dev)); | ||
469 | continue; | ||
470 | } | ||
471 | r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start; | ||
472 | for (list = head; ; list = list->next) { | ||
473 | unsigned long align = 0; | ||
474 | struct resource_list *ln = list->next; | ||
475 | int idx; | ||
476 | |||
477 | if (ln) { | ||
478 | idx = ln->res - &ln->dev->resource[0]; | ||
479 | align = (idx < PCI_BRIDGE_RESOURCES) ? | ||
480 | ln->res->end - ln->res->start + 1 : | ||
481 | ln->res->start; | ||
482 | } | ||
483 | if (r_align > align) { | ||
484 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
485 | if (!tmp) | ||
486 | panic("pdev_sort_resources(): " | ||
487 | "kmalloc() failed!\n"); | ||
488 | tmp->next = ln; | ||
489 | tmp->res = r; | ||
490 | tmp->dev = dev; | ||
491 | list->next = tmp; | ||
492 | break; | ||
493 | } | ||
494 | } | ||
495 | } | ||
496 | } | 373 | } |
497 | 374 | ||
498 | void pcibios_update_irq(struct pci_dev *pdev, int irq) | 375 | void pcibios_update_irq(struct pci_dev *pdev, int irq) |