diff mbox

ath10k: Enable IOMMU support for WCN3990 target

Message ID 1518685448-15317-1-git-send-email-govinds@codeaurora.org (mailing list archive)
State New, archived
Headers show

Commit Message

Govind Singh Feb. 15, 2018, 9:04 a.m. UTC
When an IOMMU device is available on the platform bus, allocate
an IOMMU domain and attach the wlan target to it.
WCN3990 target can then attach an DMA I/O virtual address
space to scan out of bound transactions.

Signed-off-by: Govind Singh <govinds@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/snoc.c | 100 ++++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/snoc.h |   3 +
 2 files changed, 101 insertions(+), 2 deletions(-)

Comments

Kalle Valo March 1, 2018, 10:01 a.m. UTC | #1
Govind Singh <govinds@codeaurora.org> writes:

> When an IOMMU device is available on the platform bus, allocate
> an IOMMU domain and attach the wlan target to it.
> WCN3990 target can then attach an DMA I/O virtual address
> space to scan out of bound transactions.
>
> Signed-off-by: Govind Singh <govinds@codeaurora.org>
> ---
>  drivers/net/wireless/ath/ath10k/snoc.c | 100 ++++++++++++++++++++++++++++++++-
>  drivers/net/wireless/ath/ath10k/snoc.h |   3 +
>  2 files changed, 101 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
> index cd21b25..502263d 100644
> --- a/drivers/net/wireless/ath/ath10k/snoc.c
> +++ b/drivers/net/wireless/ath/ath10k/snoc.c
> @@ -26,6 +26,10 @@
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/clk.h>
> +#include <asm/dma-iommu.h>
> +#include <linux/iommu.h>
> +#include <linux/dma-mapping.h>

Kbuild bot reported a problem with arm64 but strangely I cannot find the
full report. Anyway, this was the warning:

drivers/net/wireless/ath/ath10k/snoc.c:29:10: fatal error:
asm/dma-iommu.h: No such file or directory

Any ideas? Adding also Arnd, the grand master of compilation problems :)

Full patch here:

https://patchwork.kernel.org/patch/10220719/
Arnd Bergmann March 1, 2018, 10:10 a.m. UTC | #2
On Thu, Mar 1, 2018 at 11:01 AM, Kalle Valo <kvalo@codeaurora.org> wrote:
> Govind Singh <govinds@codeaurora.org> writes:
>
>> When an IOMMU device is available on the platform bus, allocate
>> an IOMMU domain and attach the wlan target to it.
>> WCN3990 target can then attach an DMA I/O virtual address
>> space to scan out of bound transactions.
>>
>> Signed-off-by: Govind Singh <govinds@codeaurora.org>
>> ---
>>  drivers/net/wireless/ath/ath10k/snoc.c | 100 ++++++++++++++++++++++++++++++++-
>>  drivers/net/wireless/ath/ath10k/snoc.h |   3 +
>>  2 files changed, 101 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
>> index cd21b25..502263d 100644
>> --- a/drivers/net/wireless/ath/ath10k/snoc.c
>> +++ b/drivers/net/wireless/ath/ath10k/snoc.c
>> @@ -26,6 +26,10 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>>  #include <linux/clk.h>
>> +#include <asm/dma-iommu.h>
>> +#include <linux/iommu.h>
>> +#include <linux/dma-mapping.h>
>
> Kbuild bot reported a problem with arm64 but strangely I cannot find the
> full report. Anyway, this was the warning:
>
> drivers/net/wireless/ath/ath10k/snoc.c:29:10: fatal error:
> asm/dma-iommu.h: No such file or directory
>
> Any ideas? Adding also Arnd, the grand master of compilation problems :)
>
> Full patch here:
>
> https://patchwork.kernel.org/patch/10220719/
>

The asm/dma-iommu.h header file exsists only on arm32, no other architecture.

I'm not sure about the purpose of the patch to start with:
it's normally up to the platform code to allocate IOMMU domains,
device drivers should only need to manually interact with the
IOMMU layer if they need more than one domain, but this ath10k
patch appears to be using the default domain and should have
no effect as long as the platform code works correctly.

       Arnd
