From: Dennis Chen <dennis.chen-5wv7dgnIgG8@public.gmane.org>
To: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>,
Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>,
"Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>,
linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>,
linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
Jon Masters <jcm-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
nd-5wv7dgnIgG8@public.gmane.org
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 [thread overview]
Message-ID: <20160818105005.GA20404@arm.com> (raw)
In-Reply-To: <1471274620-20754-10-git-send-email-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.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 <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
> Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
> Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
> ---
> 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 <linux/kernel.h>
> #include <linux/list.h>
> #include <linux/pci.h>
> +#include <linux/platform_device.h>
> #include <linux/slab.h>
>
> 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
>
WARNING: multiple messages have this Message-ID (diff)
From: Dennis Chen <dennis.chen@arm.com>
To: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: <iommu@lists.linux-foundation.org>,
Hanjun Guo <hanjun.guo@linaro.org>,
Tomasz Nowicki <tn@semihalf.com>,
"Rafael J. Wysocki" <rjw@rjwysocki.net>,
Will Deacon <will.deacon@arm.com>,
Marc Zyngier <marc.zyngier@arm.com>,
"Robin Murphy" <robin.murphy@arm.com>,
Joerg Roedel <joro@8bytes.org>, Jon Masters <jcm@redhat.com>,
Sinan Kaya <okaya@codeaurora.org>,
Nate Watterson <nwatters@codeaurora.org>,
<linux-acpi@vger.kernel.org>, <linux-pci@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>, <nd@arm.com>
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 [thread overview]
Message-ID: <20160818105005.GA20404@arm.com> (raw)
In-Reply-To: <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com>
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 <lorenzo.pieralisi@arm.com>
> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Tomasz Nowicki <tn@semihalf.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> ---
> 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 <linux/kernel.h>
> #include <linux/list.h>
> #include <linux/pci.h>
> +#include <linux/platform_device.h>
> #include <linux/slab.h>
> =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
WARNING: multiple messages have this Message-ID (diff)
From: dennis.chen@arm.com (Dennis Chen)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4 09/15] drivers: acpi: iort: add support for ARM SMMU platform devices creation
Date: Thu, 18 Aug 2016 18:50:07 +0800 [thread overview]
Message-ID: <20160818105005.GA20404@arm.com> (raw)
In-Reply-To: <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com>
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 <lorenzo.pieralisi@arm.com>
> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Tomasz Nowicki <tn@semihalf.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> ---
> 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 <linux/kernel.h>
> #include <linux/list.h>
> #include <linux/pci.h>
> +#include <linux/platform_device.h>
> #include <linux/slab.h>
>
> 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
>
WARNING: multiple messages have this Message-ID (diff)
From: Dennis Chen <dennis.chen@arm.com>
To: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: <iommu@lists.linux-foundation.org>,
Hanjun Guo <hanjun.guo@linaro.org>,
Tomasz Nowicki <tn@semihalf.com>,
"Rafael J. Wysocki" <rjw@rjwysocki.net>,
Will Deacon <will.deacon@arm.com>,
Marc Zyngier <marc.zyngier@arm.com>,
"Robin Murphy" <robin.murphy@arm.com>,
Joerg Roedel <joro@8bytes.org>, Jon Masters <jcm@redhat.com>,
Sinan Kaya <okaya@codeaurora.org>,
Nate Watterson <nwatters@codeaurora.org>,
<linux-acpi@vger.kernel.org>, <linux-pci@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>, <nd@arm.com>
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 [thread overview]
Message-ID: <20160818105005.GA20404@arm.com> (raw)
In-Reply-To: <1471274620-20754-10-git-send-email-lorenzo.pieralisi@arm.com>
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 <lorenzo.pieralisi@arm.com>
> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Tomasz Nowicki <tn@semihalf.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> ---
> 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 <linux/kernel.h>
> #include <linux/list.h>
> #include <linux/pci.h>
> +#include <linux/platform_device.h>
> #include <linux/slab.h>
>
> 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
>
next prev parent reply other threads:[~2016-08-18 10:50 UTC|newest]
Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-15 15:23 [PATCH v4 00/15] ACPI IORT ARM SMMU v3 support Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
[not found] ` <1471274620-20754-1-git-send-email-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
2016-08-15 15:23 ` [PATCH v4 01/15] drivers: iommu: add FWNODE_IOMMU fwnode type Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
[not found] ` <1471274620-20754-2-git-send-email-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
2016-08-23 13:49 ` Lorenzo Pieralisi
2016-08-23 13:49 ` Lorenzo Pieralisi
2016-08-23 13:49 ` Lorenzo Pieralisi
2016-09-05 11:11 ` Hanjun Guo
2016-09-05 11:11 ` Hanjun Guo
2016-09-05 11:11 ` Hanjun Guo
2016-08-15 15:23 ` [PATCH v4 02/15] drivers: iommu: implement arch_{set/get}_iommu_fwspec API Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 03/15] drivers: acpi: iort: introduce linker section for IORT entries probing Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-09-05 11:42 ` Hanjun Guo
2016-09-05 11:42 ` Hanjun Guo
2016-08-15 15:23 ` [PATCH v4 04/15] drivers: acpi: iort: add support for IOMMU fwnode registration Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-09-05 13:00 ` Hanjun Guo
2016-09-05 13:00 ` Hanjun Guo
2016-08-15 15:23 ` [PATCH v4 05/15] drivers: platform: add fwnode base platform devices retrieval Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-09-05 13:19 ` Hanjun Guo
2016-09-05 13:19 ` Hanjun Guo
[not found] ` <7659b956-c49d-bd0d-7a1d-8dfc3da6f409-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-09-05 14:57 ` Lorenzo Pieralisi
2016-09-05 14:57 ` Lorenzo Pieralisi
2016-09-05 14:57 ` Lorenzo Pieralisi
2016-09-05 14:57 ` Lorenzo Pieralisi
2016-09-06 12:08 ` Hanjun Guo
2016-09-06 12:08 ` Hanjun Guo
2016-09-06 12:08 ` Hanjun Guo
2016-08-15 15:23 ` [PATCH v4 06/15] drivers: iommu: make iommu_fwspec OF agnostic Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 07/15] drivers: acpi: implement acpi_dma_configure Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 08/15] drivers: acpi: iort: add node match function Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 09/15] drivers: acpi: iort: add support for ARM SMMU platform devices creation Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
[not found] ` <1471274620-20754-10-git-send-email-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
2016-08-18 10:50 ` Dennis Chen [this message]
2016-08-18 10:50 ` Dennis Chen
2016-08-18 10:50 ` Dennis Chen
2016-08-18 10:50 ` Dennis Chen
[not found] ` <20160818105005.GA20404-5wv7dgnIgG8@public.gmane.org>
2016-08-18 10:55 ` Lorenzo Pieralisi
2016-08-18 10:55 ` Lorenzo Pieralisi
2016-08-18 10:55 ` Lorenzo Pieralisi
2016-08-18 10:55 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 10/15] drivers: iommu: arm-smmu-v3: split probe functions into DT/generic portions Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 11/15] drivers: iommu: arm-smmu-v3: enable ACPI driver initialization Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 12/15] drivers: iommu: arm-smmu-v3: add IORT configuration Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 13/15] drivers: acpi: iort: replace rid map type with type mask Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 14/15] drivers: acpi: iort: add single mapping function Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` [PATCH v4 15/15] drivers: acpi: iort: introduce iort_iommu_configure Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-08-15 15:23 ` Lorenzo Pieralisi
2016-09-05 9:41 ` [PATCH v4 00/15] ACPI IORT ARM SMMU v3 support Hanjun Guo
2016-09-05 9:41 ` Hanjun Guo
2016-09-05 9:41 ` Hanjun Guo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160818105005.GA20404@arm.com \
--to=dennis.chen-5wv7dgnigg8@public.gmane.org \
--cc=hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
--cc=iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=jcm-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org \
--cc=marc.zyngier-5wv7dgnIgG8@public.gmane.org \
--cc=nd-5wv7dgnIgG8@public.gmane.org \
--cc=okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \
--cc=rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org \
--cc=tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org \
--cc=will.deacon-5wv7dgnIgG8@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.