diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-09-10 17:36:07 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-09-12 22:52:08 -0500 |
commit | 291d58000b96d39576e4736af939b3ec29e00b88 (patch) | |
tree | e9cd3425706486d763367ab46c7a139a1f614391 /hw | |
parent | a87db66d0a9449a8a30a566cd1de7d5465036287 (diff) | |
download | skiboot-291d58000b96d39576e4736af939b3ec29e00b88.zip skiboot-291d58000b96d39576e4736af939b3ec29e00b88.tar.gz skiboot-291d58000b96d39576e4736af939b3ec29e00b88.tar.bz2 |
xive: Make opal_xive_allocate_irq() properly try all chips
When requested via OPAL_XIVE_ANY_CHIP, we need to try all
chips. We first try the current one (on which the caller
sits) and if that fails, we iterate all chips until the
allocation succeeds.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xive.c | 54 |
1 files changed, 37 insertions, 17 deletions
@@ -4592,27 +4592,11 @@ static int64_t opal_xive_alloc_vp_block(uint32_t alloc_order) return rc; } -static int64_t opal_xive_allocate_irq(uint32_t chip_id) +static int64_t xive_try_allocate_irq(struct xive *x) { - struct proc_chip *chip; int idx, base_idx, max_count, girq; struct xive_ive *ive; - struct xive *x; - - if (xive_mode != XIVE_MODE_EXPL) - return OPAL_WRONG_STATE; - /* XXX Make this try multiple chips ... */ - if (chip_id == OPAL_XIVE_ANY_CHIP) - chip_id = this_cpu()->chip_id; - - chip = get_chip(chip_id); - if (!chip) - return OPAL_PARAMETER; - if (!chip->xive) - return OPAL_PARAMETER; - - x = chip->xive; lock(&x->lock); base_idx = x->int_ipi_top - x->int_base; @@ -4642,6 +4626,42 @@ static int64_t opal_xive_allocate_irq(uint32_t chip_id) return girq; } +static int64_t opal_xive_allocate_irq(uint32_t chip_id) +{ + struct proc_chip *chip; + bool try_all = false; + int64_t rc; + + if (xive_mode != XIVE_MODE_EXPL) + return OPAL_WRONG_STATE; + + if (chip_id == OPAL_XIVE_ANY_CHIP) { + try_all = true; + chip_id = this_cpu()->chip_id; + } + chip = get_chip(chip_id); + if (!chip) + return OPAL_PARAMETER; + + /* Try initial target chip */ + if (!chip->xive) + rc = OPAL_PARAMETER; + else + rc = xive_try_allocate_irq(chip->xive); + if (rc >= 0 || !try_all) + return rc; + + /* Failed and we try all... do so */ + for_each_chip(chip) { + if (!chip->xive) + continue; + rc = xive_try_allocate_irq(chip->xive); + if (rc >= 0) + break; + } + return rc; +} + static int64_t opal_xive_free_irq(uint32_t girq) { struct irq_source *is = irq_find_source(girq); |