Govind Singh March 1, 2018, 1:18 p.m. UTC | #3
>> The asm/dma-iommu.h header file exsists only on arm32, no other architecture.
>> I'm not sure about the purpose of the patch to start with:
>> it's normally up to the platform code to allocate IOMMU domains, device drivers should only need to manually interact with the IOMMU layer if they need more than one domain, but this ath10k patch appears to be using the default domain and should have no effect as long as the platform code works correctly.
Thanks Arnd, I have fixed this and migrated to  64bit API's(iommu_attach_device/iommu_detach_device/ iommu_get_domain_for_dev), will share the next revision.
I tried using the default domain by adding the stream ID and mask in dt and no manual interaction, but it is resulting in TZ error and unhandled context fault.
Seems I need to provide explicit mapping range(aperture_start/ aperture_end) as this is only working combination for me..

BR,
Govind

-----Original Message-----
From: ath10k [mailto:ath10k-bounces@lists.infradead.org] On Behalf Of Arnd Bergmann
Sent: Thursday, March 1, 2018 3:40 PM
To: Kalle Valo <kvalo@codeaurora.org>
Cc: Govind Singh <govinds@codeaurora.org>; linux-wireless <linux-wireless@vger.kernel.org>; ath10k@lists.infradead.org
Subject: Re: [PATCH] ath10k: Enable IOMMU support for WCN3990 target

On Thu, Mar 1, 2018 at 11:01 AM, Kalle Valo <kvalo@codeaurora.org> wrote:
> Govind Singh <govinds@codeaurora.org> writes:
>
>> When an IOMMU device is available on the platform bus, allocate an 
>> IOMMU domain and attach the wlan target to it.
>> WCN3990 target can then attach an DMA I/O virtual address space to 
>> scan out of bound transactions.
>>
>> Signed-off-by: Govind Singh <govinds@codeaurora.org>
>> ---
>>  drivers/net/wireless/ath/ath10k/snoc.c | 100 ++++++++++++++++++++++++++++++++-
>>  drivers/net/wireless/ath/ath10k/snoc.h |   3 +
>>  2 files changed, 101 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/snoc.c 
>> b/drivers/net/wireless/ath/ath10k/snoc.c
>> index cd21b25..502263d 100644
>> --- a/drivers/net/wireless/ath/ath10k/snoc.c
>> +++ b/drivers/net/wireless/ath/ath10k/snoc.c
>> @@ -26,6 +26,10 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>  #include <linux/clk.h>
>> +#include <asm/dma-iommu.h>
>> +#include <linux/iommu.h>
>> +#include <linux/dma-mapping.h>
>
> Kbuild bot reported a problem with arm64 but strangely I cannot find 
> the full report. Anyway, this was the warning:
>
> drivers/net/wireless/ath/ath10k/snoc.c:29:10: fatal error:
> asm/dma-iommu.h: No such file or directory
>
> Any ideas? Adding also Arnd, the grand master of compilation problems 
> :)
>
> Full patch here:
>
> https://patchwork.kernel.org/patch/10220719/
>

The asm/dma-iommu.h header file exsists only on arm32, no other architecture.

I'm not sure about the purpose of the patch to start with:
it's normally up to the platform code to allocate IOMMU domains, device drivers should only need to manually interact with the IOMMU layer if they need more than one domain, but this ath10k patch appears to be using the default domain and should have no effect as long as the platform code works correctly.

       Arnd
Arnd Bergmann March 1, 2018, 1:27 p.m. UTC | #4
On Thu, Mar 1, 2018 at 2:18 PM, Govind Singh <govinds@qti.qualcomm.com> wrote:
>>> The asm/dma-iommu.h header file exsists only on arm32, no other architecture.
>>> I'm not sure about the purpose of the patch to start with:
>>> it's normally up to the platform code to allocate IOMMU domains, device drivers should only need to manually interact with the IOMMU layer if they need more than one domain, but this ath10k patch appears to be using the default domain and should have no effect as long as the platform code works correctly.
> Thanks Arnd, I have fixed this and migrated to  64bit API's(iommu_attach_device/iommu_detach_device/ iommu_get_domain_for_dev), will share the next revision.
> I tried using the default domain by adding the stream ID and mask in dt and no manual interaction, but it is resulting in TZ error and unhandled context fault.
> Seems I need to provide explicit mapping range(aperture_start/ aperture_end) as this is only working combination for me..

I don't see why you need to do that at all, can you clarify?

The IOMMU should be set up implicitly for you here based on the iommus
property in DT,
with no driver changes at all. This should work on all architectures/

       Arnd
Kalle Valo March 8, 2018, 1:50 p.m. UTC | #5
Arnd Bergmann <arnd@arndb.de> writes:

