diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2016-08-09 16:38:05 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-08-11 19:54:22 +1000 |
commit | 8b6d05d9b2cd187e05ff0aa27942f07d04c8d4d6 (patch) | |
tree | 5a3dad0ac8c8fcdb0f72d9a2b82ff51af0e0fdb5 /hw/psi.c | |
parent | c6a6391892539450a84d3dd69f4d83ea1a1b04d6 (diff) | |
download | skiboot-8b6d05d9b2cd187e05ff0aa27942f07d04c8d4d6.zip skiboot-8b6d05d9b2cd187e05ff0aa27942f07d04c8d4d6.tar.gz skiboot-8b6d05d9b2cd187e05ff0aa27942f07d04c8d4d6.tar.bz2 |
interrupts: Add new source ->attributes callback
This allows a given source to provide per-interrupt attributes
such as whether it targets OPAL or Linux and it's estimated
frequency.
The former allows to get rid of the double set of ops used to
decide which interrupts go where on some modules like the PHBs
and the latter will be eventually used to implement smart
caching of the source lookups.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/psi.c')
-rw-r--r-- | hw/psi.c | 51 |
1 files changed, 27 insertions, 24 deletions
@@ -432,6 +432,12 @@ static int64_t psi_p7_get_xive(struct irq_source *is, uint32_t isn __unused, return OPAL_SUCCESS; } +static uint64_t psi_p7_irq_attributes(struct irq_source *is __unused, + uint32_t isn __unused) +{ + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_FREQUENT; +} + static int64_t psi_p8_set_xive(struct irq_source *is, uint32_t isn, uint16_t server, uint8_t priority) { @@ -509,6 +515,23 @@ static int64_t psi_p8_get_xive(struct irq_source *is, uint32_t isn __unused, return OPAL_SUCCESS; } +static uint64_t psi_p8_irq_attributes(struct irq_source *is, uint32_t isn) +{ + struct psi *psi = is->data; + uint32_t idx = isn - psi->interrupt; + uint64_t attr; + + if (idx == P8_IRQ_PSI_HOST_ERR && + psi_ext_irq_policy == EXTERNAL_IRQ_POLICY_LINUX) + return IRQ_ATTR_TARGET_LINUX; + + attr = IRQ_ATTR_TARGET_OPAL; + if (idx == P8_IRQ_PSI_HOST_ERR || idx == P8_IRQ_PSI_LPC || + idx == P8_IRQ_PSI_FSP) + attr |= IRQ_ATTR_TARGET_FREQUENT; + return attr; +} + /* Called on a fast reset, make sure we aren't stuck with * an accepted and never EOId PSI interrupt */ @@ -542,20 +565,17 @@ void psi_irq_reset(void) static const struct irq_source_ops psi_p7_irq_ops = { .get_xive = psi_p7_get_xive, .set_xive = psi_p7_set_xive, + .attributes = psi_p7_irq_attributes, .interrupt = psi_interrupt, }; static const struct irq_source_ops psi_p8_irq_ops = { .get_xive = psi_p8_get_xive, .set_xive = psi_p8_set_xive, + .attributes = psi_p8_irq_attributes, .interrupt = psi_interrupt, }; -static const struct irq_source_ops psi_p8_host_err_ops = { - .get_xive = psi_p8_get_xive, - .set_xive = psi_p8_set_xive, -}; - static void psi_tce_enable(struct psi *psi, bool enable) { void *addr; @@ -693,25 +713,8 @@ static void psi_register_interrupts(struct psi *psi) * external interrupt and the policy for that comes * from the platform */ - if (psi_ext_irq_policy == EXTERNAL_IRQ_POLICY_SKIBOOT) { - register_irq_source(&psi_p8_irq_ops, - psi, - psi->interrupt + P8_IRQ_PSI_SKIBOOT_BASE, - P8_IRQ_PSI_ALL_COUNT); - } else { - register_irq_source(&psi_p8_irq_ops, - psi, - psi->interrupt + P8_IRQ_PSI_SKIBOOT_BASE, - P8_IRQ_PSI_LOCAL_COUNT); - /* - * Host Error is handled by powernv; host error - * is at offset 5 from the PSI base. - */ - register_irq_source(&psi_p8_host_err_ops, - psi, - psi->interrupt + P8_IRQ_PSI_LINUX_BASE, - P8_IRQ_PSI_LINUX_COUNT); - } + register_irq_source(&psi_p8_irq_ops, psi, + psi->interrupt, P8_IRQ_PSI_IRQ_COUNT); break; default: /* Unknown: just no interrupts */ |