diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 05:55:10 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 05:55:10 +0400 |
commit | 5375871d432ae9fc581014ac117b96aaee3cd0c7 (patch) | |
tree | be98e8255b0f927fb920fb532a598b93fa140dbe /arch/powerpc/sysdev/mpic.c | |
parent | b57cb7231b2ce52d3dda14a7b417ae125fb2eb97 (diff) | |
parent | dfbc2d75c1bd47c3186fa91f1655ea2f3825b0ec (diff) | |
download | linux-5375871d432ae9fc581014ac117b96aaee3cd0c7.tar.xz |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc merge from Benjamin Herrenschmidt:
"Here's the powerpc batch for this merge window. It is going to be a
bit more nasty than usual as in touching things outside of
arch/powerpc mostly due to the big iSeriesectomy :-) We finally got
rid of the bugger (legacy iSeries support) which was a PITA to
maintain and that nobody really used anymore.
Here are some of the highlights:
- Legacy iSeries is gone. Thanks Stephen ! There's still some bits
and pieces remaining if you do a grep -ir series arch/powerpc but
they are harmless and will be removed in the next few weeks
hopefully.
- The 'fadump' functionality (Firmware Assisted Dump) replaces the
previous (equivalent) "pHyp assisted dump"... it's a rewrite of a
mechanism to get the hypervisor to do crash dumps on pSeries, the
new implementation hopefully being much more reliable. Thanks
Mahesh Salgaonkar.
- The "EEH" code (pSeries PCI error handling & recovery) got a big
spring cleaning, motivated by the need to be able to implement a
new backend for it on top of some new different type of firwmare.
The work isn't complete yet, but a good chunk of the cleanups is
there. Note that this adds a field to struct device_node which is
not very nice and which Grant objects to. I will have a patch soon
that moves that to a powerpc private data structure (hopefully
before rc1) and we'll improve things further later on (hopefully
getting rid of the need for that pointer completely). Thanks Gavin
Shan.
- I dug into our exception & interrupt handling code to improve the
way we do lazy interrupt handling (and make it work properly with
"edge" triggered interrupt sources), and while at it found & fixed
a wagon of issues in those areas, including adding support for page
fault retry & fatal signals on page faults.
- Your usual random batch of small fixes & updates, including a bunch
of new embedded boards, both Freescale and APM based ones, etc..."
I fixed up some conflicts with the generalized irq-domain changes from
Grant Likely, hopefully correctly.
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (141 commits)
powerpc/ps3: Do not adjust the wrapper load address
powerpc: Remove the rest of the legacy iSeries include files
powerpc: Remove the remaining CONFIG_PPC_ISERIES pieces
init: Remove CONFIG_PPC_ISERIES
powerpc: Remove FW_FEATURE ISERIES from arch code
tty/hvc_vio: FW_FEATURE_ISERIES is no longer selectable
powerpc/spufs: Fix double unlocks
powerpc/5200: convert mpc5200 to use of_platform_populate()
powerpc/mpc5200: add options to mpc5200_defconfig
powerpc/mpc52xx: add a4m072 board support
powerpc/mpc5200: update mpc5200_defconfig to fit for charon board
Documentation/powerpc/mpc52xx.txt: Checkpatch cleanup
powerpc/44x: Add additional device support for APM821xx SoC and Bluestone board
powerpc/44x: Add support PCI-E for APM821xx SoC and Bluestone board
MAINTAINERS: Update PowerPC 4xx tree
powerpc/44x: The bug fixed support for APM821xx SoC and Bluestone board
powerpc: document the FSL MPIC message register binding
powerpc: add support for MPIC message register API
powerpc/fsl: Added aliased MSIIR register address to MSI node in dts
powerpc/85xx: mpc8548cds - add 36-bit dts
...
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 104 |
1 files changed, 55 insertions, 49 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index c83a512fa175..9ac71ebd2c40 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -873,7 +873,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type) DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", mpic, d->irq, src, flow_type); - if (src >= mpic->irq_count) + if (src >= mpic->num_sources) return -EINVAL; if (flow_type == IRQ_TYPE_NONE) @@ -909,7 +909,7 @@ void mpic_set_vector(unsigned int virq, unsigned int vector) DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n", mpic, virq, src, vector); - if (src >= mpic->irq_count) + if (src >= mpic->num_sources) return; vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); @@ -926,7 +926,7 @@ void mpic_set_destination(unsigned int virq, unsigned int cpuid) DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n", mpic, virq, src, cpuid); - if (src >= mpic->irq_count) + if (src >= mpic->num_sources) return; mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); @@ -1006,7 +1006,7 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, return 0; } - if (hw >= mpic->irq_count) + if (hw >= mpic->num_sources) return -EINVAL; mpic_msi_reserve_hwirq(mpic, hw); @@ -1149,6 +1149,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, u32 greg_feature; const char *vers; const u32 *psrc; + u32 last_irq; /* Default MPIC search parameters */ static const struct of_device_id __initconst mpic_device_id[] = { @@ -1182,6 +1183,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, } } + /* Read extra device-tree properties into the flags variable */ + if (of_get_property(node, "big-endian", NULL)) + flags |= MPIC_BIG_ENDIAN; + if (of_get_property(node, "pic-no-reset", NULL)) + flags |= MPIC_NO_RESET; + if (of_get_property(node, "single-cpu-affinity", NULL)) + flags |= MPIC_SINGLE_DEST_CPU; + if (of_device_is_compatible(node, "fsl,mpic")) + flags |= MPIC_FSL; + mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL); if (mpic == NULL) goto err_of_node_put; @@ -1189,15 +1200,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->name = name; mpic->node = node; mpic->paddr = phys_addr; + mpic->flags = flags; mpic->hc_irq = mpic_irq_chip; mpic->hc_irq.name = name; - if (!(flags & MPIC_SECONDARY)) + if (!(mpic->flags & MPIC_SECONDARY)) mpic->hc_irq.irq_set_affinity = mpic_set_affinity; #ifdef CONFIG_MPIC_U3_HT_IRQS mpic->hc_ht_irq = mpic_irq_ht_chip; mpic->hc_ht_irq.name = name; - if (!(flags & MPIC_SECONDARY)) + if (!(mpic->flags & MPIC_SECONDARY)) mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity; #endif /* CONFIG_MPIC_U3_HT_IRQS */ @@ -1209,12 +1221,9 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->hc_tm = mpic_tm_chip; mpic->hc_tm.name = name; - mpic->flags = flags; - mpic->isu_size = isu_size; - mpic->irq_count = irq_count; mpic->num_sources = 0; /* so far */ - if (flags & MPIC_LARGE_VECTORS) + if (mpic->flags & MPIC_LARGE_VECTORS) intvec_top = 2047; else intvec_top = 255; @@ -1233,12 +1242,6 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->ipi_vecs[3] = intvec_top - 1; mpic->spurious_vec = intvec_top; - /* Check for "big-endian" in device-tree */ - if (of_get_property(mpic->node, "big-endian", NULL) != NULL) - mpic->flags |= MPIC_BIG_ENDIAN; - if (of_device_is_compatible(mpic->node, "fsl,mpic")) - mpic->flags |= MPIC_FSL; - /* Look for protected sources */ psrc = of_get_property(mpic->node, "protected-sources", &psize); if (psrc) { @@ -1254,11 +1257,11 @@ struct mpic * __init mpic_alloc(struct device_node *node, } #ifdef CONFIG_MPIC_WEIRD - mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; + mpic->hw_set = mpic_infos[MPIC_GET_REGSET(mpic->flags)]; #endif /* default register type */ - if (flags & MPIC_BIG_ENDIAN) + if (mpic->flags & MPIC_BIG_ENDIAN) mpic->reg_type = mpic_access_mmio_be; else mpic->reg_type = mpic_access_mmio_le; @@ -1268,10 +1271,10 @@ struct mpic * __init mpic_alloc(struct device_node *node, * only if the kernel includes DCR support. */ #ifdef CONFIG_PPC_DCR - if (flags & MPIC_USES_DCR) + if (mpic->flags & MPIC_USES_DCR) mpic->reg_type = mpic_access_dcr; #else - BUG_ON(flags & MPIC_USES_DCR); + BUG_ON(mpic->flags & MPIC_USES_DCR); #endif /* Map the global registers */ @@ -1283,10 +1286,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* When using a device-node, reset requests are only honored if the MPIC * is allowed to reset. */ - if (of_get_property(mpic->node, "pic-no-reset", NULL)) - mpic->flags |= MPIC_NO_RESET; - - if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) { + if (!(mpic->flags & MPIC_NO_RESET)) { printk(KERN_DEBUG "mpic: Resetting\n"); mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) @@ -1297,31 +1297,17 @@ struct mpic * __init mpic_alloc(struct device_node *node, } /* CoreInt */ - if (flags & MPIC_ENABLE_COREINT) + if (mpic->flags & MPIC_ENABLE_COREINT) mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | MPIC_GREG_GCONF_COREINT); - if (flags & MPIC_ENABLE_MCK) + if (mpic->flags & MPIC_ENABLE_MCK) mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | MPIC_GREG_GCONF_MCK); /* - * Read feature register. For non-ISU MPICs, num sources as well. On - * ISU MPICs, sources are counted as ISUs are added - */ - greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); - if (isu_size == 0) { - if (flags & MPIC_BROKEN_FRR_NIRQS) - mpic->num_sources = mpic->irq_count; - else - mpic->num_sources = - ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) - >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; - } - - /* * The MPIC driver will crash if there are more cores than we * can initialize, so we may as well catch that problem here. */ @@ -1336,17 +1322,41 @@ struct mpic * __init mpic_alloc(struct device_node *node, 0x1000); } + /* + * Read feature register. For non-ISU MPICs, num sources as well. On + * ISU MPICs, sources are counted as ISUs are added + */ + greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); + + /* + * By default, the last source number comes from the MPIC, but the + * device-tree and board support code can override it on buggy hw. + * If we get passed an isu_size (multi-isu MPIC) then we use that + * as a default instead of the value read from the HW. + */ + last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) + >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT; + if (isu_size) + last_irq = isu_size * MPIC_MAX_ISU - 1; + of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq); + if (irq_count) + last_irq = irq_count - 1; + /* Initialize main ISU if none provided */ - if (mpic->isu_size == 0) { - mpic->isu_size = mpic->num_sources; + if (!isu_size) { + isu_size = last_irq + 1; + mpic->num_sources = isu_size; mpic_map(mpic, mpic->paddr, &mpic->isus[0], - MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); + MPIC_INFO(IRQ_BASE), + MPIC_INFO(IRQ_STRIDE) * isu_size); } + + mpic->isu_size = isu_size; mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); mpic->isu_mask = (1 << mpic->isu_shift) - 1; mpic->irqhost = irq_domain_add_linear(mpic->node, - isu_size ? isu_size : mpic->num_sources, + last_irq + 1, &mpic_host_ops, mpic); /* @@ -1380,7 +1390,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->next = mpics; mpics = mpic; - if (!(flags & MPIC_SECONDARY)) { + if (!(mpic->flags & MPIC_SECONDARY)) { mpic_primary = mpic; irq_set_default_host(mpic->irqhost); } @@ -1447,10 +1457,6 @@ void __init mpic_init(struct mpic *mpic) (mpic->ipi_vecs[0] + i)); } - /* Initialize interrupt sources */ - if (mpic->irq_count == 0) - mpic->irq_count = mpic->num_sources; - /* Do the HT PIC fixups on U3 broken mpic */ DBG("MPIC flags: %x\n", mpic->flags); if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) { |