> On Thu, Mar 1, 2018 at 2:18 PM, Govind Singh <govinds@qti.qualcomm.com> wrote:
>>>> The asm/dma-iommu.h header file exsists only on arm32, no other architecture.
>>>> I'm not sure about the purpose of the patch to start with:
>>>> it's normally up to the platform code to allocate IOMMU domains,
>>>> device drivers should only need to manually interact with the
>>>> IOMMU layer if they need more than one domain, but this ath10k
>>>> patch appears to be using the default domain and should have no
>>>> effect as long as the platform code works correctly.
>> Thanks Arnd, I have fixed this and migrated to 64bit
>> API's(iommu_attach_device/iommu_detach_device/
>> iommu_get_domain_for_dev), will share the next revision.
>> I tried using the default domain by adding the stream ID and mask in
>> dt and no manual interaction, but it is resulting in TZ error and
>> unhandled context fault.
>> Seems I need to provide explicit mapping range(aperture_start/
>> aperture_end) as this is only working combination for me..
>
> I don't see why you need to do that at all, can you clarify?
>
> The IOMMU should be set up implicitly for you here based on the iommus
> property in DT, with no driver changes at all. This should work on all
> architectures/

Maybe Govind is using some out-of-tree tree which is buggy in this
regard?
Govind Singh March 8, 2018, 1:59 p.m. UTC | #6
On 2018-03-08 19:20, Kalle Valo wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
> 
>> On Thu, Mar 1, 2018 at 2:18 PM, Govind Singh 
>> <govinds@qti.qualcomm.com> wrote:
>>>>> The asm/dma-iommu.h header file exsists only on arm32, no other 
>>>>> architecture.
>>>>> I'm not sure about the purpose of the patch to start with:
>>>>> it's normally up to the platform code to allocate IOMMU domains,
>>>>> device drivers should only need to manually interact with the
>>>>> IOMMU layer if they need more than one domain, but this ath10k
>>>>> patch appears to be using the default domain and should have no
>>>>> effect as long as the platform code works correctly.
>>> Thanks Arnd, I have fixed this and migrated to 64bit
>>> API's(iommu_attach_device/iommu_detach_device/
>>> iommu_get_domain_for_dev), will share the next revision.
>>> I tried using the default domain by adding the stream ID and mask in
>>> dt and no manual interaction, but it is resulting in TZ error and
>>> unhandled context fault.
>>> Seems I need to provide explicit mapping range(aperture_start/
>>> aperture_end) as this is only working combination for me..
>> 
>> I don't see why you need to do that at all, can you clarify?
>> 
>> The IOMMU should be set up implicitly for you here based on the iommus
>> property in DT, with no driver changes at all. This should work on all
>> architectures/
> 
> Maybe Govind is using some out-of-tree tree which is buggy in this
> regard?

Actually there is limitations in using the iova address range for wlan 
IP.
It can allow certain iova range and i was attaching the iommu to specify 
the iova range.
I am exploring if i can use "dma-ranges" in dt to avoid the manual 
interaction apart from
stream ID and mask.

BR,
Govind
diff mbox

Patch

diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index cd21b25..502263d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -26,6 +26,10 @@ 
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/clk.h>
+#include <asm/dma-iommu.h>
+#include <linux/iommu.h>
+#include <linux/dma-mapping.h>
+
 #define  WCN3990_CE_ATTR_FLAGS 0
 #define ATH10K_SNOC_RX_POST_RETRY_MS 50
 #define CE_POLL_PIPE 4
@@ -1292,6 +1296,88 @@  static int ath10k_hw_power_off(struct ath10k *ar)
 	return ret;
 }
 
