aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/pci/pci.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-11-12 13:33:06 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-11-15 08:08:37 -0500
commit7a572a3ab1d1d346fcde5243914a18b0218780e9 (patch)
tree35fc7fdac2f24256204467609a3c0455fe51e836 /arch/s390/pci/pci.c
parentd1e61fe49fd450be15d402ac353784f5ba8a624e (diff)
s390/pci: improve handling of bus resources
Cleanup the functions for allocation and setup of bus resources. Do not allocate the same name for each resource but use a per-bus name. Also provide means to cleanup all resources allocated by a bus. Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r--arch/s390/pci/pci.c147
1 files changed, 83 insertions, 64 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 0c9a17780e4b..63a086072edb 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -579,37 +579,6 @@ static void zpci_irq_exit(void)
579 unregister_adapter_interrupt(&zpci_airq); 579 unregister_adapter_interrupt(&zpci_airq);
580} 580}
581 581
582static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size,
583 unsigned long flags, int domain)
584{
585 struct resource *r;
586 char *name;
587 int rc;
588
589 r = kzalloc(sizeof(*r), GFP_KERNEL);
590 if (!r)
591 return ERR_PTR(-ENOMEM);
592 r->start = start;
593 r->end = r->start + size - 1;
594 r->flags = flags;
595 r->parent = &iomem_resource;
596 name = kmalloc(18, GFP_KERNEL);
597 if (!name) {
598 kfree(r);
599 return ERR_PTR(-ENOMEM);
600 }
601 sprintf(name, "PCI Bus: %04x:%02x", domain, ZPCI_BUS_NR);
602 r->name = name;
603
604 rc = request_resource(&iomem_resource, r);
605 if (rc) {
606 kfree(r->name);
607 kfree(r);
608 return ERR_PTR(-ENOMEM);
609 }
610 return r;
611}
612
613static int zpci_alloc_iomap(struct zpci_dev *zdev) 582static int zpci_alloc_iomap(struct zpci_dev *zdev)
614{ 583{
615 int entry; 584 int entry;
@@ -633,6 +602,82 @@ static void zpci_free_iomap(struct zpci_dev *zdev, int entry)
633 spin_unlock(&zpci_iomap_lock); 602 spin_unlock(&zpci_iomap_lock);
634} 603}
635 604
605static struct resource *__alloc_res(struct zpci_dev *zdev, unsigned long start,
606 unsigned long size, unsigned long flags)
607{
608 struct resource *r;
609
610 r = kzalloc(sizeof(*r), GFP_KERNEL);
611 if (!r)
612 return NULL;
613
614 r->start = start;
615 r->end = r->start + size - 1;
616 r->flags = flags;
617 r->name = zdev->res_name;
618
619 if (request_resource(&iomem_resource, r)) {
620 kfree(r);
621 return NULL;
622 }
623 return r;
624}
625
626static int zpci_setup_bus_resources(struct zpci_dev *zdev,
627 struct list_head *resources)
628{
629 unsigned long addr, size, flags;
630 struct resource *res;
631 int i, entry;
632
633 snprintf(zdev->res_name, sizeof(zdev->res_name),
634 "PCI Bus %04x:%02x", zdev->domain, ZPCI_BUS_NR);
635
636 for (i = 0; i < PCI_BAR_COUNT; i++) {
637 if (!zdev->bars[i].size)
638 continue;
639 entry = zpci_alloc_iomap(zdev);
640 if (entry < 0)
641 return entry;
642 zdev->bars[i].map_idx = entry;
643
644 /* only MMIO is supported */
645 flags = IORESOURCE_MEM;
646 if (zdev->bars[i].val & 8)
647 flags |= IORESOURCE_PREFETCH;
648 if (zdev->bars[i].val & 4)
649 flags |= IORESOURCE_MEM_64;
650
651 addr = ZPCI_IOMAP_ADDR_BASE + ((u64) entry << 48);
652
653 size = 1UL << zdev->bars[i].size;
654
655 res = __alloc_res(zdev, addr, size, flags);
656 if (!res) {
657 zpci_free_iomap(zdev, entry);
658 return -ENOMEM;
659 }
660 zdev->bars[i].res = res;
661 pci_add_resource(resources, res);
662 }
663
664 return 0;
665}
666
667static void zpci_cleanup_bus_resources(struct zpci_dev *zdev)
668{
669 int i;
670
671 for (i = 0; i < PCI_BAR_COUNT; i++) {
672 if (!zdev->bars[i].size)
673 continue;
674
675 zpci_free_iomap(zdev, zdev->bars[i].map_idx);
676 release_resource(zdev->bars[i].res);
677 kfree(zdev->bars[i].res);
678 }
679}
680
636int pcibios_add_device(struct pci_dev *pdev) 681int pcibios_add_device(struct pci_dev *pdev)
637{ 682{
638 struct zpci_dev *zdev = get_zdev(pdev); 683 struct zpci_dev *zdev = get_zdev(pdev);
@@ -731,45 +776,19 @@ struct dev_pm_ops pcibios_pm_ops = {
731 776
732static int zpci_scan_bus(struct zpci_dev *zdev) 777static int zpci_scan_bus(struct zpci_dev *zdev)
733{ 778{
734 struct resource *res;
735 LIST_HEAD(resources); 779 LIST_HEAD(resources);
736 int i; 780 int ret;
737
738 /* allocate mapping entry for each used bar */
739 for (i = 0; i < PCI_BAR_COUNT; i++) {
740 unsigned long addr, size, flags;
741 int entry;
742
743 if (!zdev->bars[i].size)
744 continue;
745 entry = zpci_alloc_iomap(zdev);
746 if (entry < 0)
747 return entry;
748 zdev->bars[i].map_idx = entry;
749
750 /* only MMIO is supported */
751 flags = IORESOURCE_MEM;
752 if (zdev->bars[i].val & 8)
753 flags |= IORESOURCE_PREFETCH;
754 if (zdev->bars[i].val & 4)
755 flags |= IORESOURCE_MEM_64;
756
757 addr = ZPCI_IOMAP_ADDR_BASE + ((u64) entry << 48);
758
759 size = 1UL << zdev->bars[i].size;
760 781
761 res = zpci_alloc_bus_resource(addr, size, flags, zdev->domain); 782 ret = zpci_setup_bus_resources(zdev, &resources);
762 if (IS_ERR(res)) { 783 if (ret)
763 zpci_free_iomap(zdev, entry); 784 return ret;
764 return PTR_ERR(res);
765 }
766 pci_add_resource(&resources, res);
767 }
768 785
769 zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops, 786 zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
770 zdev, &resources); 787 zdev, &resources);
771 if (!zdev->bus) 788 if (!zdev->bus) {
789 zpci_cleanup_bus_resources(zdev);
772 return -EIO; 790 return -EIO;
791 }
773 792
774 zdev->bus->max_bus_speed = zdev->max_bus_speed; 793 zdev->bus->max_bus_speed = zdev->max_bus_speed;
775 return 0; 794 return 0;