From patchwork Wed Jul 29 10:08:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanjun Guo X-Patchwork-Id: 6891911 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6EABBC05AC for ; Wed, 29 Jul 2015 10:14:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5784A207AE for ; Wed, 29 Jul 2015 10:14:15 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2FB67207A9 for ; Wed, 29 Jul 2015 10:14:14 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZKOLZ-0002l4-Lm; Wed, 29 Jul 2015 10:12:25 +0000 Received: from mail-pd0-f175.google.com ([209.85.192.175]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZKOKG-0001Cp-Ob for linux-arm-kernel@lists.infradead.org; Wed, 29 Jul 2015 10:11:06 +0000 Received: by pdbbh15 with SMTP id bh15so3530619pdb.1 for ; Wed, 29 Jul 2015 03:10:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=iSIObropjCII9BWAFs8FmRyPrm7oDbe26MywcVabucs=; b=DmR5UKFyFdcFm4dcR5TY1zcDzafAahCAGXIoWXQXDg6xZVLuh4kIKFODfL0CIIRerL FYdFTkt8E1CpkRamvfxBmHjscxLy1WDZNb92liN2qbzgtHYjElhbeDpyi30O+JhIQoe8 YYgXEAoYIrwwddYcac9iRy0wxpSz9Or0H6U0pDDk900jnw470sOJfdRXZ64BVG7FcECs mPZ6Gedpn5R4bBfAM2PcwFL70jUdjIu481dXAoVXwNf7kaQVjGIisFT0Y9wPf09AcXPB zIgCZjXr5VtsED50Lo4eqEw3r+xu+P9D/96UyyTQfsKaBV8t/PAATxqRKHVI7mQf4EiJ yn5A== X-Gm-Message-State: ALoCoQmZjLAvDxn5aoBe69hsDd0bThXTNQSK1fnMW3QhiV4DFo1e4WbJd53gp/DrOxCLqaTTfU3a X-Received: by 10.70.0.71 with SMTP id 7mr91807425pdc.157.1438164644400; Wed, 29 Jul 2015 03:10:44 -0700 (PDT) Received: from localhost ([180.150.157.4]) by smtp.googlemail.com with ESMTPSA id oi17sm39815178pdb.74.2015.07.29.03.10.42 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Wed, 29 Jul 2015 03:10:43 -0700 (PDT) From: Hanjun Guo To: Marc Zyngier , Jason Cooper , Will Deacon , Catalin Marinas , "Rafael J. Wysocki" Subject: [PATCH v4 08/10] ACPI: GIC: Add ACPI helper functions to query irq-domain tokens for for GIC MSI and ITS Date: Wed, 29 Jul 2015 18:08:57 +0800 Message-Id: <1438164539-29256-9-git-send-email-hanjun.guo@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1438164539-29256-1-git-send-email-hanjun.guo@linaro.org> References: <1438164539-29256-1-git-send-email-hanjun.guo@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150729_031104_912097_2BE01F9B X-CRM114-Status: GOOD ( 26.44 ) X-Spam-Score: -2.6 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Wei Huang , Lorenzo Pieralisi , linux-acpi@vger.kernel.org, Timur Tabi , linaro-acpi@lists.linaro.org, linux-kernel@vger.kernel.org, Tomasz Nowicki , Grant Likely , Mark Brown , Hanjun Guo , Suravee Suthikulpanit , Bjorn Helgaas , Thomas Gleixner , Jiang Liu , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Suravee Suthikulpanit This patch introduces acpi_gic_get_msi_token(), which returns irq-domain token that can be used to look up MSI doamin of a device. In both GIC MSI and ITS cases, the base_address specified in the GIC MSI or GIC ITS structure is used as a token for MSI domain. In addition, this patch also provides low-level helper functions to parse and query GIC MSI structure and GIC ITS from MADT. Once parsed, it keeps a copy of the structure for use in subsequent queries to avoid having to map and parse MADT multiple times. Signed-off-by: Suravee Suthikulpanit Signed-off-by: Hanjun Guo --- drivers/acpi/Makefile | 1 + drivers/acpi/acpi_gic.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_gic.h | 23 +++++ include/linux/acpi.h | 1 + 4 files changed, 259 insertions(+) create mode 100644 drivers/acpi/acpi_gic.c create mode 100644 include/acpi/acpi_gic.h diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 8321430..def54b9 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -54,6 +54,7 @@ acpi-$(CONFIG_ACPI_NUMA) += numa.o acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o acpi-y += acpi_lpat.o acpi-$(CONFIG_ACPI_GENERIC_GSI) += gsi.o +acpi-$(CONFIG_ARM_GIC_ACPI) += acpi_gic.o # These are (potentially) separate modules diff --git a/drivers/acpi/acpi_gic.c b/drivers/acpi/acpi_gic.c new file mode 100644 index 0000000..11ee4eb --- /dev/null +++ b/drivers/acpi/acpi_gic.c @@ -0,0 +1,234 @@ +/* + * File: acpi_gic.c + * + * ACPI helper functions for ARM GIC + * + * Copyright (C) 2015 Advanced Micro Devices, Inc. + * Authors: Suravee Suthikulpanit + */ + +#include +#include + +/* + * GIC MSI Frame data structures + */ +struct gic_msi_frame_handle { + struct list_head list; + struct acpi_madt_generic_msi_frame frame; +}; + +static LIST_HEAD(msi_frame_list); + +static int acpi_num_msi; + +/* + * GIC ITS data structures + */ +struct gic_its_handle { + struct list_head list; + struct acpi_madt_generic_translator trans; +}; + +static LIST_HEAD(its_list); + +static int acpi_num_its; + +/* + * GIC MSI Frame parsing stuff + */ +inline int acpi_gic_get_num_msi_frame(void) +{ + return acpi_num_msi; +} + +static int __init +acpi_parse_madt_msi(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct gic_msi_frame_handle *h; + struct acpi_madt_generic_msi_frame *frame; + + frame = (struct acpi_madt_generic_msi_frame *)header; + if (BAD_MADT_ENTRY(frame, end)) + return -EINVAL; + + h = kzalloc(sizeof(struct gic_msi_frame_handle *), GFP_KERNEL); + if (!h) + return -ENOMEM; + + /** Note: + * We make a copy of this structure since this code is called + * prior to acpi_early_init(), which sets the acpi_gbl_permanent_mmap. + * Therefore, we could not keep just the pointer sincce the memory + * could be unmapped. + */ + memcpy(&h->frame, frame, sizeof(struct acpi_madt_generic_msi_frame)); + + list_add(&h->list, &msi_frame_list); + + return 0; +} + +int __init acpi_gic_msi_init(struct acpi_table_header *table) +{ + int ret = 0; + + if (acpi_num_msi > 0) + return ret; + + ret = acpi_parse_entries(ACPI_SIG_MADT, + sizeof(struct acpi_table_madt), + acpi_parse_madt_msi, table, + ACPI_MADT_TYPE_GENERIC_MSI_FRAME, 0); + if (ret == 0) { + pr_debug("No valid ACPI GIC MSI FRAME exist\n"); + return ret; + } + + acpi_num_msi = ret; + return 0; +} + +int acpi_gic_get_msi_frame(int index, struct acpi_madt_generic_msi_frame **p) +{ + int i = 0; + struct gic_msi_frame_handle *m; + + if (index >= acpi_num_msi) + return -EINVAL; + + list_for_each_entry(m, &msi_frame_list, list) { + if (i == index) + break; + i++; + } + + if (i == acpi_num_msi) + return -EINVAL; + + *p = &(m->frame); + return 0; +} + +/* + * GIC ITS parsing stuff + */ +inline int acpi_gic_get_num_its(void) +{ + return acpi_num_its; +} + +static int __init +acpi_parse_madt_its(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct gic_its_handle *h; + struct acpi_madt_generic_translator *trans; + + trans = (struct acpi_madt_generic_translator *)header; + if (BAD_MADT_ENTRY(trans, end)) + return -EINVAL; + + h = kzalloc(sizeof(struct gic_its_handle *), GFP_KERNEL); + if (!h) + return -ENOMEM; + + memcpy(&h->trans, trans, sizeof(struct acpi_madt_generic_translator)); + + list_add(&h->list, &its_list); + + return 0; +} + +int __init acpi_gic_madt_gic_its_init(struct acpi_table_header *table) +{ + int ret = 0; + + if (acpi_num_its > 0) + return ret; + + ret = acpi_parse_entries(ACPI_SIG_MADT, + sizeof(struct acpi_table_madt), + acpi_parse_madt_its, table, + ACPI_MADT_TYPE_GENERIC_TRANSLATOR, 0); + if (ret == 0) { + pr_debug("No valid ACPI GIC ITS exist\n"); + return ret; + } + + acpi_num_its = ret; + return 0; +} + +int acpi_gic_get_its(int index, struct acpi_madt_generic_translator **p) +{ + int i = 0; + struct gic_its_handle *m; + + if (index >= acpi_num_its) + return -EINVAL; + + list_for_each_entry(m, &its_list, list) { + if (i == index) + break; + i++; + } + + if (i == acpi_num_its) + return -EINVAL; + + *p = &(m->trans); + return 0; +} + +static void *acpi_gic_msi_token(struct device *dev) +{ + int err; + struct acpi_madt_generic_msi_frame *msi; + + /** + * Since ACPI 5.1 currently does not define + * a way to associate MSI frame ID to a device, + * we can only support single MSI frame (index 0) + * at the moment. + */ + err = acpi_gic_get_msi_frame(0, &msi); + if (err) + return NULL; + + return (void *) msi->base_address; +} + +static void *acpi_gic_its_token(struct device *dev) +{ + int err; + struct acpi_madt_generic_translator *trans; + int its_id = 0; + + /** + * TODO: We need a way to retrieve GIC ITS ID from + * struct device pointer (in this case, the device + * would be the PCI host controller. + * + * This would be done by the IORT-related code. + * + * its_id = get_its_id(dev); + */ + + err = acpi_gic_get_its(its_id, &trans); + if (err) + return NULL; + + return (void *) trans->base_address; +} + +void *acpi_gic_get_msi_token(struct device *dev) +{ + void *token = acpi_gic_msi_token(dev); + + if (!token) + token = acpi_gic_its_token(dev); + + return token; +} diff --git a/include/acpi/acpi_gic.h b/include/acpi/acpi_gic.h new file mode 100644 index 0000000..34fa475 --- /dev/null +++ b/include/acpi/acpi_gic.h @@ -0,0 +1,23 @@ +/* + * include/acpi/acpi_gic.h + * + * Copyright (C) 2015 Advanced Micro Devices, Inc. + * Authors: Suravee Suthikulpanit + */ + +#ifndef __ACPI_GIC_H__ +#define __ACPI_GIC_H__ + +#ifdef CONFIG_ACPI +int acpi_gic_get_num_msi_frame(void); +int acpi_gic_msi_init(struct acpi_table_header *table); +int acpi_gic_get_msi_frame(int index, struct acpi_madt_generic_msi_frame **p); + +int acpi_gic_get_num_its(void); +int acpi_gic_its_init(struct acpi_table_header *table); +int acpi_gic_get_its(int index, struct acpi_madt_generic_translator **p); + +void *acpi_gic_get_msi_token(struct device *dev); +#endif + +#endif /*__ACPI_GIC_H__*/ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 04dd0bb..5d58b61 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -44,6 +44,7 @@ #include #include +#include #include #include #include