+static int ath10k_smmu_attach(struct ath10k *ar)
+{
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	struct dma_iommu_mapping *mapping;
+	struct platform_device *pdev;
+	int ret = 0;
+
+	ath10k_dbg(ar, ATH10K_DBG_SNOC, "Initializing SMMU\n");
+
+	pdev = ar_snoc->dev;
+	mapping = arm_iommu_create_mapping(&platform_bus_type,
+					   ar_snoc->smmu_iova_start,
+					   ar_snoc->smmu_iova_len);
+	if (IS_ERR(mapping)) {
+		ath10k_err(ar, "create mapping failed, err = %d\n", ret);
+		ret = PTR_ERR(mapping);
+		goto map_fail;
+	}
+
+	ret = arm_iommu_attach_device(&pdev->dev, mapping);
+	if (ret < 0 && ret != -EEXIST) {
+		ath10k_err(ar, "iommu attach device failed, err = %d\n", ret);
+		goto attach_fail;
+	} else if (ret == -EEXIST) {
+		ret = 0;
+	}
+
+	ar_snoc->smmu_mapping = mapping;
+
+	return ret;
+
+attach_fail:
+	arm_iommu_release_mapping(mapping);
+map_fail:
+	return ret;
+}
+
+static void ath10k_smmu_deinit(struct ath10k *ar)
+{
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	struct platform_device *pdev;
+
+	pdev = ar_snoc->dev;
+
+	if (!ar_snoc->smmu_mapping)
+		return;
+
+	arm_iommu_detach_device(&pdev->dev);
+	arm_iommu_release_mapping(ar_snoc->smmu_mapping);
+
+	ar_snoc->smmu_mapping = NULL;
+}
+
+static int ath10k_smmu_init(struct ath10k *ar)
+{
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	struct platform_device *pdev;
+	struct resource *res;
+	int ret = 0;
+
+	pdev = ar_snoc->dev;
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "smmu_iova_base");
+	if (!res) {
+		ath10k_err(ar, "SMMU iova base not found\n");
+	} else {
+		ar_snoc->smmu_iova_start = res->start;
+		ar_snoc->smmu_iova_len = resource_size(res);
+		ath10k_dbg(ar, ATH10K_DBG_SNOC, "SMMU iova start: %pa, len: %zu\n",
+			   &ar_snoc->smmu_iova_start, ar_snoc->smmu_iova_len);
+
+		ret = ath10k_smmu_attach(ar);
+		if (ret < 0) {
+			ath10k_err(ar, "SMMU init failed, err = %d, start: %pad, len: %zx\n",
+				   ret, &ar_snoc->smmu_iova_start,
+				   ar_snoc->smmu_iova_len);
+		}
+	}
+
+	return ret;
+}
+
 static const struct of_device_id ath10k_snoc_dt_match[] = {
 	{ .compatible = "qcom,wcn3990-wifi",
 	 .data = &drv_priv,
@@ -1339,16 +1425,22 @@  static int ath10k_snoc_probe(struct platform_device *pdev)
 	ar_snoc->ce.bus_ops = &ath10k_snoc_bus_ops;
 	ar->ce_priv = &ar_snoc->ce;
 
+	ret = ath10k_smmu_init(ar);
+	if (ret) {
+		ath10k_warn(ar, "failed to int SMMU: %d\n", ret);
+		goto err_core_destroy;
+	}
+
 	ath10k_snoc_resource_init(ar);
 	if (ret) {
 		ath10k_warn(ar, "failed to initialize resource: %d\n", ret);
-		goto err_core_destroy;
+		goto err_smmu_deinit;
 	}
 
 	ath10k_snoc_setup_resource(ar);
 	if (ret) {
 		ath10k_warn(ar, "failed to setup resource: %d\n", ret);
-		goto err_core_destroy;
+		goto err_smmu_deinit;
 	}
 	ret = ath10k_snoc_request_irq(ar);
 	if (ret) {
@@ -1396,6 +1488,9 @@  static int ath10k_snoc_probe(struct platform_device *pdev)
 err_release_resource:
 	ath10k_snoc_release_resource(ar);
 
+err_smmu_deinit:
+	ath10k_smmu_deinit(ar);
+
 err_core_destroy:
 	ath10k_core_destroy(ar);
 
@@ -1409,6 +1504,7 @@  static int ath10k_snoc_remove(struct platform_device *pdev)
 	ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc remove\n");
 	ath10k_core_unregister(ar);
 	ath10k_hw_power_off(ar);
+	ath10k_smmu_deinit(ar);
 	ath10k_snoc_free_irq(ar);
 	ath10k_snoc_release_resource(ar);
 	ath10k_core_destroy(ar);
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index 05dc98f..a9bca2e 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -82,6 +82,9 @@  struct ath10k_snoc {
 	struct timer_list rx_post_retry;
 	struct ath10k_wcn3990_vreg_info *vreg;
 	struct ath10k_wcn3990_clk_info *clk;
+	struct dma_iommu_mapping *smmu_mapping;
+	dma_addr_t smmu_iova_start;
+	size_t smmu_iova_len;
 };
 
 static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)