From 944239c59e93a2a76c0c0dfa473700f82572e17d Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 5 Jun 2013 16:06:16 +0200 Subject: s390/pci: implement pcibios_release_device Use pcibios_release_device to implement architecture-specific functionality when a pci device is released. This function will be called during pci_release_dev. Reviewed-by: Gerald Schaefer Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/pci/pci.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'arch/s390/pci/pci.c') diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index f1e5be85d592..a56fce445c39 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -565,7 +565,21 @@ static void zpci_map_resources(struct zpci_dev *zdev) pr_debug("BAR%i: -> start: %Lx end: %Lx\n", i, pdev->resource[i].start, pdev->resource[i].end); } -}; +} + +static void zpci_unmap_resources(struct zpci_dev *zdev) +{ + struct pci_dev *pdev = zdev->pdev; + resource_size_t len; + int i; + + for (i = 0; i < PCI_BAR_COUNT; i++) { + len = pci_resource_len(pdev, i); + if (!len) + continue; + pci_iounmap(pdev, (void *) pdev->resource[i].start); + } +} struct zpci_dev *zpci_alloc_device(void) { @@ -810,6 +824,16 @@ int pcibios_add_device(struct pci_dev *pdev) return 0; } +void pcibios_release_device(struct pci_dev *pdev) +{ + struct zpci_dev *zdev = get_zdev(pdev); + + zpci_unmap_resources(zdev); + zpci_fmb_disable_device(zdev); + zpci_debug_exit_device(zdev); + zdev->pdev = NULL; +} + static int zpci_scan_bus(struct zpci_dev *zdev) { struct resource *res; -- cgit v1.2.3 From 4bee2a5dce45096851cb8694d962bf8c016816a8 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 5 Jun 2013 16:06:42 +0200 Subject: s390/pci: cleanup hotplug code Provide wrappers for the [de]configure operations, add some error handling, and use pci_scan_slot instead of pci_scan_single_device. Reviewed-by: Gerald Schaefer Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/pci/pci.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'arch/s390/pci/pci.c') diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index a56fce445c39..628769b91b97 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -974,25 +974,6 @@ void zpci_stop_device(struct zpci_dev *zdev) } EXPORT_SYMBOL_GPL(zpci_stop_device); -int zpci_scan_device(struct zpci_dev *zdev) -{ - zdev->pdev = pci_scan_single_device(zdev->bus, ZPCI_DEVFN); - if (!zdev->pdev) { - pr_err("pci_scan_single_device failed for fid: 0x%x\n", - zdev->fid); - goto out; - } - - pci_bus_add_devices(zdev->bus); - - return 0; -out: - zpci_dma_exit_device(zdev); - clp_disable_fh(zdev); - return -EIO; -} -EXPORT_SYMBOL_GPL(zpci_scan_device); - static inline int barsize(u8 size) { return (size) ? (1 << size) >> 10 : 0; -- cgit v1.2.3 From 386aa051fb4b6298c23996e68b7c92f186e484b6 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 19 Jun 2013 14:26:46 +0200 Subject: s390/pci: remove per device debug attribute The per-pci-device 'debug' attribute is ill defined. For each device it prints the same information, the adapter interrupt bit vector for irq numbers 0 & 1, the start of the global interrupt summary vector and the global irq retries counter. Just remove the attribute and the associated code. Signed-off-by: Martin Schwidefsky --- arch/s390/pci/pci.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'arch/s390/pci/pci.c') diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 628769b91b97..51c3ca86bd05 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -85,8 +85,6 @@ static struct intr_bucket *bucket; /* Adapter local summary indicator */ static u8 *zpci_irq_si; -static atomic_t irq_retries = ATOMIC_INIT(0); - /* I/O Map */ static DEFINE_SPINLOCK(zpci_iomap_lock); static DECLARE_BITMAP(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES); @@ -452,7 +450,6 @@ scan: max = aisb_max; sbit = find_first_bit_left(bucket->aisb, max); if (sbit != max) { - atomic_inc(&irq_retries); rescan++; goto scan; } @@ -751,16 +748,6 @@ static void zpci_irq_exit(void) kfree(bucket); } -void zpci_debug_info(struct zpci_dev *zdev, struct seq_file *m) -{ - if (!zdev) - return; - - seq_printf(m, "global irq retries: %u\n", atomic_read(&irq_retries)); - seq_printf(m, "aibv[0]:%016lx aibv[1]:%016lx aisb:%016lx\n", - get_imap(0)->aibv, get_imap(1)->aibv, *bucket->aisb); -} - static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size, unsigned long flags, int domain) { -- cgit v1.2.3 From f4eae94f71372ea5ec1ba17a85f3aebedc516ca8 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 24 Jun 2013 10:30:41 +0200 Subject: s390/airq: simplify adapter interrupt code There are three users of adapter interrupts: AP, QDIO and PCI. Each registers a single adapter interrupt with independent ISCs. Define a "struct airq" with the interrupt handler, a pointer and a mask for the local summary indicator and the ISC for the adapter interrupt source. Convert the indicator array with its fixed number of adapter interrupt sources per ISE to an array of hlists. This removes the limitation to 32 adapter interrupts per ISC and allows for arbitrary memory locations for the local summary indicator. Signed-off-by: Martin Schwidefsky --- arch/s390/pci/pci.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'arch/s390/pci/pci.c') diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 51c3ca86bd05..e2956ad39a4f 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -82,8 +82,13 @@ struct intr_bucket { static struct intr_bucket *bucket; -/* Adapter local summary indicator */ -static u8 *zpci_irq_si; +/* Adapter interrupt definitions */ +static void zpci_irq_handler(struct airq_struct *airq); + +static struct airq_struct zpci_airq = { + .handler = zpci_irq_handler, + .isc = PCI_ISC, +}; /* I/O Map */ static DEFINE_SPINLOCK(zpci_iomap_lock); @@ -402,7 +407,7 @@ static struct pci_ops pci_root_ops = { /* store the last handled bit to implement fair scheduling of devices */ static DEFINE_PER_CPU(unsigned long, next_sbit); -static void zpci_irq_handler(void *dont, void *need) +static void zpci_irq_handler(struct airq_struct *airq) { unsigned long sbit, mbit, last = 0, start = __get_cpu_var(next_sbit); int rescan = 0, max = aisb_max; @@ -712,25 +717,20 @@ static int __init zpci_irq_init(void) goto out_alloc; } - isc_register(PCI_ISC); - zpci_irq_si = s390_register_adapter_interrupt(&zpci_irq_handler, NULL, PCI_ISC); - if (IS_ERR(zpci_irq_si)) { - rc = PTR_ERR(zpci_irq_si); - zpci_irq_si = NULL; + rc = register_adapter_interrupt(&zpci_airq); + if (rc) goto out_ai; - } + /* Set summary to 1 to be called every time for the ISC. */ + *zpci_airq.lsi_ptr = 1; for_each_online_cpu(cpu) per_cpu(next_sbit, cpu) = 0; spin_lock_init(&bucket->lock); - /* set summary to 1 to be called every time for the ISC */ - *zpci_irq_si = 1; set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC); return 0; out_ai: - isc_unregister(PCI_ISC); free_page((unsigned long) bucket->alloc); out_alloc: free_page((unsigned long) bucket->aisb); @@ -743,8 +743,7 @@ static void zpci_irq_exit(void) { free_page((unsigned long) bucket->alloc); free_page((unsigned long) bucket->aisb); - s390_unregister_adapter_interrupt(zpci_irq_si, PCI_ISC); - isc_unregister(PCI_ISC); + unregister_adapter_interrupt(&zpci_airq); kfree(bucket); } -- cgit v1.2.3