aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r--arch/s390/pci/pci.c83
1 files changed, 37 insertions, 46 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index f1e5be85d592..e2956ad39a4f 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -82,10 +82,13 @@ struct intr_bucket {
82 82
83static struct intr_bucket *bucket; 83static struct intr_bucket *bucket;
84 84
85/* Adapter local summary indicator */ 85/* Adapter interrupt definitions */
86static u8 *zpci_irq_si; 86static void zpci_irq_handler(struct airq_struct *airq);
87 87
88static atomic_t irq_retries = ATOMIC_INIT(0); 88static struct airq_struct zpci_airq = {
89 .handler = zpci_irq_handler,
90 .isc = PCI_ISC,
91};
89 92
90/* I/O Map */ 93/* I/O Map */
91static DEFINE_SPINLOCK(zpci_iomap_lock); 94static DEFINE_SPINLOCK(zpci_iomap_lock);
@@ -404,7 +407,7 @@ static struct pci_ops pci_root_ops = {
404/* store the last handled bit to implement fair scheduling of devices */ 407/* store the last handled bit to implement fair scheduling of devices */
405static DEFINE_PER_CPU(unsigned long, next_sbit); 408static DEFINE_PER_CPU(unsigned long, next_sbit);
406 409
407static void zpci_irq_handler(void *dont, void *need) 410static void zpci_irq_handler(struct airq_struct *airq)
408{ 411{
409 unsigned long sbit, mbit, last = 0, start = __get_cpu_var(next_sbit); 412 unsigned long sbit, mbit, last = 0, start = __get_cpu_var(next_sbit);
410 int rescan = 0, max = aisb_max; 413 int rescan = 0, max = aisb_max;
@@ -452,7 +455,6 @@ scan:
452 max = aisb_max; 455 max = aisb_max;
453 sbit = find_first_bit_left(bucket->aisb, max); 456 sbit = find_first_bit_left(bucket->aisb, max);
454 if (sbit != max) { 457 if (sbit != max) {
455 atomic_inc(&irq_retries);
456 rescan++; 458 rescan++;
457 goto scan; 459 goto scan;
458 } 460 }
@@ -565,7 +567,21 @@ static void zpci_map_resources(struct zpci_dev *zdev)
565 pr_debug("BAR%i: -> start: %Lx end: %Lx\n", 567 pr_debug("BAR%i: -> start: %Lx end: %Lx\n",
566 i, pdev->resource[i].start, pdev->resource[i].end); 568 i, pdev->resource[i].start, pdev->resource[i].end);
567 } 569 }
568}; 570}
571
572static void zpci_unmap_resources(struct zpci_dev *zdev)
573{
574 struct pci_dev *pdev = zdev->pdev;
575 resource_size_t len;
576 int i;
577
578 for (i = 0; i < PCI_BAR_COUNT; i++) {
579 len = pci_resource_len(pdev, i);
580 if (!len)
581 continue;
582 pci_iounmap(pdev, (void *) pdev->resource[i].start);
583 }
584}
569 585
570struct zpci_dev *zpci_alloc_device(void) 586struct zpci_dev *zpci_alloc_device(void)
571{ 587{
@@ -701,25 +717,20 @@ static int __init zpci_irq_init(void)
701 goto out_alloc; 717 goto out_alloc;
702 } 718 }
703 719
704 isc_register(PCI_ISC); 720 rc = register_adapter_interrupt(&zpci_airq);
705 zpci_irq_si = s390_register_adapter_interrupt(&zpci_irq_handler, NULL, PCI_ISC); 721 if (rc)
706 if (IS_ERR(zpci_irq_si)) {
707 rc = PTR_ERR(zpci_irq_si);
708 zpci_irq_si = NULL;
709 goto out_ai; 722 goto out_ai;
710 } 723 /* Set summary to 1 to be called every time for the ISC. */
724 *zpci_airq.lsi_ptr = 1;
711 725
712 for_each_online_cpu(cpu) 726 for_each_online_cpu(cpu)
713 per_cpu(next_sbit, cpu) = 0; 727 per_cpu(next_sbit, cpu) = 0;
714 728
715 spin_lock_init(&bucket->lock); 729 spin_lock_init(&bucket->lock);
716 /* set summary to 1 to be called every time for the ISC */
717 *zpci_irq_si = 1;
718 set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC); 730 set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
719 return 0; 731 return 0;
720 732
721out_ai: 733out_ai:
722 isc_unregister(PCI_ISC);
723 free_page((unsigned long) bucket->alloc); 734 free_page((unsigned long) bucket->alloc);
724out_alloc: 735out_alloc:
725 free_page((unsigned long) bucket->aisb); 736 free_page((unsigned long) bucket->aisb);
@@ -732,21 +743,10 @@ static void zpci_irq_exit(void)
732{ 743{
733 free_page((unsigned long) bucket->alloc); 744 free_page((unsigned long) bucket->alloc);
734 free_page((unsigned long) bucket->aisb); 745 free_page((unsigned long) bucket->aisb);
735 s390_unregister_adapter_interrupt(zpci_irq_si, PCI_ISC); 746 unregister_adapter_interrupt(&zpci_airq);
736 isc_unregister(PCI_ISC);
737 kfree(bucket); 747 kfree(bucket);
738} 748}
739 749
740void zpci_debug_info(struct zpci_dev *zdev, struct seq_file *m)
741{
742 if (!zdev)
743 return;
744
745 seq_printf(m, "global irq retries: %u\n", atomic_read(&irq_retries));
746 seq_printf(m, "aibv[0]:%016lx aibv[1]:%016lx aisb:%016lx\n",
747 get_imap(0)->aibv, get_imap(1)->aibv, *bucket->aisb);
748}
749
750static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size, 750static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size,
751 unsigned long flags, int domain) 751 unsigned long flags, int domain)
752{ 752{
@@ -810,6 +810,16 @@ int pcibios_add_device(struct pci_dev *pdev)
810 return 0; 810 return 0;
811} 811}
812 812
813void pcibios_release_device(struct pci_dev *pdev)
814{
815 struct zpci_dev *zdev = get_zdev(pdev);
816
817 zpci_unmap_resources(zdev);
818 zpci_fmb_disable_device(zdev);
819 zpci_debug_exit_device(zdev);
820 zdev->pdev = NULL;
821}
822
813static int zpci_scan_bus(struct zpci_dev *zdev) 823static int zpci_scan_bus(struct zpci_dev *zdev)
814{ 824{
815 struct resource *res; 825 struct resource *res;
@@ -950,25 +960,6 @@ void zpci_stop_device(struct zpci_dev *zdev)
950} 960}
951EXPORT_SYMBOL_GPL(zpci_stop_device); 961EXPORT_SYMBOL_GPL(zpci_stop_device);
952 962
953int zpci_scan_device(struct zpci_dev *zdev)
954{
955 zdev->pdev = pci_scan_single_device(zdev->bus, ZPCI_DEVFN);
956 if (!zdev->pdev) {
957 pr_err("pci_scan_single_device failed for fid: 0x%x\n",
958 zdev->fid);
959 goto out;
960 }
961
962 pci_bus_add_devices(zdev->bus);
963
964 return 0;
965out:
966 zpci_dma_exit_device(zdev);
967 clp_disable_fh(zdev);
968 return -EIO;
969}
970EXPORT_SYMBOL_GPL(zpci_scan_device);
971
972static inline int barsize(u8 size) 963static inline int barsize(u8 size)
973{ 964{
974 return (size) ? (1 << size) >> 10 : 0; 965 return (size) ? (1 << size) >> 10 : 0;