lkml.org 
[lkml]   [2014]   [Aug]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[Patch v4 12/16] x86, irq, ACPI: Implement interface to support ACPI based IOAPIC hot-addition
    Date
    Implement acpi_register_ioapic() and enhance mp_register_ioapic()
    to support ACPI based IOAPIC hot-addition.

    Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
    ---
    arch/x86/kernel/acpi/boot.c | 31 +++++++++++++++++++++++++++++--
    arch/x86/kernel/apic/io_apic.c | 27 ++++++++++++++++++++++++---
    2 files changed, 53 insertions(+), 5 deletions(-)

    diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
    index e23f7460c3f8..796cd9e31ef3 100644
    --- a/arch/x86/kernel/acpi/boot.c
    +++ b/arch/x86/kernel/acpi/boot.c
    @@ -764,8 +764,35 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);

    int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
    {
    - /* TBD */
    - return -EINVAL;
    + int ret = -ENOSYS;
    +#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
    + int ioapic_id;
    + u64 addr;
    + struct ioapic_domain_cfg cfg = {
    + .type = IOAPIC_DOMAIN_DYNAMIC,
    + .ops = &acpi_irqdomain_ops,
    + };
    +
    + ioapic_id = acpi_get_ioapic_id(handle, gsi_base, &addr);
    + if (ioapic_id < 0) {
    + unsigned long long uid;
    + acpi_status status;
    +
    + status = acpi_evaluate_integer(handle, METHOD_NAME__UID,
    + NULL, &uid);
    + if (ACPI_FAILURE(status)) {
    + acpi_handle_warn(handle, "failed to get IOAPIC ID.\n");
    + return -EINVAL;
    + }
    + ioapic_id = (int)uid;
    + }
    +
    + down_write(&acpi_ioapic_rwsem);
    + ret = mp_register_ioapic(ioapic_id, phys_addr, gsi_base, &cfg);
    + up_write(&acpi_ioapic_rwsem);
    +#endif
    +
    + return ret;
    }

    EXPORT_SYMBOL(acpi_register_ioapic);
    diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
    index 6e67af0c5f99..b286461cabf9 100644
    --- a/arch/x86/kernel/apic/io_apic.c
    +++ b/arch/x86/kernel/apic/io_apic.c
    @@ -3851,7 +3851,13 @@ static int bad_ioapic_register(int idx)

    static int find_free_ioapic_entry(void)
    {
    - return nr_ioapics;
    + int idx;
    +
    + for (idx = 0; idx < MAX_IO_APICS; idx++)
    + if (ioapics[idx].nr_registers == 0)
    + return idx;
    +
    + return MAX_IO_APICS;
    }

    int mp_register_ioapic(int id, u32 address, u32 gsi_base,
    @@ -3867,8 +3873,15 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
    }
    for_each_ioapic(ioapic)
    if (ioapics[ioapic].mp_config.apicaddr == address) {
    - pr_warn("address 0x%x conflicts with IOAPIC%d\n",
    - address, ioapic);
    + /*
    + * IOAPIC unit may also be visible in PCI scope.
    + * When ioapic PCI driver's probe() is called,
    + * the IOAPIC unit may have already been initialized
    + * at boot time.
    + */
    + if (!ioapic_initialized)
    + pr_warn("address 0x%x conflicts with IOAPIC%d\n",
    + address, ioapic);
    return -EEXIST;
    }

    @@ -3918,6 +3931,14 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
    ioapics[idx].irqdomain = NULL;
    ioapics[idx].irqdomain_cfg = *cfg;

    + if (ioapic_initialized) {
    + if (mp_irqdomain_create(idx)) {
    + clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
    + return -ENOMEM;
    + }
    + alloc_ioapic_saved_registers(idx);
    + }
    +
    if (gsi_cfg->gsi_end >= gsi_top)
    gsi_top = gsi_cfg->gsi_end + 1;
    if (nr_ioapics <= idx)
    --
    1.7.10.4


    \
     
     \ /
      Last update: 2014-08-28 04:41    [W:4.023 / U:0.436 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site