From patchwork Thu Aug 11 10:06:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 9274949 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0A6CC60231 for ; Thu, 11 Aug 2016 10:09:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EDBD7285E4 for ; Thu, 11 Aug 2016 10:09:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E2092285E9; Thu, 11 Aug 2016 10:09:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4F0D5285E4 for ; Thu, 11 Aug 2016 10:09:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932926AbcHKKIw (ORCPT ); Thu, 11 Aug 2016 06:08:52 -0400 Received: from mail-wm0-f48.google.com ([74.125.82.48]:36681 "EHLO mail-wm0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752672AbcHKKGs (ORCPT ); Thu, 11 Aug 2016 06:06:48 -0400 Received: by mail-wm0-f48.google.com with SMTP id q128so20114948wma.1 for ; Thu, 11 Aug 2016 03:06:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=pN/N9iuKYo7ylX6nhInzqBMepzMyeANFJZnYVqsxXd0=; b=x5vpQyS6Q3hSfrSGxd8NwaY3fTCk7jExCjBLH28dSRRDrMdWUmcOmQNPyx5Y73/abl 5ZsLmhbCHnZyqpgiMJCKK20vgUd2x0H0XL5uiyhZNnCNTJu74r1iql/4wjf/+dTTyHNk oQEXba/t9CRwNS437DcWA4Clv7f0bBZAs6QbPG/IwM1eNLGQmoxXLuYuOM1JLIibMz4N z5x3tfiHWuF/oDEk16pA2+L7jxtsM2n9g6EWGWGtui151sBEvscU6OI9sogiADik7yaK ASlj8wSJQazHDwqUQpZKHZmfYDa4w3RcsNs1i0meYfZVE9UUbsrL68TtKtLyzfQ5hh6+ t/9Q== 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=pN/N9iuKYo7ylX6nhInzqBMepzMyeANFJZnYVqsxXd0=; b=ftN1T1d2R+GKFhfRNrSCycKHzs2WCci4QDoswTv/ANVRgn3mzIH8qnaJ2uK/w05lDH bEV2IaKyAOm3XiD5Pj2EZ2x4vtUVniSIbTAe9FWteIS9NoKlZ4SbAeHwekyua3zJrUhb XANbKgNsqk1za/Jbgz13MaPwFFcr9bpj1tPobOh7A0X3At1FS8HOw6GvzjtbrPlzG0QM kMpD/+XRYpZWXMTgcwXiAsl6XWggQM2L7h6us/nIPGPss8+4AKMWCm/LKZvH7pJJ3xO6 4wqCykrK8O72yrAQcfsRjNjsShbeTjn/x7csiJctFVaqJEBwDxdb+05ukI8Yk6tfz3aG b3qw== X-Gm-Message-State: AEkooutOrMFfFbH0MvszLVOzEDpFo6rmd0Za/zud7VvrerKzVHQ/VxmUoc7KkRECVBEyyA== X-Received: by 10.25.76.137 with SMTP id z131mr1397484lfa.49.1470910006964; Thu, 11 Aug 2016 03:06:46 -0700 (PDT) Received: from tn-HP-4.semihalf.local (31-172-191-173.noc.fibertech.net.pl. [31.172.191.173]) by smtp.gmail.com with ESMTPSA id p21sm448233lfp.4.2016.08.11.03.06.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 11 Aug 2016 03:06:45 -0700 (PDT) From: Tomasz Nowicki To: marc.zyngier@arm.com, tglx@linutronix.de, jason@lakedaemon.net, rjw@rjwysocki.net, helgaas@kernel.org, rafael@kernel.org, Lorenzo.Pieralisi@arm.com Cc: will.deacon@arm.com, catalin.marinas@arm.com, hanjun.guo@linaro.org, shijie.huang@arm.com, robert.richter@caviumnetworks.com, mw@semihalf.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linaro-acpi@lists.linaro.org, andrea.gallo@linaro.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, al.stone@linaro.org, graeme.gregory@linaro.org, ddaney.cavm@gmail.com, okaya@codeaurora.org, Tomasz Nowicki Subject: [PATCH V8 2/8] ACPI: Add new IORT functions to support MSI domain handling Date: Thu, 11 Aug 2016 12:06:32 +0200 Message-Id: <1470909998-16710-3-git-send-email-tn@semihalf.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1470909998-16710-1-git-send-email-tn@semihalf.com> References: <1470909998-16710-1-git-send-email-tn@semihalf.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP For ITS, MSI functionality consists on building domain stack and during that process we need to reference to domain stack components e.g. before we create new DOMAIN_BUS_PCI_MSI domain we need to specify its DOMAIN_BUS_NEXUS parent domain. In order to manage that process properly, maintain list which elements contain domain token (unique for MSI domain stack) and ITS ID: iort_register_domain_token() and iort_deregister_domain_token(). Then retrieve domain token any time later with ITS ID being key off: iort_find_domain_token(). With domain token and domain type we are able to find corresponding IRQ domain. Since IORT is prepared to describe MSI domain on a per-device basis, use existing IORT helpers and implement two calls: 1. iort_msi_map_rid() to map MSI RID for a device 2. iort_get_device_domain() to find domain token for a device Signed-off-by: Tomasz Nowicki Reviewed-by: Hanjun Guo --- drivers/acpi/arm64/iort.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/iort.h | 11 +++ 2 files changed, 180 insertions(+) diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index f89056e..a03386d 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -22,12 +22,91 @@ #include #include +struct iort_its_msi_chip { + struct list_head list; + struct fwnode_handle *fw_node; + u32 translation_id; +}; + typedef acpi_status (*iort_find_node_callback) (struct acpi_iort_node *node, void *context); /* Root pointer to the mapped IORT table */ static struct acpi_table_header *iort_table; +static LIST_HEAD(iort_msi_chip_list); +static DEFINE_SPINLOCK(iort_msi_chip_lock); + +/** + * iort_register_domain_token() - register domain token and related ITS ID + * to the list from where we can get it back later on. + * @trans_id: ITS ID. + * @fw_node: Domain token. + * + * Returns: 0 on success, -ENOMEM if no memory when allocating list element + */ +int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node) +{ + struct iort_its_msi_chip *its_msi_chip; + + its_msi_chip = kzalloc(sizeof(*its_msi_chip), GFP_KERNEL); + if (!its_msi_chip) + return -ENOMEM; + + its_msi_chip->fw_node = fw_node; + its_msi_chip->translation_id = trans_id; + + spin_lock(&iort_msi_chip_lock); + list_add(&its_msi_chip->list, &iort_msi_chip_list); + spin_unlock(&iort_msi_chip_lock); + + return 0; +} + +/** + * iort_deregister_domain_token() - Deregister domain token based on ITS ID + * @trans_id: ITS ID. + * + * Returns: none. + */ +void iort_deregister_domain_token(int trans_id) +{ + struct iort_its_msi_chip *its_msi_chip, *t; + + spin_lock(&iort_msi_chip_lock); + list_for_each_entry_safe(its_msi_chip, t, &iort_msi_chip_list, list) { + if (its_msi_chip->translation_id == trans_id) { + list_del(&its_msi_chip->list); + kfree(its_msi_chip); + break; + } + } + spin_unlock(&iort_msi_chip_lock); +} + +/** + * iort_find_domain_token() - Find domain token based on given ITS ID + * @trans_id: ITS ID. + * + * Returns: domain token when find on the list, NULL otherwise + */ +struct fwnode_handle *iort_find_domain_token(int trans_id) +{ + struct fwnode_handle *fw_node = NULL; + struct iort_its_msi_chip *its_msi_chip; + + spin_lock(&iort_msi_chip_lock); + list_for_each_entry(its_msi_chip, &iort_msi_chip_list, list) { + if (its_msi_chip->translation_id == trans_id) { + fw_node = its_msi_chip->fw_node; + break; + } + } + spin_unlock(&iort_msi_chip_lock); + + return fw_node; +} + static struct acpi_iort_node * iort_scan_node(enum acpi_iort_node_type type, iort_find_node_callback callback, void *context) @@ -206,6 +285,96 @@ iort_find_dev_node(struct device *dev) iort_match_node_callback, &pbus->dev); } +/** + * iort_msi_map_rid() - Map a MSI requester ID for a device + * @dev: The device for which the mapping is to be done. + * @req_id: The device requester ID. + * + * Returns: mapped MSI RID on success, input requester ID otherwise + */ +u32 iort_msi_map_rid(struct device *dev, u32 req_id) +{ + struct acpi_iort_node *node; + u32 dev_id; + + if (!iort_table) + return req_id; + + node = iort_find_dev_node(dev); + if (!node) { + dev_err(dev, "can't find related IORT node\n"); + return req_id; + } + + iort_node_map_rid(node, req_id, &dev_id, ACPI_IORT_NODE_ITS_GROUP); + return dev_id; +} + +/** + * iort_dev_find_its_id() - Find the ITS identifier for a device + * @dev: The device. + * @idx: Index of the ITS identifier list. + * @its_id: ITS identifier. + * + * Returns: 0 on success, appropriate error value otherwise + */ +static int +iort_dev_find_its_id(struct device *dev, u32 req_id, unsigned int idx, + int *its_id) +{ + struct acpi_iort_its_group *its; + struct acpi_iort_node *node; + + node = iort_find_dev_node(dev); + if (!node) { + dev_err(dev, "can't find related IORT node\n"); + return -ENXIO; + } + + node = iort_node_map_rid(node, req_id, NULL, ACPI_IORT_NODE_ITS_GROUP); + if (!node) { + dev_err(dev, "can't find related ITS node\n"); + return -ENXIO; + } + + /* Move to ITS specific data */ + its = (struct acpi_iort_its_group *)node->node_data; + if (idx > its->its_count) { + dev_err(dev, "requested ITS ID index [%d] is greater than available [%d]\n", + idx, its->its_count); + return -ENXIO; + } + + *its_id = its->identifiers[idx]; + return 0; +} + +/** + * iort_get_device_domain() - Find MSI domain related to a device + * @dev: The device. + * @req_id: Requester ID for the device. + * + * Returns: the MSI domain for this device, NULL otherwise + */ +struct irq_domain * +iort_get_device_domain(struct device *dev, u32 req_id) +{ + static struct fwnode_handle *handle; + int its_id; + + if (!iort_table) + return NULL; + + if (iort_dev_find_its_id(dev, req_id, 0, &its_id)) + return NULL; + + handle = iort_find_domain_token(its_id); + if (!handle) + return NULL; + + return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI); +} + void __init iort_table_detect(void) { acpi_status status; diff --git a/include/linux/iort.h b/include/linux/iort.h index cde6809..d7daba1 100644 --- a/include/linux/iort.h +++ b/include/linux/iort.h @@ -20,11 +20,22 @@ #define __IORT_H__ #include +#include +#include +int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node); +void iort_deregister_domain_token(int trans_id); +struct fwnode_handle *iort_find_domain_token(int trans_id); #ifdef CONFIG_IORT_TABLE void iort_table_detect(void); +u32 iort_msi_map_rid(struct device *dev, u32 req_id); +struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id); #else static inline void iort_table_detect(void) { } +static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id) +{ return req_id; } +static inline struct irq_domain * +iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; } #endif #endif /* __IORT_H__ */