From patchwork Fri Nov 22 10:49:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 180007 Delivered-To: patch@linaro.org Received: by 2002:a92:38d5:0:0:0:0:0 with SMTP id g82csp40786ilf; Fri, 22 Nov 2019 02:57:16 -0800 (PST) X-Google-Smtp-Source: APXvYqx+8NRwg8NOo9wFmd50Zdm0AsM4XF7AXl9DwQuSytq4AuwR7M2olP68IfxWwgQStZ2E2Trk X-Received: by 2002:a05:6402:13cd:: with SMTP id a13mr253971edx.57.1574419865547; Fri, 22 Nov 2019 02:51:05 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574419865; cv=none; d=google.com; s=arc-20160816; b=eVEqw91Vw3zFk71DCppBqFtVCAEM9enHmax2CJWf730Jz8jzyWGfRYhJ6TSLC+/Ywe slwcTJMeM8smBoLiBZR6jaNGNz1Xu8t8PkwxG2QloVnU/2HAmQA8zSAqEAA6+DGeUPxQ InDEFjsWWYPEw7dGsCznXvg0li3rGkZKCSHfDEfpTRlxjjTFByfQyr2nTMflBHsebGvP s613tlOeM+fYSVCtkJwtvUqqwTxvgzkKQuQq3bRGYdoVRNqmhrcWateeOw83ZmQSnB9M 86m1UWoveekeR7aO1jR+k6RiejUw1l5jmz4hlBMda3DZVrY9eYSjc/PbwB6gktz/xVwL YdXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=A1h5FjHSoFWza4c7kQCG4diNrL6ym0OIuM4Ss4lynM4=; b=GbP+TMRHnHLE8y4TbpA0VnQ7nusdHmtr9FU/1CBuvbSOc/w+MCI/VIwcNBNheg/51T XK2PsjCWDvDEpDUvTN2+naB6iLl9n3hY+Ngm2rdoS5h/WqVjYQTD6zKuCMCUXHdwVhx+ QxIbMHBr3B5FieCr9beJnXmvDWxWB2hWXGvoVEP/fclGhLt42KjxvY/qVcvpmhDqIpXy hQNZ4cvilw0WkZH3nOlBDQ6d1ZyqsrXfs+tsvaDOv5SMDQv0Sr+HuQuvS55+CZGk3Dv9 knHwjWq/CLygU4TanENF6urk6yk3sUZoy3RSdtLq7StpMUUzII0iq7l21htvmOKCVpM6 mNRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bAqX72LI; spf=pass (google.com: best guess record for domain of linux-acpi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-acpi-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id um2si3764583ejb.64.2019.11.22.02.51.04; Fri, 22 Nov 2019 02:51:05 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-acpi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bAqX72LI; spf=pass (google.com: best guess record for domain of linux-acpi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-acpi-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729474AbfKVKvB (ORCPT + 7 others); Fri, 22 Nov 2019 05:51:01 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:33784 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729471AbfKVKvA (ORCPT ); Fri, 22 Nov 2019 05:51:00 -0500 Received: by mail-wm1-f68.google.com with SMTP id t26so6008637wmi.0 for ; Fri, 22 Nov 2019 02:50:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=A1h5FjHSoFWza4c7kQCG4diNrL6ym0OIuM4Ss4lynM4=; b=bAqX72LIDtPtMJeGcUhtez0KLSm3flrmYHny6W5WMhZW2tBjcEjLpecXs8daLtPL+u gIyq0KG407aqOZvr8HCFfx2NxejbVRv+DXKSXLx1CmdcZvWAq2wuqlUIJFsCWwnqVj0z FNPNz0je2zOTjhgcT7Rskv72VmKDs3V7INAXyNn62BSM84iWNxGhohaR8+szZkJBwjXz gdfG/SnuAB8CMKbpfQ2N8du37PEiZ833hhE67RGgFzExhMx9eL1NmwtFVa7X0wbDMWv4 I3LJsTClmFHCo6nmwPzWtZwPa8AoFWIvUaQZg04i4FPj5mGi2bRHYO6iQf1hiWBEEDVY 8C7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=A1h5FjHSoFWza4c7kQCG4diNrL6ym0OIuM4Ss4lynM4=; b=lhaxGlc2qdgbmFMfOnBUkN4WLUFgWP1jZqjxUOfOyrJVOxOvKprG2dNIoKq8RCdQgf liTaYGUIaPp0cR23Jl8g7zvhVpJwouuU+gmKCRBn2LwncZHEYjFJAQd6pu/Fu6ERdFid FlN60ziuR8y4xaB20uDwDM04BbNjJMhvw8Bcqh/TmuT0Ubl56COkmhq2WD2oLwIirr5H Yiqm6x0/5W+NPMEvi9CyxZ3pNEVBS8bm5g6IUrOOgTaPxgs5um588uJNLckMAD7Xb8A9 rbbuAtClUMrjzQa3cN7CnpAXSqomyhFCKqO46akTZj4lQsJaEZkHc/PRspz+EOeswW98 Th5w== X-Gm-Message-State: APjAAAUF6ucjrkzcTRq8qYZlYg1qZJasOIxG4zVXz84mIkaZlHqff8oB Seg9nMypujtNO4nMWLEIEWIelrKAhbw= X-Received: by 2002:a1c:4b18:: with SMTP id y24mr15475854wma.71.1574419858922; Fri, 22 Nov 2019 02:50:58 -0800 (PST) Received: from localhost.localdomain (xdsl-188-155-204-106.adslplus.ch. [188.155.204.106]) by smtp.gmail.com with ESMTPSA id o133sm2088197wmb.4.2019.11.22.02.50.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Nov 2019 02:50:58 -0800 (PST) From: Jean-Philippe Brucker To: linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, iommu@lists.linux-foundation.org, virtualization@lists.linux-foundation.org, linux-pci@vger.kernel.org, virtio-dev@lists.oasis-open.org Cc: rjw@rjwysocki.net, lenb@kernel.org, lorenzo.pieralisi@arm.com, guohanjun@huawei.com, sudeep.holla@arm.com, gregkh@linuxfoundation.org, joro@8bytes.org, bhelgaas@google.com, mst@redhat.com, jasowang@redhat.com, jacob.jun.pan@intel.com, eric.auger@redhat.com, sebastien.boeuf@intel.com, kevin.tian@intel.com Subject: [RFC 06/13] ACPI/IORT: Support VIOT virtio-pci node Date: Fri, 22 Nov 2019 11:49:53 +0100 Message-Id: <20191122105000.800410-7-jean-philippe@linaro.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191122105000.800410-1-jean-philippe@linaro.org> References: <20191122105000.800410-1-jean-philippe@linaro.org> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org When virtio-iommu uses the PCI transport, IORT doesn't instantiate the device and doesn't create a fwnode. They will be created later by the PCI subsystem. Store the information needed to identify the IOMMU in iort_fwnode_list. Signed-off-by: Jean-Philippe Brucker --- drivers/acpi/iort.c | 117 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 24 deletions(-) -- 2.24.0 diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c index adc5953fffa5..b517aa4e83ba 100644 --- a/drivers/acpi/iort.c +++ b/drivers/acpi/iort.c @@ -30,10 +30,17 @@ struct iort_its_msi_chip { u32 translation_id; }; +struct iort_pci_devid { + u16 segment; + u8 bus; + u8 devfn; +}; + struct iort_fwnode { struct list_head list; struct acpi_iort_node *iort_node; struct fwnode_handle *fwnode; + struct iort_pci_devid *pci_devid; }; static LIST_HEAD(iort_fwnode_list); static DEFINE_SPINLOCK(iort_fwnode_lock); @@ -44,7 +51,8 @@ static bool iort_type_matches(u8 type, enum iort_node_category category) case IORT_IOMMU_TYPE: return type == ACPI_IORT_NODE_SMMU || type == ACPI_IORT_NODE_SMMU_V3 || - type == ACPI_VIOT_IORT_NODE_VIRTIO_MMIO_IOMMU; + type == ACPI_VIOT_IORT_NODE_VIRTIO_MMIO_IOMMU || + type == ACPI_VIOT_IORT_NODE_VIRTIO_PCI_IOMMU; case IORT_MSI_TYPE: return type == ACPI_IORT_NODE_ITS_GROUP; default: @@ -59,12 +67,14 @@ static bool iort_type_matches(u8 type, enum iort_node_category category) * * @node: IORT table node associated with the IOMMU * @fwnode: fwnode associated with the IORT node + * @pci_devid: pci device ID associated with the IORT node, may be NULL * * Returns: 0 on success * <0 on failure */ static inline int iort_set_fwnode(struct acpi_iort_node *iort_node, - struct fwnode_handle *fwnode) + struct fwnode_handle *fwnode, + struct iort_pci_devid *pci_devid) { struct iort_fwnode *np; @@ -76,6 +86,7 @@ static inline int iort_set_fwnode(struct acpi_iort_node *iort_node, INIT_LIST_HEAD(&np->list); np->iort_node = iort_node; np->fwnode = fwnode; + np->pci_devid = pci_devid; spin_lock(&iort_fwnode_lock); list_add_tail(&np->list, &iort_fwnode_list); @@ -121,6 +132,7 @@ static inline void iort_delete_fwnode(struct acpi_iort_node *node) spin_lock(&iort_fwnode_lock); list_for_each_entry_safe(curr, tmp, &iort_fwnode_list, list) { if (curr->iort_node == node) { + kfree(curr->pci_devid); list_del(&curr->list); kfree(curr); break; @@ -870,6 +882,7 @@ static inline bool iort_iommu_driver_enabled(u8 type) case ACPI_IORT_NODE_SMMU: return IS_BUILTIN(CONFIG_ARM_SMMU); case ACPI_VIOT_IORT_NODE_VIRTIO_MMIO_IOMMU: + case ACPI_VIOT_IORT_NODE_VIRTIO_PCI_IOMMU: return IS_ENABLED(CONFIG_VIRTIO_IOMMU); default: pr_warn("IORT node type %u does not describe an IOMMU\n", type); @@ -1451,6 +1464,28 @@ static void __init viommu_mmio_dma_configure(struct device *dev, acpi_dma_configure(dev, attr); } +static __init struct iort_pci_devid * +viommu_pci_get_devid(struct acpi_iort_node *node) +{ + unsigned int val; + struct iort_pci_devid *devid; + struct acpi_viot_iort_virtio_pci_iommu *viommu; + + viommu = (struct acpi_viot_iort_virtio_pci_iommu *)node->node_data; + + val = le32_to_cpu(viommu->devid); + + devid = kzalloc(sizeof(*devid), GFP_KERNEL); + if (!devid) + return ERR_PTR(-ENOMEM); + + devid->segment = val >> 16; + devid->bus = PCI_BUS_NUM(val); + devid->devfn = val & 0xff; + + return devid; +} + struct iort_dev_config { const char *name; int (*dev_init)(struct acpi_iort_node *node); @@ -1462,6 +1497,7 @@ struct iort_dev_config { int (*dev_set_proximity)(struct device *dev, struct acpi_iort_node *node); int (*dev_add_platdata)(struct platform_device *pdev); + struct iort_pci_devid *(*dev_get_pci_devid)(struct acpi_iort_node *node); }; static const struct iort_dev_config iort_arm_smmu_v3_cfg __initconst = { @@ -1494,6 +1530,10 @@ static const struct iort_dev_config iort_viommu_mmio_cfg __initconst = { .dev_init_resources = viommu_mmio_init_resources, }; +static const struct iort_dev_config iort_viommu_pci_cfg __initconst = { + .dev_get_pci_devid = viommu_pci_get_devid, +}; + static __init const struct iort_dev_config *iort_get_dev_cfg( struct acpi_iort_node *node) { @@ -1510,6 +1550,8 @@ static __init const struct iort_dev_config *iort_get_dev_cfg( switch (node->type) { case ACPI_VIOT_IORT_NODE_VIRTIO_MMIO_IOMMU: return &iort_viommu_mmio_cfg; + case ACPI_VIOT_IORT_NODE_VIRTIO_PCI_IOMMU: + return &iort_viommu_pci_cfg; } } @@ -1641,13 +1683,55 @@ static void __init iort_enable_acs(struct acpi_iort_node *iort_node) static inline void iort_enable_acs(struct acpi_iort_node *iort_node) { } #endif -static void __init iort_init_platform_devices(void) +static int __init iort_init_node(struct acpi_iort_node *iort_node) +{ + int ret; + const struct iort_dev_config *ops; + struct fwnode_handle *fwnode; + + iort_enable_acs(iort_node); + + ops = iort_get_dev_cfg(iort_node); + if (!ops) + return 0; + + if (ops->dev_get_pci_devid) { + struct iort_pci_devid *pci_devid = + ops->dev_get_pci_devid(iort_node); + + if (IS_ERR(pci_devid)) + return PTR_ERR(pci_devid); + /* + * For a PCI-based IOMMU, set the pci_devid handle now, but + * leave the fwnode empty. It will be completed later when the + * PCI device gets probed. + */ + iort_set_fwnode(iort_node, NULL, pci_devid); + + return 0; + } + + fwnode = acpi_alloc_fwnode_static(); + if (!fwnode) + return -ENOMEM; + + iort_set_fwnode(iort_node, fwnode, NULL); + + ret = iort_add_platform_device(iort_node, ops); + if (ret) { + iort_delete_fwnode(iort_node); + acpi_free_fwnode_static(fwnode); + return ret; + } + + return 0; +} + +static void __init iort_init_devices(void) { struct acpi_iort_node *iort_node, *iort_end; struct acpi_table_iort *iort; - struct fwnode_handle *fwnode; - int i, ret; - const struct iort_dev_config *ops; + int i; /* * iort_table and iort both point to the start of IORT table, but @@ -1667,23 +1751,8 @@ static void __init iort_init_platform_devices(void) return; } - iort_enable_acs(iort_node); - - ops = iort_get_dev_cfg(iort_node); - if (ops) { - fwnode = acpi_alloc_fwnode_static(); - if (!fwnode) - return; - - iort_set_fwnode(iort_node, fwnode); - - ret = iort_add_platform_device(iort_node, ops); - if (ret) { - iort_delete_fwnode(iort_node); - acpi_free_fwnode_static(fwnode); - return; - } - } + if (iort_init_node(iort_node)) + return; iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node, iort_node->length); @@ -1703,7 +1772,7 @@ void __init acpi_iort_register_table(struct acpi_table_header *table, iort_table = table; iort_table_source = source; - iort_init_platform_devices(); + iort_init_devices(); } void __init acpi_iort_init(void)