From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dennis Chen Subject: Re: [PATCH v4 09/15] drivers: acpi: iort: add support for ARM SMMU platform devices creation Date: Thu, 18 Aug 2016 18:50:07 +0800 Message-ID: <20160818105005.GA20404@arm.com> References: <1471274620-20754-1-git-send-email-lorenzo.pieralisi@arm.com> <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1471274620-20754-10-git-send-email-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org> Content-Disposition: inline List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org Errors-To: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org To: Lorenzo Pieralisi Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, Marc Zyngier , Tomasz Nowicki , "Rafael J. Wysocki" , linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Will Deacon , linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Sinan Kaya , linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org, Hanjun Guo , Jon Masters , nd-5wv7dgnIgG8@public.gmane.org List-Id: linux-acpi@vger.kernel.org Hi Lorenzo, On Mon, Aug 15, 2016 at 04:23:34PM +0100, Lorenzo Pieralisi wrote: > In ARM ACPI systems, IOMMU components are specified through static > IORT table entries. In order to create platform devices for the > corresponding ARM SMMU components, IORT kernel code should be made > able to parse IORT table entries and create platform devices > dynamically. > > This patch adds the generic IORT infrastructure required to create > platform devices for ARM SMMUs. > > ARM SMMU versions have different resources requirement therefore this > patch also introduces an IORT specific structure (ie iort_iommu_config) > that contains hooks (to be defined when the corresponding ARM SMMU > driver support is added to the kernel) to be used to define the > platform devices names, init the IOMMUs, count their resources and > finally initialize them. > > Signed-off-by: Lorenzo Pieralisi > Cc: Hanjun Guo > Cc: Tomasz Nowicki > Cc: "Rafael J. Wysocki" > --- > drivers/acpi/arm64/iort.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 153 insertions(+) > > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c > index f6db3d8..4043071 100644 > --- a/drivers/acpi/arm64/iort.c > +++ b/drivers/acpi/arm64/iort.c > @@ -22,6 +22,7 @@ > #include > #include > #include > +#include > #include > > struct iort_its_msi_chip { > @@ -454,6 +455,157 @@ iort_get_device_domain(struct device *dev, u32 req_id) > return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI); > } > > +struct iort_iommu_config { > + const char *name; > + int (*iommu_init)(struct acpi_iort_node *node); > + bool (*iommu_is_coherent)(struct acpi_iort_node *node); > + int (*iommu_count_resources)(struct acpi_iort_node *node); > + void (*iommu_init_resources)(struct resource *res, > + struct acpi_iort_node *node); > +}; > + > +static const struct iort_iommu_config * __init > +iort_get_iommu_config(struct acpi_iort_node *node) > +{ > + return NULL; > +} > + > +/** > + * iort_add_smmu_platform_device() - Allocate a platform device for SMMU > + * @fwnode: IORT node associated fwnode handle > + * @node: Pointer to SMMU ACPI IORT node > + * > + * Returns: 0 on success, <0 failure > + */ > +static int __init > +iort_add_smmu_platform_device(struct fwnode_handle *fwnode, > + struct acpi_iort_node *node) > +{ > + struct platform_device *pdev; > + struct resource *r; > + enum dev_dma_attr attr; > + int ret, count; > + const struct iort_iommu_config *ops = > + iort_get_iommu_config(node); > + > + if (!ops) > + return -ENODEV; > + > + pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO); > + if (!pdev) > + return PTR_ERR(pdev); > + > + count = ops->iommu_count_resources(node); > + > + r = kcalloc(count, sizeof(*r), GFP_KERNEL); > + if (!r) { > + ret = -ENOMEM; > + goto dev_put; > + } > + > + ops->iommu_init_resources(r, node); > + > + ret = platform_device_add_resources(pdev, r, count); > + /* > + * Resources are duplicated in platform_device_add_resources, > + * free their allocated memory > + */ > + kfree(r); > + > + if (ret) > + goto dev_put; > + > + /* > + * Add a copy of IORT node pointer to platform_data to > + * be used to retrieve IORT data information. > + */ > + ret = platform_device_add_data(pdev, &node, sizeof(node)); > + if (ret) > + goto dev_put; > + > + pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); > + if (!pdev->dev.dma_mask) { > + ret = -ENOMEM; > + goto dev_put; > + } > + > + pdev->dev.fwnode = fwnode; > + > + /* > + * Set default dma mask value for the table walker, > + * to be overridden on probing with correct value. > + */ > + *pdev->dev.dma_mask = DMA_BIT_MASK(32); > + pdev->dev.coherent_dma_mask = *pdev->dev.dma_mask; > + > + attr = ops->iommu_is_coherent(node) ? > + DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT; > + > + /* Configure DMA for the page table walker */ > + acpi_dma_configure(&pdev->dev, attr); > + > + ret = platform_device_add(pdev); > + if (ret) > + goto dma_deconfigure; > + > + return 0; > + > +dma_deconfigure: > + acpi_dma_deconfigure(&pdev->dev); > + kfree(pdev->dev.dma_mask); > + > +dev_put: > + platform_device_put(pdev); > + > + return ret; > +} > + > +static void __init iort_smmu_init(void) > +{ > + struct acpi_iort_node *iort_node, *iort_end; > + struct acpi_table_iort *iort; > + struct fwnode_handle *fwnode; > + int i, ret; > + > + /* > + * table and iort will both point to the start of IORT table, but > + * have different struct types > + */ > + iort = (struct acpi_table_iort *)iort_table; > If the firmware of a platform happens to miss the IORT table, then iort_table here will be a NULL pointer, in this case 'NULL pointer dereference' kernel panic will occur, if this is not an expected behavior then we can add a sanity check here to avoid this. IORT missing is a fatal error? I don't think so. Thanks, Dennis > + > + /* Get the first IORT node */ > + iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_table, > + iort->node_offset); > + iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort_table, > + iort_table->length); > + > + for (i = 0; i < iort->node_count; i++) { > + > + if (iort_node >= iort_end) { > + pr_err("iort node pointer overflows, bad table\n"); > + return; > + } > + > + if (iort_node->type == ACPI_IORT_NODE_SMMU || > + iort_node->type == ACPI_IORT_NODE_SMMU_V3) { > + fwnode = iort_get_fwnode(iort_node); > + > + if (!fwnode) > + continue; > + > + ret = iort_add_smmu_platform_device(fwnode, > + iort_node); > + if (ret) { > + pr_err("Error in platform device creation\n"); > + return; > + } > + } > + > + iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node, > + iort_node->length); > + } > +} > + > void __init iort_table_detect(void) > { > acpi_status status; > @@ -465,4 +617,5 @@ void __init iort_table_detect(void) > } > > acpi_probe_device_table(iort); > + iort_smmu_init(); > } > -- > 2.6.4 > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1946988AbcHRKvu (ORCPT ); Thu, 18 Aug 2016 06:51:50 -0400 Received: from eu-smtp-delivery-143.mimecast.com ([207.82.80.143]:20762 "EHLO eu-smtp-delivery-143.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752898AbcHRKu5 (ORCPT ); Thu, 18 Aug 2016 06:50:57 -0400 Date: Thu, 18 Aug 2016 18:50:07 +0800 From: Dennis Chen To: Lorenzo Pieralisi CC: , Hanjun Guo , Tomasz Nowicki , "Rafael J. Wysocki" , Will Deacon , Marc Zyngier , "Robin Murphy" , Joerg Roedel , Jon Masters , Sinan Kaya , Nate Watterson , , , , , Subject: Re: [PATCH v4 09/15] drivers: acpi: iort: add support for ARM SMMU platform devices creation Message-ID: <20160818105005.GA20404@arm.com> References: <1471274620-20754-1-git-send-email-lorenzo.pieralisi@arm.com> <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com> MIME-Version: 1.0 In-Reply-To: <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:217.140.96.140;IPV:CAL;SCL:-1;CTRY:GB;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(7916002)(2980300002)(448002)(24454002)(199003)(189002)(2906002)(36756003)(11100500001)(87936001)(4326007)(92566002)(106466001)(97756001)(46406003)(31430400001)(189998001)(26826002)(4001350100001)(1076002)(246002)(356003)(50466002)(7846002)(104016004)(110136002)(19580395003)(83506001)(77096005)(23726003)(626004)(8936002)(76176999)(47776003)(50986999)(19580405001)(2950100001)(86362001)(305945005)(85326001)(586003)(33656002)(8676002)(54356999)(7416002)(7696003)(18370500001)(217873001);DIR:OUT;SFP:1101;SCL:1;SRVR:DB6PR0801MB1799;H:nebula.arm.com;FPR:;SPF:PermError;PTR:fw-tnat.cambridge.arm.com;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;AM1FFO11FD014;1:ldPZvzePRUPGpezQQta5y7dowQXYFHd5nIWqlIUVwvjMsK4I/g2JvdlsI7uDp2YZbZH6T9/uT2phPoc0Ir1Pk6gEabTQxZYkBiCB6QI1vZsJRncNHblp+ktn1yXS0XHq0L7Vh2Rli1oTpkPy6lMeG+Xxo01u1c4ogLT+3GL8dD7qxkM+9SHpFfwICRpgNV4f6WnvGAGpMkunpfLNY0Ggo0Bv2M7FqNRIk4mYL8EBiGOVA7+tsmqVKC7YXAH6EP3ehQdpTOKS37n4g7xGdhmmqwrs1M4O7PuXKqxt65HLrgXd33J6v+FJnPHX3yVFvt6A5G39hDdRWwahC/Z0UcDaIgOYxPO/Tk0wuqgIuUXquLDz8bSklQ1FkAdnrm+HXTQeMLkrJCwDWM37GBEDysav0GcOJ5g7SJ3yDSewD21ej7hmdn+UGPaAsyUYjFb2lVctExjHt47NAu/hjJrK3XS+fQZbOEoVp+PEmHHOycwkLnKk3V+4p26cfZORcMS3QiyMX3hK4zptcF8LZNyi4vjDWucusc1dMhP1imiOy602Zu6tD0NBuNv5dlvd5G5J7FLBcqy9j9J8oQRQNiCV5uqXAvXPIOantrQWvCMaPjgURMg= X-MS-Office365-Filtering-Correlation-Id: a118ccf5-4bdc-4b19-ded5-08d3c755782d X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1799;2:j97fFPKPBsSZgxGdO+D5nkcVvwYqnQlgK63Slvlpg7xxEMO1PQE7btHSyiZ9wXvJ+hc2krGasmDiDirl2VkkoSYwxEQEHSohShrVP4Wc8vO9MAazJieXuEdcA8Gjg0Kj3It0pzlQbT5lAQPVNNNDoKJBxeAiHgFGHzGbHhvUIytl149vE7el+dtk4m8/AdPH;3:YJk7h2wAOFzMo4KPCX3q3hy6OF5x7HNjSuSJRbWZYO5A7QgIw+I2TuVrvzit6G+iVK3Kj+xGCAYHW1tedBPlkoEwUwWsVJcOMtFedTVGf+/xqZzHR2Q64fHomdRI0wGVtDRJzJIZc5gMKDEKRa2WOHMTTqPQ2TKhYI0WbEoJktCZWs5KmwUn3cM+EiOti0AuRnYsPaZgrM70sTjmCr5sWlRD/kAVY2IWyPuaybiLjFs=;25:kzeHfL/Gt8Xs7lzNf+Vr+40+yJnDWUHonHIDf6H+xtKYZBK1ymy8wy1AN2Bx0eIHPsG9MP564IgMfe5epXUe5413B8ujVM7jB5JJRT53Y1gQX9xsVYFYvKNSqhZ0MCohQjJMzzCwGItW3psGY5TfkGWndLygoXXrU6WmtW/Tt/QFagU8WGb7oa/FJSCjyAE1RbaJT7q2vJIbAswAuzInANzeRCcESupRsYZtI9v2P5yc4Czovrm4ysR9wi73iNfYr1RYj/z85ONfzprJShe+V5DgYmjoRQHUtf2fNHHUlAOrKbT6JrBcAE2ys6AsrBDDJ75+e45NZP58iJ0yp99eq906nOnOVdFddyEZ27lFHv23tu4zzVa3fxmzmvd9RWb3zI275gdJBe+xE7Raig6/ZYIUSZSm8QbUi8awS3OIIKU= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DB6PR0801MB1799; X-LD-Processed: f34e5979-57d9-4aaa-ad4d-b122a662184d,ExtAddr X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1799;31:RuE5vaY0rGU9FKMzk1DHDWHCr9UT/WSde2hVzq15VmXNCN7FbXFyHJOoid13zVMivs58Pc05C8KUV/P5vkaWJx4fPHYNLtyygsPxEf0RuPBVCR0izlghRMYH8Ez3lY7RcNhxm+KYHKenn93WHlVzum7t6W0S9jziMRzu+qL/ig+VuusAS8D4WtCTZOWwBsoZ/nw346VaLFzhmK5HIbv9NeYdadIBI6fk+TzoMPqJvcg=;20:SnyICVqjUlwqSy74dKZdYmcXAELqVk0IiNtRzTXjBvICwwu5rmMq+lY9Srr4nwR7xRBRwo6i7k8F1s86zJhv5zRu3IRXUzFhM9WNeAVhHkWRtxY2l68sN4lrR0IrU0Cl2GtEzJa7XCs+CoLIE5cZs9+6agyJ4jD1JvaUKn6RpCYSYto0qHNF5JssA55Tp79AU4DRbgXbeovcQZoOJmhQYStqPX1X0jrFDz5ZR7KEwNaZK6Xz8ntseUq1xeV6Cnt8 NoDisclaimer: True X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(180628864354917); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040176)(601004)(2401047)(13020025)(13023025)(13024025)(13013025)(8121501046)(5005006)(10201501046)(3002001)(6055026);SRVR:DB6PR0801MB1799;BCL:0;PCL:0;RULEID:;SRVR:DB6PR0801MB1799; X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1799;4:wRyzxt6f4nK3xXpHhpDh4ZDHHf9J8iTi4kODkogNZkbKqdc/AsjiREwrpCFzjZBvjVXbTj+UidZF3pc3hpH4AkEbZHuml4KzsiWpsl2zDsR82bS++TdH1L0/lRX4oRUtozNK7E0z27+oHMORLzAlqZpdOwx+oF1CbWf2CD8JCHVf5cCnp3cbbO2/ymBPHpYe9t52Iar+1+rMhq/EDG5Luresf2Cb5hdTfIyHpX1Liuos6VIHJN/iLp43tPzs7RZmmZlV4zUuBhjVmZGTGVMRKHyf/L+84ngMJ25TP9hjlHLz/1gYxTfgioPXCt+7+8LY3Ix2kOi7hnNshzGGdYrznHh6KaHaxOnh6aqBlvJ70UbQozm4XoECkt30JiZc3/s8kP2Hnt+Ko1NeIcAug3EicQxJPuGw8kGBQDEvNjy/pgeRBJWNFsoaAcb3w1YSUPk+hFCaetfwQfXfIRH//2Z37sTVe5n/txG/lWW8LXEIxuXoJZuB0eiF2T8Vd5yn809LRjF7F9lU/xhCVXhDXwoo3A== X-Forefront-PRVS: 0038DE95A2 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;DB6PR0801MB1799;23:6Re9ABUvgRbHH0nd9rrM5OdYHxfMilbjlYsc+rq?= =?us-ascii?Q?9Br0OnTkFSioW9w3HKS2vkcPch8G7Dy0/A3KXN4Q2jJWHapDaq2DQYh1bmU5?= =?us-ascii?Q?otlulU/EVFcQQqo2mGIOPupQ4RSTbLjkizO5ZN/lRABCrCbNxgN3N8qwL1Vw?= =?us-ascii?Q?6FlrOKtSz4+r1YGWuQ8MUbVB6oruRnNSiRvP9mIUl3M+CJ8eiN4wYiFYOEcR?= =?us-ascii?Q?EPxmgWkziNX5KoGePWYzpMGnEJMdkly5K//943n4XveydKFCM2/7vFw/Jz0L?= =?us-ascii?Q?OqueNyHrRFRcLU1DnQ0La0++68+4kGypKcVTcDTtv04HI2LkM4vRGgGkUapR?= =?us-ascii?Q?yrWqhm3HOgwFZ0ZWCPNrpEvBZyAKSyw53BdvDV8vdwUucKAh/2d0ixcWHZXC?= =?us-ascii?Q?nmWXIffSi1rpiafyLjIX4JIsejQ895nuGnZ69sQtQRS5oVGYaJcLEdEohoiW?= =?us-ascii?Q?wI8nivwaEsVaPImbSCLjgtH0A+Qu+oHucpU+6zOYQQ7qC+hr8dDcIlmJvNpR?= =?us-ascii?Q?YxreZ33Uh+xEru3l1OSTaCyfZ286PsKgjDoxd0Y0BqyMEy7YdhDruQ0+902+?= =?us-ascii?Q?8nwxN3IaTCEnIrc5WoJNZq+a0OkqYcoO7L27qR86bTzc6o42MHbLNxGiXfNz?= =?us-ascii?Q?b/k9jJ0xA1jrE5DXf2iGNWQXVTxrkhKJ+BYr7j8ekxUXgwPovWgit77T4V2G?= =?us-ascii?Q?NOSe8RnMXL0O8Rj5I/+N2dvrVEJElUfk5KT5TakG18fBtxq/4+aJ4isqYbYr?= =?us-ascii?Q?utF//FryY3dBSFALa9lzhf7F2CLrMaKPIfLVakCBa940pVi3lOVW6i5EaEaA?= =?us-ascii?Q?He8y/p2rODvm0xIKEEMLXqVFluhtgc03qJ+XUa3HEwOT32QXawCfmPooOnLS?= =?us-ascii?Q?BEmTWOoAhjTis+xGJwgx2jj/iQQ0hN/eWUIo+++XmhotLqxqJidNlbhU+j1T?= =?us-ascii?Q?7wE0C9JXYnwfKbhHz/QIQfWzWsoHv/t66KC8B3Rg28IOoEt5f8cseGmz8NUX?= =?us-ascii?Q?ZzqnndDWt3aOJD3NQNu2c288SXMVYdOIm98tG5+PHdXVscADr+avLllYIy17?= =?us-ascii?Q?/iE1Na/JGGj+b+q/IxV5FHUCr8trJDHQ0HBcAdwhpjzCI/XMXE6jQ2o20zLx?= =?us-ascii?Q?ZWIAO5uxTtEMIKJ9lKqAeJ8iEGNipjWSoS2EL2U49fwJExLhW0pAD+wVL87Y?= =?us-ascii?Q?6ZcGKMLqBnzhOLo1CUCtOMnh0SwnkY+4auHGa?= X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1799;6:x+n9JTILI4CLVB7J9tSGaZQkZmyOI0mzfZF9eoSF0EmOM8/jXCBphpYHi9b53uOez6BtWisXcKxcvZN/mMdYm7k4EbN2+btASNnU1TX/fm2NCvjF4A5kNYixWS2QwzLLr1brw+Pbax7VFbvptiFGMk8b/TPvGYG7IW59mpl354NoZzr7AehonTDgHA68H4eqSoJAuy8g/T1+P0j+SDpPM5WsTmHNZr9ZImfswxs5L29mYzBMvDrrd0V+AyIq+oT82/54et7D3qJKJIseT3C0T68K5uZxb71/dLn95Ivc9xV1qDeM5Mx0QYShr8lDW8akOE3k7UgrjCi+0ru0L3bCTQ==;5:ctFo3vJTMkrSDBaQ7I9UmlGOFbre0YkgDVL/HXICZnXDLuQzI+rLLX4zLa6lZG6IcxhwIvNHitTbH8+Ky+fS+MBFgDRxjn7fecG6WKiDha2d5XfTHqFeBCbdriVjDEqpDksESxYeWS4xLrWOVnZHHg==;24:rFaFPu4IWYjWcVaEp+++ZDSkeLZr5Ih0NIjbW3WQBC737SrZwJHQz1sxAVyxyH9gDDMtYbHSzmSdbiUtKtnSK9Y0qOBFgWZAtQXHgZ7X0/g=;7:1XFuMk42mrhoenKXecIyXV2g40c85VuszX2F+KYNaVWSMOabC9gO35u/2CyoxCTVqY1WrjUEgmsFMcDGVpTV8H0G0xMZoVwzRx+6CFW2wpt2I7Hbk+oGu1YaBhwKQ1aEnSAP23yFjX5DaVGFU4HzSWZ9e7jLxBWVwWpTqjdEd9AnWHxY0i25ojIdtMn87pm6Erq7qT4KDYO+kPWuiHtwNQU/P81C98wQC8Rjvx6zpLa/cFYKhJjrnYAQeELrcNdc SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1799;20:GUHpK0584ezCK13WUcDAId0P6jUTYbtbpVqSdvmvojNia+FtSGjoRvKZhmRClG0dkL3QDuj55juSTfUYn3l1bZY9xcEtmgktnO8mAbpDOc/dEhyozi+e51LN2oFOIyrJyVUc5KD+XZSp37Fb/XL9zG3zOrLAbDc1tJsdgmwydco= X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Aug 2016 10:50:28.9451 (UTC) X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d;Ip=[217.140.96.140];Helo=[nebula.arm.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0801MB1799 X-MC-Unique: Lx2qHSFxOeeAFPimfENXVA-1 Content-Type: text/plain; charset=WINDOWS-1252 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by mail.home.local id u7IAqAWd022425 Hi Lorenzo, On Mon, Aug 15, 2016 at 04:23:34PM +0100, Lorenzo Pieralisi wrote: > In ARM ACPI systems, IOMMU components are specified through static > IORT table entries. In order to create platform devices for the > corresponding ARM SMMU components, IORT kernel code should be made > able to parse IORT table entries and create platform devices > dynamically. > > This patch adds the generic IORT infrastructure required to create > platform devices for ARM SMMUs. > > ARM SMMU versions have different resources requirement therefore this > patch also introduces an IORT specific structure (ie iort_iommu_config) > that contains hooks (to be defined when the corresponding ARM SMMU > driver support is added to the kernel) to be used to define the > platform devices names, init the IOMMUs, count their resources and > finally initialize them. > > Signed-off-by: Lorenzo Pieralisi > Cc: Hanjun Guo > Cc: Tomasz Nowicki > Cc: "Rafael J. Wysocki" > --- > drivers/acpi/arm64/iort.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 153 insertions(+) > > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c > index f6db3d8..4043071 100644 > --- a/drivers/acpi/arm64/iort.c > +++ b/drivers/acpi/arm64/iort.c > @@ -22,6 +22,7 @@ > #include > #include > #include > +#include > #include > > struct iort_its_msi_chip { > @@ -454,6 +455,157 @@ iort_get_device_domain(struct device *dev, u32 req_id) > return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI); > } > > +struct iort_iommu_config { > + const char *name; > + int (*iommu_init)(struct acpi_iort_node *node); > + bool (*iommu_is_coherent)(struct acpi_iort_node *node); > + int (*iommu_count_resources)(struct acpi_iort_node *node); > + void (*iommu_init_resources)(struct resource *res, > + struct acpi_iort_node *node); > +}; > + > +static const struct iort_iommu_config * __init > +iort_get_iommu_config(struct acpi_iort_node *node) > +{ > + return NULL; > +} > + > +/** > + * iort_add_smmu_platform_device() - Allocate a platform device for SMMU > + * @fwnode: IORT node associated fwnode handle > + * @node: Pointer to SMMU ACPI IORT node > + * > + * Returns: 0 on success, <0 failure > + */ > +static int __init > +iort_add_smmu_platform_device(struct fwnode_handle *fwnode, > + struct acpi_iort_node *node) > +{ > + struct platform_device *pdev; > + struct resource *r; > + enum dev_dma_attr attr; > + int ret, count; > + const struct iort_iommu_config *ops = > + iort_get_iommu_config(node); > + > + if (!ops) > + return -ENODEV; > + > + pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO); > + if (!pdev) > + return PTR_ERR(pdev); > + > + count = ops->iommu_count_resources(node); > + > + r = kcalloc(count, sizeof(*r), GFP_KERNEL); > + if (!r) { > + ret = -ENOMEM; > + goto dev_put; > + } > + > + ops->iommu_init_resources(r, node); > + > + ret = platform_device_add_resources(pdev, r, count); > + /* > + * Resources are duplicated in platform_device_add_resources, > + * free their allocated memory > + */ > + kfree(r); > + > + if (ret) > + goto dev_put; > + > + /* > + * Add a copy of IORT node pointer to platform_data to > + * be used to retrieve IORT data information. > + */ > + ret = platform_device_add_data(pdev, &node, sizeof(node)); > + if (ret) > + goto dev_put; > + > + pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); > + if (!pdev->dev.dma_mask) { > + ret = -ENOMEM; > + goto dev_put; > + } > + > + pdev->dev.fwnode = fwnode; > + > + /* > + * Set default dma mask value for the table walker, > + * to be overridden on probing with correct value. > + */ > + *pdev->dev.dma_mask = DMA_BIT_MASK(32); > + pdev->dev.coherent_dma_mask = *pdev->dev.dma_mask; > + > + attr = ops->iommu_is_coherent(node) ? > + DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT; > + > + /* Configure DMA for the page table walker */ > + acpi_dma_configure(&pdev->dev, attr); > + > + ret = platform_device_add(pdev); > + if (ret) > + goto dma_deconfigure; > + > + return 0; > + > +dma_deconfigure: > + acpi_dma_deconfigure(&pdev->dev); > + kfree(pdev->dev.dma_mask); > + > +dev_put: > + platform_device_put(pdev); > + > + return ret; > +} > + > +static void __init iort_smmu_init(void) > +{ > + struct acpi_iort_node *iort_node, *iort_end; > + struct acpi_table_iort *iort; > + struct fwnode_handle *fwnode; > + int i, ret; > + > + /* > + * table and iort will both point to the start of IORT table, but > + * have different struct types > + */ > + iort = (struct acpi_table_iort *)iort_table; > If the firmware of a platform happens to miss the IORT table, then iort_table here will be a NULL pointer, in this case 'NULL pointer dereference' kernel panic will occur, if this is not an expected behavior then we can add a sanity check here to avoid this. IORT missing is a fatal error? I don't think so. Thanks, Dennis > + > + /* Get the first IORT node */ > + iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_table, > + iort->node_offset); > + iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort_table, > + iort_table->length); > + > + for (i = 0; i < iort->node_count; i++) { > + > + if (iort_node >= iort_end) { > + pr_err("iort node pointer overflows, bad table\n"); > + return; > + } > + > + if (iort_node->type == ACPI_IORT_NODE_SMMU || > + iort_node->type == ACPI_IORT_NODE_SMMU_V3) { > + fwnode = iort_get_fwnode(iort_node); > + > + if (!fwnode) > + continue; > + > + ret = iort_add_smmu_platform_device(fwnode, > + iort_node); > + if (ret) { > + pr_err("Error in platform device creation\n"); > + return; > + } > + } > + > + iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node, > + iort_node->length); > + } > +} > + > void __init iort_table_detect(void) > { > acpi_status status; > @@ -465,4 +617,5 @@ void __init iort_table_detect(void) > } > > acpi_probe_device_table(iort); > + iort_smmu_init(); > } > -- > 2.6.4 > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from eu-smtp-delivery-143.mimecast.com ([207.82.80.143]:40305 "EHLO eu-smtp-delivery-143.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752864AbcHRKu5 (ORCPT ); Thu, 18 Aug 2016 06:50:57 -0400 Date: Thu, 18 Aug 2016 18:50:07 +0800 From: Dennis Chen To: Lorenzo Pieralisi CC: , Hanjun Guo , Tomasz Nowicki , "Rafael J. Wysocki" , Will Deacon , Marc Zyngier , "Robin Murphy" , Joerg Roedel , Jon Masters , Sinan Kaya , Nate Watterson , , , , , Subject: Re: [PATCH v4 09/15] drivers: acpi: iort: add support for ARM SMMU platform devices creation Message-ID: <20160818105005.GA20404@arm.com> References: <1471274620-20754-1-git-send-email-lorenzo.pieralisi@arm.com> <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com> MIME-Version: 1.0 In-Reply-To: <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com> Content-Type: text/plain; charset=WINDOWS-1252 Sender: linux-pci-owner@vger.kernel.org List-ID: Hi Lorenzo, On Mon, Aug 15, 2016 at 04:23:34PM +0100, Lorenzo Pieralisi wrote: > In ARM ACPI systems, IOMMU components are specified through static > IORT table entries. In order to create platform devices for the > corresponding ARM SMMU components, IORT kernel code should be made > able to parse IORT table entries and create platform devices > dynamically. >=20 > This patch adds the generic IORT infrastructure required to create > platform devices for ARM SMMUs. >=20 > ARM SMMU versions have different resources requirement therefore this > patch also introduces an IORT specific structure (ie iort_iommu_config) > that contains hooks (to be defined when the corresponding ARM SMMU > driver support is added to the kernel) to be used to define the > platform devices names, init the IOMMUs, count their resources and > finally initialize them. >=20 > Signed-off-by: Lorenzo Pieralisi > Cc: Hanjun Guo > Cc: Tomasz Nowicki > Cc: "Rafael J. Wysocki" > --- > drivers/acpi/arm64/iort.c | 153 ++++++++++++++++++++++++++++++++++++++++= ++++++ > 1 file changed, 153 insertions(+) >=20 > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c > index f6db3d8..4043071 100644 > --- a/drivers/acpi/arm64/iort.c > +++ b/drivers/acpi/arm64/iort.c > @@ -22,6 +22,7 @@ > #include > #include > #include > +#include > #include > =20 > struct iort_its_msi_chip { > @@ -454,6 +455,157 @@ iort_get_device_domain(struct device *dev, u32 req_= id) > =09return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI); > } > =20 > +struct iort_iommu_config { > +=09const char *name; > +=09int (*iommu_init)(struct acpi_iort_node *node); > +=09bool (*iommu_is_coherent)(struct acpi_iort_node *node); > +=09int (*iommu_count_resources)(struct acpi_iort_node *node); > +=09void (*iommu_init_resources)(struct resource *res, > +=09=09=09=09 struct acpi_iort_node *node); > +}; > + > +static const struct iort_iommu_config * __init > +iort_get_iommu_config(struct acpi_iort_node *node) > +{ > +=09return NULL; > +} > + > +/** > + * iort_add_smmu_platform_device() - Allocate a platform device for SMMU > + * @fwnode: IORT node associated fwnode handle > + * @node: Pointer to SMMU ACPI IORT node > + * > + * Returns: 0 on success, <0 failure > + */ > +static int __init > +iort_add_smmu_platform_device(struct fwnode_handle *fwnode, > +=09=09=09 struct acpi_iort_node *node) > +{ > +=09struct platform_device *pdev; > +=09struct resource *r; > +=09enum dev_dma_attr attr; > +=09int ret, count; > +=09const struct iort_iommu_config *ops =3D > +=09=09=09=09iort_get_iommu_config(node); > + > +=09if (!ops) > +=09=09return -ENODEV; > + > +=09pdev =3D platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO); > +=09if (!pdev) > +=09=09return PTR_ERR(pdev); > + > +=09count =3D ops->iommu_count_resources(node); > + > +=09r =3D kcalloc(count, sizeof(*r), GFP_KERNEL); > +=09if (!r) { > +=09=09ret =3D -ENOMEM; > +=09=09goto dev_put; > +=09} > + > +=09ops->iommu_init_resources(r, node); > + > +=09ret =3D platform_device_add_resources(pdev, r, count); > +=09/* > +=09 * Resources are duplicated in platform_device_add_resources, > +=09 * free their allocated memory > +=09 */ > +=09kfree(r); > + > +=09if (ret) > +=09=09goto dev_put; > + > +=09/* > +=09 * Add a copy of IORT node pointer to platform_data to > +=09 * be used to retrieve IORT data information. > +=09 */ > +=09ret =3D platform_device_add_data(pdev, &node, sizeof(node)); > +=09if (ret) > +=09=09goto dev_put; > + > +=09pdev->dev.dma_mask =3D kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNE= L); > +=09if (!pdev->dev.dma_mask) { > +=09=09ret =3D -ENOMEM; > +=09=09goto dev_put; > +=09} > + > +=09pdev->dev.fwnode =3D fwnode; > + > +=09/* > +=09 * Set default dma mask value for the table walker, > +=09 * to be overridden on probing with correct value. > +=09 */ > +=09*pdev->dev.dma_mask =3D DMA_BIT_MASK(32); > +=09pdev->dev.coherent_dma_mask =3D *pdev->dev.dma_mask; > + > +=09attr =3D ops->iommu_is_coherent(node) ? > +=09=09=09 DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT; > + > +=09/* Configure DMA for the page table walker */ > +=09acpi_dma_configure(&pdev->dev, attr); > + > +=09ret =3D platform_device_add(pdev); > +=09if (ret) > +=09=09goto dma_deconfigure; > + > +=09return 0; > + > +dma_deconfigure: > +=09acpi_dma_deconfigure(&pdev->dev); > +=09kfree(pdev->dev.dma_mask); > + > +dev_put: > +=09platform_device_put(pdev); > + > +=09return ret; > +} > + > +static void __init iort_smmu_init(void) > +{ > +=09struct acpi_iort_node *iort_node, *iort_end; > +=09struct acpi_table_iort *iort; > +=09struct fwnode_handle *fwnode; > +=09int i, ret; > + > +=09/* > +=09 * table and iort will both point to the start of IORT table, but > +=09 * have different struct types > +=09 */ > +=09iort =3D (struct acpi_table_iort *)iort_table; > If the firmware of a platform happens to miss the IORT table, then iort_tab= le here will be a NULL pointer, in this case 'NULL pointer dereference' kernel pani= c will occur,=20 if this is not an expected behavior then we can add a sanity check here to = avoid this.=20 IORT missing is a fatal error? I don't think so. Thanks, Dennis > + > +=09/* Get the first IORT node */ > +=09iort_node =3D ACPI_ADD_PTR(struct acpi_iort_node, iort_table, > +=09=09=09=09 iort->node_offset); > +=09iort_end =3D ACPI_ADD_PTR(struct acpi_iort_node, iort_table, > +=09=09=09=09iort_table->length); > + > +=09for (i =3D 0; i < iort->node_count; i++) { > + > +=09=09if (iort_node >=3D iort_end) { > +=09=09=09pr_err("iort node pointer overflows, bad table\n"); > +=09=09=09return; > +=09=09} > + > +=09=09if (iort_node->type =3D=3D ACPI_IORT_NODE_SMMU || > +=09=09 iort_node->type =3D=3D ACPI_IORT_NODE_SMMU_V3) { > +=09=09=09fwnode =3D iort_get_fwnode(iort_node); > + > +=09=09=09if (!fwnode) > +=09=09=09=09continue; > + > +=09=09=09ret =3D iort_add_smmu_platform_device(fwnode, > +=09=09=09=09=09=09=09 iort_node); > +=09=09=09if (ret) { > +=09=09=09=09pr_err("Error in platform device creation\n"); > +=09=09=09=09return; > +=09=09=09} > +=09=09} > + > +=09=09iort_node =3D ACPI_ADD_PTR(struct acpi_iort_node, iort_node, > +=09=09=09=09=09 iort_node->length); > +=09} > +} > + > void __init iort_table_detect(void) > { > =09acpi_status status; > @@ -465,4 +617,5 @@ void __init iort_table_detect(void) > =09} > =20 > =09acpi_probe_device_table(iort); > +=09iort_smmu_init(); > } > --=20 > 2.6.4 >=20 From mboxrd@z Thu Jan 1 00:00:00 1970 From: dennis.chen@arm.com (Dennis Chen) Date: Thu, 18 Aug 2016 18:50:07 +0800 Subject: [PATCH v4 09/15] drivers: acpi: iort: add support for ARM SMMU platform devices creation In-Reply-To: <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com> References: <1471274620-20754-1-git-send-email-lorenzo.pieralisi@arm.com> <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com> Message-ID: <20160818105005.GA20404@arm.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hi Lorenzo, On Mon, Aug 15, 2016 at 04:23:34PM +0100, Lorenzo Pieralisi wrote: > In ARM ACPI systems, IOMMU components are specified through static > IORT table entries. In order to create platform devices for the > corresponding ARM SMMU components, IORT kernel code should be made > able to parse IORT table entries and create platform devices > dynamically. > > This patch adds the generic IORT infrastructure required to create > platform devices for ARM SMMUs. > > ARM SMMU versions have different resources requirement therefore this > patch also introduces an IORT specific structure (ie iort_iommu_config) > that contains hooks (to be defined when the corresponding ARM SMMU > driver support is added to the kernel) to be used to define the > platform devices names, init the IOMMUs, count their resources and > finally initialize them. > > Signed-off-by: Lorenzo Pieralisi > Cc: Hanjun Guo > Cc: Tomasz Nowicki > Cc: "Rafael J. Wysocki" > --- > drivers/acpi/arm64/iort.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 153 insertions(+) > > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c > index f6db3d8..4043071 100644 > --- a/drivers/acpi/arm64/iort.c > +++ b/drivers/acpi/arm64/iort.c > @@ -22,6 +22,7 @@ > #include > #include > #include > +#include > #include > > struct iort_its_msi_chip { > @@ -454,6 +455,157 @@ iort_get_device_domain(struct device *dev, u32 req_id) > return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI); > } > > +struct iort_iommu_config { > + const char *name; > + int (*iommu_init)(struct acpi_iort_node *node); > + bool (*iommu_is_coherent)(struct acpi_iort_node *node); > + int (*iommu_count_resources)(struct acpi_iort_node *node); > + void (*iommu_init_resources)(struct resource *res, > + struct acpi_iort_node *node); > +}; > + > +static const struct iort_iommu_config * __init > +iort_get_iommu_config(struct acpi_iort_node *node) > +{ > + return NULL; > +} > + > +/** > + * iort_add_smmu_platform_device() - Allocate a platform device for SMMU > + * @fwnode: IORT node associated fwnode handle > + * @node: Pointer to SMMU ACPI IORT node > + * > + * Returns: 0 on success, <0 failure > + */ > +static int __init > +iort_add_smmu_platform_device(struct fwnode_handle *fwnode, > + struct acpi_iort_node *node) > +{ > + struct platform_device *pdev; > + struct resource *r; > + enum dev_dma_attr attr; > + int ret, count; > + const struct iort_iommu_config *ops = > + iort_get_iommu_config(node); > + > + if (!ops) > + return -ENODEV; > + > + pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO); > + if (!pdev) > + return PTR_ERR(pdev); > + > + count = ops->iommu_count_resources(node); > + > + r = kcalloc(count, sizeof(*r), GFP_KERNEL); > + if (!r) { > + ret = -ENOMEM; > + goto dev_put; > + } > + > + ops->iommu_init_resources(r, node); > + > + ret = platform_device_add_resources(pdev, r, count); > + /* > + * Resources are duplicated in platform_device_add_resources, > + * free their allocated memory > + */ > + kfree(r); > + > + if (ret) > + goto dev_put; > + > + /* > + * Add a copy of IORT node pointer to platform_data to > + * be used to retrieve IORT data information. > + */ > + ret = platform_device_add_data(pdev, &node, sizeof(node)); > + if (ret) > + goto dev_put; > + > + pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); > + if (!pdev->dev.dma_mask) { > + ret = -ENOMEM; > + goto dev_put; > + } > + > + pdev->dev.fwnode = fwnode; > + > + /* > + * Set default dma mask value for the table walker, > + * to be overridden on probing with correct value. > + */ > + *pdev->dev.dma_mask = DMA_BIT_MASK(32); > + pdev->dev.coherent_dma_mask = *pdev->dev.dma_mask; > + > + attr = ops->iommu_is_coherent(node) ? > + DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT; > + > + /* Configure DMA for the page table walker */ > + acpi_dma_configure(&pdev->dev, attr); > + > + ret = platform_device_add(pdev); > + if (ret) > + goto dma_deconfigure; > + > + return 0; > + > +dma_deconfigure: > + acpi_dma_deconfigure(&pdev->dev); > + kfree(pdev->dev.dma_mask); > + > +dev_put: > + platform_device_put(pdev); > + > + return ret; > +} > + > +static void __init iort_smmu_init(void) > +{ > + struct acpi_iort_node *iort_node, *iort_end; > + struct acpi_table_iort *iort; > + struct fwnode_handle *fwnode; > + int i, ret; > + > + /* > + * table and iort will both point to the start of IORT table, but > + * have different struct types > + */ > + iort = (struct acpi_table_iort *)iort_table; > If the firmware of a platform happens to miss the IORT table, then iort_table here will be a NULL pointer, in this case 'NULL pointer dereference' kernel panic will occur, if this is not an expected behavior then we can add a sanity check here to avoid this. IORT missing is a fatal error? I don't think so. Thanks, Dennis > + > + /* Get the first IORT node */ > + iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_table, > + iort->node_offset); > + iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort_table, > + iort_table->length); > + > + for (i = 0; i < iort->node_count; i++) { > + > + if (iort_node >= iort_end) { > + pr_err("iort node pointer overflows, bad table\n"); > + return; > + } > + > + if (iort_node->type == ACPI_IORT_NODE_SMMU || > + iort_node->type == ACPI_IORT_NODE_SMMU_V3) { > + fwnode = iort_get_fwnode(iort_node); > + > + if (!fwnode) > + continue; > + > + ret = iort_add_smmu_platform_device(fwnode, > + iort_node); > + if (ret) { > + pr_err("Error in platform device creation\n"); > + return; > + } > + } > + > + iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node, > + iort_node->length); > + } > +} > + > void __init iort_table_detect(void) > { > acpi_status status; > @@ -465,4 +617,5 @@ void __init iort_table_detect(void) > } > > acpi_probe_device_table(iort); > + iort_smmu_init(); > } > -- > 2.6.4 >