aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-08-08 16:19:08 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 17:57:25 -0400
commit085ae41f66657a9655ce832b0a61832a06f0e1dc (patch)
tree215690b947b14fa18cbb2810db1a4082ad607e7a /arch/sparc64/kernel/pci.c
parent064b53dbcc977dbf2753a67c2b8fc1c061d74f21 (diff)
[PATCH] Make sparc64 use setup-res.c
There were three changes necessary in order to allow sparc64 to use setup-res.c: 1) Sparc64 roots the PCI I/O and MEM address space using parent resources contained in the PCI controller structure. I'm actually surprised no other platforms do this, especially ones like Alpha and PPC{,64}. These resources get linked into the iomem/ioport tree when PCI controllers are probed. So the hierarchy looks like this: iomem --| PCI controller 1 MEM space --| device 1 device 2 etc. PCI controller 2 MEM space --| ... ioport --| PCI controller 1 IO space --| ... PCI controller 2 IO space --| ... You get the idea. The drivers/pci/setup-res.c code allocates using plain iomem_space and ioport_space as the root, so that wouldn't work with the above setup. So I added a pcibios_select_root() that is used to handle this. It uses the PCI controller struct's io_space and mem_space on sparc64, and io{port,mem}_resource on every other platform to keep current behavior. 2) quirk_io_region() is buggy. It takes in raw BUS view addresses and tries to use them as a PCI resource. pci_claim_resource() expects the resource to be fully formed when it gets called. The sparc64 implementation would do the translation but that's absolutely wrong, because if the same resource gets released then re-claimed we'll adjust things twice. So I fixed up quirk_io_region() to do the proper pcibios_bus_to_resource() conversion before passing it on to pci_claim_resource(). 3) I was mistakedly __init'ing the function methods the PCI controller drivers provide on sparc64 to implement some parts of these routines. This was, of course, easy to fix. So we end up with the following, and that nasty SPARC64 makefile ifdef in drivers/pci/Makefile is finally zapped. Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch/sparc64/kernel/pci.c')
-rw-r--r--arch/sparc64/kernel/pci.c133
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
362int pci_claim_resource(struct pci_dev *pdev, int resource) 362struct 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 */
386static 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
416void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
417{
418 /* Not implemented for sparc64... */
419 BUG();
420}
421
422int 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 */
451void 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
498void pcibios_update_irq(struct pci_dev *pdev, int irq) 375void pcibios_update_irq(struct pci_dev *pdev, int irq)