diff options
Diffstat (limited to 'drivers/parisc/iosapic.c')
| -rw-r--r-- | drivers/parisc/iosapic.c | 84 |
1 files changed, 39 insertions, 45 deletions
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index e79e006eb9ab..a4011461189b 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* ** I/O Sapic Driver - PCI interrupt line support ** ** (c) Copyright 1999 Grant Grundler ** (c) Copyright 1999 Hewlett-Packard Company ** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. ** ** The I/O sapic driver manages the Interrupt Redirection Table which is ** the control logic to convert PCI line based interrupts into a Message @@ -126,21 +123,10 @@ ** o disable IRdT - call disable_irq(vector[line]->processor_irq) */ - -/* FIXME: determine which include files are really needed */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/spinlock.h> #include <linux/pci.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <asm/byteorder.h> /* get in-line asm for swab */ #include <asm/pdc.h> #include <asm/pdcpat.h> -#include <asm/page.h> -#include <asm/io.h> /* read/write functions */ #ifdef CONFIG_SUPERIO #include <asm/superio.h> #endif @@ -216,9 +202,9 @@ static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 va static DEFINE_SPINLOCK(iosapic_lock); -static inline void iosapic_eoi(void __iomem *addr, unsigned int data) +static inline void iosapic_eoi(__le32 __iomem *addr, __le32 data) { - __raw_writel(data, addr); + __raw_writel((__force u32)data, addr); } /* @@ -235,16 +221,7 @@ static size_t irt_num_entry; static struct irt_entry *iosapic_alloc_irt(int num_entries) { - unsigned long a; - - /* The IRT needs to be 8-byte aligned for the PDC call. - * Normally kmalloc would guarantee larger alignment, but - * if CONFIG_DEBUG_SLAB is enabled, then we can get only - * 4-byte alignment on 32-bit kernels - */ - a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL); - a = (a + 7UL) & ~7UL; - return (struct irt_entry *)a; + return kcalloc(num_entries, sizeof(struct irt_entry), GFP_KERNEL); } /** @@ -371,13 +348,10 @@ iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt) } - -void __init iosapic_init(void) +static int __init iosapic_init(void) { unsigned long cell = 0; - DBG("iosapic_init()\n"); - #ifdef __LP64__ if (is_pdc_pat()) { int status; @@ -394,7 +368,10 @@ void __init iosapic_init(void) irt_num_entry = iosapic_load_irt(cell, &irt_cell); if (irt_num_entry == 0) irt_cell = NULL; /* old PDC w/o iosapic */ + + return 0; } +arch_initcall(iosapic_init); /* @@ -691,7 +668,7 @@ static int iosapic_set_affinity_irq(struct irq_data *d, if (dest_cpu < 0) return -1; - cpumask_copy(d->affinity, cpumask_of(dest_cpu)); + irq_data_update_affinity(d, cpumask_of(dest_cpu)); vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu); spin_lock_irqsave(&iosapic_lock, flags); @@ -811,18 +788,28 @@ int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev) return pcidev->irq; } -static struct iosapic_info *first_isi = NULL; +static struct iosapic_info *iosapic_list; #ifdef CONFIG_64BIT -int iosapic_serial_irq(int num) +int iosapic_serial_irq(struct parisc_device *dev) { - struct iosapic_info *isi = first_isi; - struct irt_entry *irte = NULL; /* only used if PAT PDC */ + struct iosapic_info *isi; + struct irt_entry *irte; struct vector_info *vi; - int isi_line; /* line used by device */ + int cnt; + int intin; + + intin = (dev->mod_info >> 24) & 15; /* lookup IRT entry for isi/slot/pin set */ - irte = &irt_cell[num]; + for (cnt = 0; cnt < irt_num_entry; cnt++) { + irte = &irt_cell[cnt]; + if (COMPARE_IRTE_ADDR(irte, dev->mod0) && + irte->dest_iosapic_intin == intin) + break; + } + if (cnt >= irt_num_entry) + return 0; /* no irq found, force polling */ DBG_IRT("iosapic_serial_irq(): irte %p %x %x %x %x %x %x %x %x\n", irte, @@ -834,11 +821,17 @@ int iosapic_serial_irq(int num) irte->src_seg_id, irte->dest_iosapic_intin, (u32) irte->dest_iosapic_addr); - isi_line = irte->dest_iosapic_intin; + + /* search for iosapic */ + for (isi = iosapic_list; isi; isi = isi->isi_next) + if (isi->isi_hpa == dev->mod0) + break; + if (!isi) + return 0; /* no iosapic found, force polling */ /* get vector info for this input line */ - vi = isi->isi_vector + isi_line; - DBG_IRT("iosapic_serial_irq: line %d vi 0x%p\n", isi_line, vi); + vi = isi->isi_vector + intin; + DBG_IRT("iosapic_serial_irq: line %d vi 0x%p\n", iosapic_intin, vi); /* If this IRQ line has already been setup, skip it */ if (vi->irte) @@ -873,6 +866,7 @@ int iosapic_serial_irq(int num) return vi->txn_irq; } +EXPORT_SYMBOL(iosapic_serial_irq); #endif @@ -896,7 +890,7 @@ iosapic_rd_version(struct iosapic_info *isi) ** o allocate and initialize isi_vector[] ** o allocate irq region */ -void *iosapic_register(unsigned long hpa) +void *iosapic_register(unsigned long hpa, void __iomem *vaddr) { struct iosapic_info *isi = NULL; struct irt_entry *irte = irt_cell; @@ -925,7 +919,7 @@ void *iosapic_register(unsigned long hpa) return NULL; } - isi->addr = ioremap_nocache(hpa, 4096); + isi->addr = vaddr; isi->isi_hpa = hpa; isi->isi_version = iosapic_rd_version(isi); isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; @@ -941,8 +935,8 @@ void *iosapic_register(unsigned long hpa) vip->irqline = (unsigned char) cnt; vip->iosapic = isi; } - if (!first_isi) - first_isi = isi; + isi->isi_next = iosapic_list; + iosapic_list = isi; return isi; } |
