linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Add support to handle targets without TrustZone
@ 2020-03-25 11:01 Rakesh Pillai
  2020-03-25 11:01 ` [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode for wifi node Rakesh Pillai
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Rakesh Pillai @ 2020-03-25 11:01 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, devicetree, linux-kernel, Rakesh Pillai

The iommu mapping for S2 SIDs are taken care by TrustZone.
For the targets which does not have the support of TrustZone,
these mappings need to be created in the driver using an
iommu domain.

Leaving these SIDs unconfigured will result in a global
smmu fault. Hence configuring them for Non-TrustZone targets
is mandatory.

Changes from v1:
- Rebase and fix compilation errors on latest ath10k tree tip

Rakesh Pillai (3):
  dt-bindings: ath10k: Add wifi-firmware subnode for wifi node
  ath10k: Setup the msa resources before qmi init
  ath10k: Add support for targets without trustzone

 .../bindings/net/wireless/qcom,ath10k.txt          |  14 ++
 drivers/net/wireless/ath/ath10k/core.h             |   5 +
 drivers/net/wireless/ath/ath10k/qmi.c              |  61 +------
 drivers/net/wireless/ath/ath10k/qmi.h              |   3 -
 drivers/net/wireless/ath/ath10k/snoc.c             | 182 ++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/snoc.h             |   7 +
 6 files changed, 208 insertions(+), 64 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode for wifi node
  2020-03-25 11:01 [PATCH v2 0/3] Add support to handle targets without TrustZone Rakesh Pillai
@ 2020-03-25 11:01 ` Rakesh Pillai
  2020-03-31 21:40   ` Rob Herring
  2020-03-25 11:01 ` [PATCH v2 2/3] ath10k: Setup the msa resources before qmi init Rakesh Pillai
  2020-03-25 11:01 ` [PATCH v2 3/3] ath10k: Add support for targets without trustzone Rakesh Pillai
  2 siblings, 1 reply; 7+ messages in thread
From: Rakesh Pillai @ 2020-03-25 11:01 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, devicetree, linux-kernel, Rakesh Pillai

Add a wifi-firmware subnode for the wifi node.
This wifi-firmware subnode is needed for the
targets which do not support TrustZone.

Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
---
 .../devicetree/bindings/net/wireless/qcom,ath10k.txt       | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
index 71bf91f..65ee68e 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
@@ -96,6 +96,17 @@ Optional properties:
 - qcom,coexist-gpio-pin : gpio pin number  information to support coex
 			  which will be used by wifi firmware.
 
+* Subnodes
+The ath10k wifi node can contain one optional firmware subnode.
+Firmware subnode is needed when the platform does not have TustZone.
+The firmware subnode must have:
+
+- iommus:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A list of phandle and IOMMU specifier pairs.
+
+
 Example (to supply PCI based wifi block details):
 
 In this example, the node is defined as child node of the PCI controller.
@@ -196,4 +207,7 @@ wifi@18000000 {
 		memory-region = <&wifi_msa_mem>;
 		iommus = <&apps_smmu 0x0040 0x1>;
 		qcom,msa-fixed-perm;
+		wifi-firmware {
+			iommus = <&apps_iommu 0xc22 0x1>;
+		};
 };
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/3] ath10k: Setup the msa resources before qmi init
  2020-03-25 11:01 [PATCH v2 0/3] Add support to handle targets without TrustZone Rakesh Pillai
  2020-03-25 11:01 ` [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode for wifi node Rakesh Pillai
@ 2020-03-25 11:01 ` Rakesh Pillai
  2020-03-25 11:01 ` [PATCH v2 3/3] ath10k: Add support for targets without trustzone Rakesh Pillai
  2 siblings, 0 replies; 7+ messages in thread
From: Rakesh Pillai @ 2020-03-25 11:01 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, devicetree, linux-kernel, Rakesh Pillai

Move the msa resources setup out of qmi init and
setup the msa resources as a part of probe before
the qmi init is done.

Tested HW: WCN3990
Tested FW: WLAN.HL.3.1-01040-QCAHLSWMTPLZ-1

Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/core.h |  5 +++
 drivers/net/wireless/ath/ath10k/qmi.c  | 61 +++++---------------------------
 drivers/net/wireless/ath/ath10k/qmi.h  |  3 --
 drivers/net/wireless/ath/ath10k/snoc.c | 64 ++++++++++++++++++++++++++++++----
 4 files changed, 70 insertions(+), 63 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index bd8ef57..89d5c07 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -949,6 +949,11 @@ struct ath10k {
 	struct ieee80211_hw *hw;
 	struct ieee80211_ops *ops;
 	struct device *dev;
+	struct msa_region {
+		dma_addr_t paddr;
+		u32 mem_size;
+		void *vaddr;
+	} msa;
 	u8 mac_addr[ETH_ALEN];
 
 	enum ath10k_hw_rev hw_rev;
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 85dce43..5ae829b 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -122,8 +122,8 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
 	int ret;
 	int i;
 
-	req.msa_addr = qmi->msa_pa;
-	req.size = qmi->msa_mem_size;
+	req.msa_addr = ar->msa.paddr;
+	req.size = ar->msa.mem_size;
 
 	ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
 			   wlfw_msa_info_resp_msg_v01_ei, &resp);
@@ -157,12 +157,12 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
 		goto out;
 	}
 
-	max_mapped_addr = qmi->msa_pa + qmi->msa_mem_size;
+	max_mapped_addr = ar->msa.paddr + ar->msa.mem_size;
 	qmi->nr_mem_region = resp.mem_region_info_len;
 	for (i = 0; i < resp.mem_region_info_len; i++) {
-		if (resp.mem_region_info[i].size > qmi->msa_mem_size ||
+		if (resp.mem_region_info[i].size > ar->msa.mem_size ||
 		    resp.mem_region_info[i].region_addr > max_mapped_addr ||
-		    resp.mem_region_info[i].region_addr < qmi->msa_pa ||
+		    resp.mem_region_info[i].region_addr < ar->msa.paddr ||
 		    resp.mem_region_info[i].size +
 		    resp.mem_region_info[i].region_addr > max_mapped_addr) {
 			ath10k_err(ar, "received out of range memory region address 0x%llx with size 0x%x, aborting\n",
@@ -1006,54 +1006,10 @@ static void ath10k_qmi_driver_event_work(struct work_struct *work)
 	spin_unlock(&qmi->event_lock);
 }
 
-static int ath10k_qmi_setup_msa_resources(struct ath10k_qmi *qmi, u32 msa_size)
-{
-	struct ath10k *ar = qmi->ar;
-	struct device *dev = ar->dev;
-	struct device_node *node;
-	struct resource r;
-	int ret;
-
-	node = of_parse_phandle(dev->of_node, "memory-region", 0);
-	if (node) {
-		ret = of_address_to_resource(node, 0, &r);
-		if (ret) {
-			dev_err(dev, "failed to resolve msa fixed region\n");
-			return ret;
-		}
-		of_node_put(node);
-
-		qmi->msa_pa = r.start;
-		qmi->msa_mem_size = resource_size(&r);
-		qmi->msa_va = devm_memremap(dev, qmi->msa_pa, qmi->msa_mem_size,
-					    MEMREMAP_WT);
-		if (IS_ERR(qmi->msa_va)) {
-			dev_err(dev, "failed to map memory region: %pa\n", &r.start);
-			return PTR_ERR(qmi->msa_va);
-		}
-	} else {
-		qmi->msa_va = dmam_alloc_coherent(dev, msa_size,
-						  &qmi->msa_pa, GFP_KERNEL);
-		if (!qmi->msa_va) {
-			ath10k_err(ar, "failed to allocate dma memory for msa region\n");
-			return -ENOMEM;
-		}
-		qmi->msa_mem_size = msa_size;
-	}
-
-	if (of_property_read_bool(dev->of_node, "qcom,msa-fixed-perm"))
-		qmi->msa_fixed_perm = true;
-
-	ath10k_dbg(ar, ATH10K_DBG_QMI, "msa pa: %pad , msa va: 0x%p\n",
-		   &qmi->msa_pa,
-		   qmi->msa_va);
-
-	return 0;
-}
-
 int ath10k_qmi_init(struct ath10k *ar, u32 msa_size)
 {
 	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	struct device *dev = ar->dev;
 	struct ath10k_qmi *qmi;
 	int ret;
 
@@ -1064,9 +1020,8 @@ int ath10k_qmi_init(struct ath10k *ar, u32 msa_size)
 	qmi->ar = ar;
 	ar_snoc->qmi = qmi;
 
-	ret = ath10k_qmi_setup_msa_resources(qmi, msa_size);
-	if (ret)
-		goto err;
+	if (of_property_read_bool(dev->of_node, "qcom,msa-fixed-perm"))
+		qmi->msa_fixed_perm = true;
 
 	ret = qmi_handle_init(&qmi->qmi_hdl,
 			      WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
diff --git a/drivers/net/wireless/ath/ath10k/qmi.h b/drivers/net/wireless/ath/ath10k/qmi.h
index dc25737..450be18 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.h
+++ b/drivers/net/wireless/ath/ath10k/qmi.h
@@ -93,9 +93,6 @@ struct ath10k_qmi {
 	spinlock_t event_lock; /* spinlock for qmi event list */
 	u32 nr_mem_region;
 	struct ath10k_msa_mem_info mem_region[MAX_NUM_MEMORY_REGIONS];
-	dma_addr_t msa_pa;
-	u32 msa_mem_size;
-	void *msa_va;
 	struct ath10k_qmi_chip_info chip_info;
 	struct ath10k_qmi_board_info board_info;
 	struct ath10k_qmi_soc_info soc_info;
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 21081b4..3633ea5 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of_address.h>
 
 #include "ce.h"
 #include "coredump.h"
@@ -1393,7 +1394,6 @@ static int ath10k_hw_power_off(struct ath10k *ar)
 static void ath10k_msa_dump_memory(struct ath10k *ar,
 				   struct ath10k_fw_crash_data *crash_data)
 {
-	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
 	const struct ath10k_hw_mem_layout *mem_layout;
 	const struct ath10k_mem_region *current_region;
 	struct ath10k_dump_ram_data_hdr *hdr;
@@ -1419,15 +1419,15 @@ static void ath10k_msa_dump_memory(struct ath10k *ar,
 	buf_len -= sizeof(*hdr);
 
 	hdr->region_type = cpu_to_le32(current_region->type);
-	hdr->start = cpu_to_le32((unsigned long)ar_snoc->qmi->msa_va);
-	hdr->length = cpu_to_le32(ar_snoc->qmi->msa_mem_size);
+	hdr->start = cpu_to_le32((unsigned long)ar->msa.vaddr);
+	hdr->length = cpu_to_le32(ar->msa.mem_size);
 
-	if (current_region->len < ar_snoc->qmi->msa_mem_size) {
-		memcpy(buf, ar_snoc->qmi->msa_va, current_region->len);
+	if (current_region->len < ar->msa.mem_size) {
+		memcpy(buf, ar->msa.vaddr, current_region->len);
 		ath10k_warn(ar, "msa dump length is less than msa size %x, %x\n",
-			    current_region->len, ar_snoc->qmi->msa_mem_size);
+			    current_region->len, ar->msa.mem_size);
 	} else {
-		memcpy(buf, ar_snoc->qmi->msa_va, ar_snoc->qmi->msa_mem_size);
+		memcpy(buf, ar->msa.vaddr, ar->msa.mem_size);
 	}
 }
 
@@ -1455,6 +1455,50 @@ void ath10k_snoc_fw_crashed_dump(struct ath10k *ar)
 	mutex_unlock(&ar->dump_mutex);
 }
 
+static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size)
+{
+	struct device *dev = ar->dev;
+	struct device_node *node;
+	struct resource r;
+	int ret;
+
+	node = of_parse_phandle(dev->of_node, "memory-region", 0);
+	if (node) {
+		ret = of_address_to_resource(node, 0, &r);
+		if (ret) {
+			dev_err(dev, "failed to resolve msa fixed region\n");
+			return ret;
+		}
+		of_node_put(node);
+
+		ar->msa.paddr = r.start;
+		ar->msa.mem_size = resource_size(&r);
+		ar->msa.vaddr = devm_memremap(dev, ar->msa.paddr,
+					      ar->msa.mem_size,
+					      MEMREMAP_WT);
+		if (IS_ERR(ar->msa.vaddr)) {
+			dev_err(dev, "failed to map memory region: %pa\n",
+				&r.start);
+			return PTR_ERR(ar->msa.vaddr);
+		}
+	} else {
+		ar->msa.vaddr = dmam_alloc_coherent(dev, msa_size,
+						    &ar->msa.paddr,
+						    GFP_KERNEL);
+		if (!ar->msa.vaddr) {
+			ath10k_err(ar, "failed to allocate dma memory for msa region\n");
+			return -ENOMEM;
+		}
+		ar->msa.mem_size = msa_size;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa.paddr: %pad , msa.vaddr: 0x%p\n",
+		   &ar->msa.paddr,
+		   ar->msa.vaddr);
+
+	return 0;
+}
+
 static const struct of_device_id ath10k_snoc_dt_match[] = {
 	{ .compatible = "qcom,wcn3990-wifi",
 	 .data = &drv_priv,
@@ -1557,6 +1601,12 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
 		goto err_free_irq;
 	}
 
+	ret = ath10k_setup_msa_resources(ar, msa_size);
+	if (ret) {
+		ath10k_warn(ar, "failed to setup msa resources: %d\n", ret);
+		goto err_power_off;
+	}
+
 	ret = ath10k_qmi_init(ar, msa_size);
 	if (ret) {
 		ath10k_warn(ar, "failed to register wlfw qmi client: %d\n", ret);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/3] ath10k: Add support for targets without trustzone
  2020-03-25 11:01 [PATCH v2 0/3] Add support to handle targets without TrustZone Rakesh Pillai
  2020-03-25 11:01 ` [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode for wifi node Rakesh Pillai
  2020-03-25 11:01 ` [PATCH v2 2/3] ath10k: Setup the msa resources before qmi init Rakesh Pillai
@ 2020-03-25 11:01 ` Rakesh Pillai
  2020-04-15 17:33   ` pillair
  2 siblings, 1 reply; 7+ messages in thread
From: Rakesh Pillai @ 2020-03-25 11:01 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, devicetree, linux-kernel, Rakesh Pillai

Add the support to attach and map iommu
domain for targets which do not have the
support of TrustZone.

Tested HW: WCN3990
Tested FW: WLAN.HL.3.1-01040-QCAHLSWMTPLZ-1

Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/snoc.c | 118 ++++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/snoc.h |   7 ++
 2 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 3633ea5..7a7e79b 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -12,6 +12,7 @@
 #include <linux/property.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of_address.h>
+#include <linux/iommu.h>
 
 #include "ce.h"
 #include "coredump.h"
@@ -1499,6 +1500,111 @@ static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size)
 	return 0;
 }
 
+static int ath10k_fw_init(struct ath10k *ar)
+{
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	struct device *host_dev = &ar_snoc->dev->dev;
+	struct platform_device_info info;
+	struct iommu_domain *iommu_dom;
+	struct platform_device *pdev;
+	struct device_node *node;
+	int ret;
+
+	node = of_get_child_by_name(host_dev->of_node, "wifi-firmware");
+	if (!node) {
+		ar_snoc->use_tz = true;
+		return 0;
+	}
+
+	memset(&info, 0, sizeof(info));
+	info.fwnode = &node->fwnode;
+	info.parent = host_dev;
+	info.name = node->name;
+	info.dma_mask = DMA_BIT_MASK(32);
+
+	pdev = platform_device_register_full(&info);
+	if (IS_ERR(pdev)) {
+		of_node_put(node);
+		return PTR_ERR(pdev);
+	}
+
+	pdev->dev.of_node = node;
+
+	ret = of_dma_configure(&pdev->dev, node, true);
+	if (ret) {
+		ath10k_err(ar, "dma configure fail: %d\n", ret);
+		goto err_unregister;
+	}
+
+	ar_snoc->fw.dev = &pdev->dev;
+
+	iommu_dom = iommu_domain_alloc(&platform_bus_type);
+	if (!iommu_dom) {
+		ath10k_err(ar, "failed to allocate iommu domain\n");
+		ret = -ENOMEM;
+		goto err_unregister;
+	}
+
+	ret = iommu_attach_device(iommu_dom, ar_snoc->fw.dev);
+	if (ret) {
+		ath10k_err(ar, "could not attach device: %d\n", ret);
+		goto err_iommu_free;
+	}
+
+	ar_snoc->fw.iommu_domain = iommu_dom;
+	ar_snoc->fw.fw_start_addr = ar->msa.paddr;
+
+	ret = iommu_map(iommu_dom, ar_snoc->fw.fw_start_addr,
+			ar->msa.paddr, ar->msa.mem_size,
+			IOMMU_READ | IOMMU_WRITE);
+	if (ret) {
+		ath10k_err(ar, "failed to map firmware region: %d\n", ret);
+		goto err_iommu_detach;
+	}
+
+	of_node_put(node);
+
+	return 0;
+
+err_iommu_detach:
+	iommu_detach_device(iommu_dom, ar_snoc->fw.dev);
+
+err_iommu_free:
+	iommu_domain_free(iommu_dom);
+
+err_unregister:
+	platform_device_unregister(pdev);
+	of_node_put(node);
+
+	return ret;
+}
+
+static int ath10k_fw_deinit(struct ath10k *ar)
+{
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	const size_t mapped_size = ar_snoc->fw.mapped_mem_size;
+	struct iommu_domain *iommu;
+	size_t unmapped_size;
+
+	if (ar_snoc->use_tz)
+		return 0;
+
+	iommu = ar_snoc->fw.iommu_domain;
+
+	unmapped_size = iommu_unmap(iommu, ar_snoc->fw.fw_start_addr,
+				    mapped_size);
+	if (unmapped_size != mapped_size)
+		ath10k_err(ar, "failed to unmap firmware: %zu\n",
+			   unmapped_size);
+
+	iommu_detach_device(iommu, ar_snoc->fw.dev);
+	iommu_domain_free(iommu);
+
+	platform_device_unregister(to_platform_device(ar_snoc->fw.dev));
+
+	return 0;
+}
+
 static const struct of_device_id ath10k_snoc_dt_match[] = {
 	{ .compatible = "qcom,wcn3990-wifi",
 	 .data = &drv_priv,
@@ -1607,16 +1713,25 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
 		goto err_power_off;
 	}
 
+	ret = ath10k_fw_init(ar);
+	if (ret) {
+		ath10k_err(ar, "failed to initialize firmware: %d\n", ret);
+		goto err_power_off;
+	}
+
 	ret = ath10k_qmi_init(ar, msa_size);
 	if (ret) {
 		ath10k_warn(ar, "failed to register wlfw qmi client: %d\n", ret);
-		goto err_power_off;
+		goto err_fw_deinit;
 	}
 
 	ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n");
 
 	return 0;
 
+err_fw_deinit:
+	ath10k_fw_deinit(ar);
+
 err_power_off:
 	ath10k_hw_power_off(ar);
 
@@ -1648,6 +1763,7 @@ static int ath10k_snoc_remove(struct platform_device *pdev)
 
 	ath10k_core_unregister(ar);
 	ath10k_hw_power_off(ar);
+	ath10k_fw_deinit(ar);
 	ath10k_snoc_free_irq(ar);
 	ath10k_snoc_release_resource(ar);
 	ath10k_qmi_deinit(ar);
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index c05df45..18e19fb 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -55,6 +55,13 @@ struct regulator_bulk_data;
 struct ath10k_snoc {
 	struct platform_device *dev;
 	struct ath10k *ar;
+	unsigned int use_tz;
+	struct video_firmware {
+		struct device *dev;
+		dma_addr_t fw_start_addr;
+		struct iommu_domain *iommu_domain;
+		size_t mapped_mem_size;
+	} fw;
 	void __iomem *mem;
 	dma_addr_t mem_pa;
 	struct ath10k_snoc_target_info target_info;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode for wifi node
  2020-03-25 11:01 ` [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode for wifi node Rakesh Pillai
@ 2020-03-31 21:40   ` Rob Herring
  2020-04-01  7:30     ` pillair
  0 siblings, 1 reply; 7+ messages in thread
From: Rob Herring @ 2020-03-31 21:40 UTC (permalink / raw)
  To: Rakesh Pillai; +Cc: ath10k, linux-wireless, devicetree, linux-kernel

On Wed, Mar 25, 2020 at 04:31:38PM +0530, Rakesh Pillai wrote:
> Add a wifi-firmware subnode for the wifi node.
> This wifi-firmware subnode is needed for the
> targets which do not support TrustZone.
> 
> Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
> ---
>  .../devicetree/bindings/net/wireless/qcom,ath10k.txt       | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> index 71bf91f..65ee68e 100644
> --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> @@ -96,6 +96,17 @@ Optional properties:
>  - qcom,coexist-gpio-pin : gpio pin number  information to support coex
>  			  which will be used by wifi firmware.
>  
> +* Subnodes
> +The ath10k wifi node can contain one optional firmware subnode.
> +Firmware subnode is needed when the platform does not have TustZone.
> +The firmware subnode must have:
> +
> +- iommus:
> +	Usage: required
> +	Value type: <prop-encoded-array>
> +	Definition: A list of phandle and IOMMU specifier pairs.
> +
> +
>  Example (to supply PCI based wifi block details):
>  
>  In this example, the node is defined as child node of the PCI controller.
> @@ -196,4 +207,7 @@ wifi@18000000 {
>  		memory-region = <&wifi_msa_mem>;
>  		iommus = <&apps_smmu 0x0040 0x1>;
>  		qcom,msa-fixed-perm;
> +		wifi-firmware {
> +			iommus = <&apps_iommu 0xc22 0x1>;

Why can't you just add a 2nd entry to the existing 'iommus' property? 

A driver doing of_dma_configure() is generally not the right thing to 
do.

Rob

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode for wifi node
  2020-03-31 21:40   ` Rob Herring
@ 2020-04-01  7:30     ` pillair
  0 siblings, 0 replies; 7+ messages in thread
From: pillair @ 2020-04-01  7:30 UTC (permalink / raw)
  To: 'Rob Herring'; +Cc: ath10k, linux-wireless, devicetree, linux-kernel

Hi Rob,
Comments inline.

> -----Original Message-----
> From: Rob Herring <robh@kernel.org>
> Sent: Wednesday, April 1, 2020 3:11 AM
> To: Rakesh Pillai <pillair@codeaurora.org>
> Cc: ath10k@lists.infradead.org; linux-wireless@vger.kernel.org;
> devicetree@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode
> for wifi node
> 
> On Wed, Mar 25, 2020 at 04:31:38PM +0530, Rakesh Pillai wrote:
> > Add a wifi-firmware subnode for the wifi node.
> > This wifi-firmware subnode is needed for the
> > targets which do not support TrustZone.
> >
> > Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
> > ---
> >  .../devicetree/bindings/net/wireless/qcom,ath10k.txt       | 14
> ++++++++++++++
> >  1 file changed, 14 insertions(+)
> >
> > diff --git
> a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> > index 71bf91f..65ee68e 100644
> > --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> > +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> > @@ -96,6 +96,17 @@ Optional properties:
> >  - qcom,coexist-gpio-pin : gpio pin number  information to support coex
> >  			  which will be used by wifi firmware.
> >
> > +* Subnodes
> > +The ath10k wifi node can contain one optional firmware subnode.
> > +Firmware subnode is needed when the platform does not have TustZone.
> > +The firmware subnode must have:
> > +
> > +- iommus:
> > +	Usage: required
> > +	Value type: <prop-encoded-array>
> > +	Definition: A list of phandle and IOMMU specifier pairs.
> > +
> > +
> >  Example (to supply PCI based wifi block details):
> >
> >  In this example, the node is defined as child node of the PCI
controller.
> > @@ -196,4 +207,7 @@ wifi@18000000 {
> >  		memory-region = <&wifi_msa_mem>;
> >  		iommus = <&apps_smmu 0x0040 0x1>;
> >  		qcom,msa-fixed-perm;
> > +		wifi-firmware {
> > +			iommus = <&apps_iommu 0xc22 0x1>;
> 
> Why can't you just add a 2nd entry to the existing 'iommus' property?
> 
> A driver doing of_dma_configure() is generally not the right thing to
> do.

The SIDs mentioned in the wifi-firmware node will be belonging to the
firmware and not any HLOS.
In other targets with TZ, the hypervisor takes care of configuring the SIDs
(for its master).
In this target (sc7180 IDP) we are not having TZ (no hypervisor), hence
these need to be configured by HLOS.
The wifi-firmware node is added in-order to differentiate the SID between
driver and firmware.

This is same as the approach followed by Venus video driver in the below
patch
https://patchwork.kernel.org/patch/11315765/ 

> 
> Rob

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH v2 3/3] ath10k: Add support for targets without trustzone
  2020-03-25 11:01 ` [PATCH v2 3/3] ath10k: Add support for targets without trustzone Rakesh Pillai
@ 2020-04-15 17:33   ` pillair
  0 siblings, 0 replies; 7+ messages in thread
From: pillair @ 2020-04-15 17:33 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, devicetree, linux-kernel

Hi Kalle,

I have sent out v3 for this patchset after correcting the firmware structure
name which was added in ath10k snoc structure

Thanks,
Rakesh Pillai.

> -----Original Message-----
> From: Rakesh Pillai <pillair@codeaurora.org>
> Sent: Wednesday, March 25, 2020 4:32 PM
> To: ath10k@lists.infradead.org
> Cc: linux-wireless@vger.kernel.org; devicetree@vger.kernel.org; linux-
> kernel@vger.kernel.org; Rakesh Pillai <pillair@codeaurora.org>
> Subject: [PATCH v2 3/3] ath10k: Add support for targets without trustzone
> 
> Add the support to attach and map iommu
> domain for targets which do not have the
> support of TrustZone.
> 
> Tested HW: WCN3990
> Tested FW: WLAN.HL.3.1-01040-QCAHLSWMTPLZ-1
> 
> Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
> ---
>  drivers/net/wireless/ath/ath10k/snoc.c | 118
> ++++++++++++++++++++++++++++++++-
>  drivers/net/wireless/ath/ath10k/snoc.h |   7 ++
>  2 files changed, 124 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/snoc.c
> b/drivers/net/wireless/ath/ath10k/snoc.c
> index 3633ea5..7a7e79b 100644
> --- a/drivers/net/wireless/ath/ath10k/snoc.c
> +++ b/drivers/net/wireless/ath/ath10k/snoc.c
> @@ -12,6 +12,7 @@
>  #include <linux/property.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/of_address.h>
> +#include <linux/iommu.h>
> 
>  #include "ce.h"
>  #include "coredump.h"
> @@ -1499,6 +1500,111 @@ static int ath10k_setup_msa_resources(struct
> ath10k *ar, u32 msa_size)
>  	return 0;
>  }
> 
> +static int ath10k_fw_init(struct ath10k *ar)
> +{
> +	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
> +	struct device *host_dev = &ar_snoc->dev->dev;
> +	struct platform_device_info info;
> +	struct iommu_domain *iommu_dom;
> +	struct platform_device *pdev;
> +	struct device_node *node;
> +	int ret;
> +
> +	node = of_get_child_by_name(host_dev->of_node, "wifi-
> firmware");
> +	if (!node) {
> +		ar_snoc->use_tz = true;
> +		return 0;
> +	}
> +
> +	memset(&info, 0, sizeof(info));
> +	info.fwnode = &node->fwnode;
> +	info.parent = host_dev;
> +	info.name = node->name;
> +	info.dma_mask = DMA_BIT_MASK(32);
> +
> +	pdev = platform_device_register_full(&info);
> +	if (IS_ERR(pdev)) {
> +		of_node_put(node);
> +		return PTR_ERR(pdev);
> +	}
> +
> +	pdev->dev.of_node = node;
> +
> +	ret = of_dma_configure(&pdev->dev, node, true);
> +	if (ret) {
> +		ath10k_err(ar, "dma configure fail: %d\n", ret);
> +		goto err_unregister;
> +	}
> +
> +	ar_snoc->fw.dev = &pdev->dev;
> +
> +	iommu_dom = iommu_domain_alloc(&platform_bus_type);
> +	if (!iommu_dom) {
> +		ath10k_err(ar, "failed to allocate iommu domain\n");
> +		ret = -ENOMEM;
> +		goto err_unregister;
> +	}
> +
> +	ret = iommu_attach_device(iommu_dom, ar_snoc->fw.dev);
> +	if (ret) {
> +		ath10k_err(ar, "could not attach device: %d\n", ret);
> +		goto err_iommu_free;
> +	}
> +
> +	ar_snoc->fw.iommu_domain = iommu_dom;
> +	ar_snoc->fw.fw_start_addr = ar->msa.paddr;
> +
> +	ret = iommu_map(iommu_dom, ar_snoc->fw.fw_start_addr,
> +			ar->msa.paddr, ar->msa.mem_size,
> +			IOMMU_READ | IOMMU_WRITE);
> +	if (ret) {
> +		ath10k_err(ar, "failed to map firmware region: %d\n", ret);
> +		goto err_iommu_detach;
> +	}
> +
> +	of_node_put(node);
> +
> +	return 0;
> +
> +err_iommu_detach:
> +	iommu_detach_device(iommu_dom, ar_snoc->fw.dev);
> +
> +err_iommu_free:
> +	iommu_domain_free(iommu_dom);
> +
> +err_unregister:
> +	platform_device_unregister(pdev);
> +	of_node_put(node);
> +
> +	return ret;
> +}
> +
> +static int ath10k_fw_deinit(struct ath10k *ar)
> +{
> +	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
> +	const size_t mapped_size = ar_snoc->fw.mapped_mem_size;
> +	struct iommu_domain *iommu;
> +	size_t unmapped_size;
> +
> +	if (ar_snoc->use_tz)
> +		return 0;
> +
> +	iommu = ar_snoc->fw.iommu_domain;
> +
> +	unmapped_size = iommu_unmap(iommu, ar_snoc-
> >fw.fw_start_addr,
> +				    mapped_size);
> +	if (unmapped_size != mapped_size)
> +		ath10k_err(ar, "failed to unmap firmware: %zu\n",
> +			   unmapped_size);
> +
> +	iommu_detach_device(iommu, ar_snoc->fw.dev);
> +	iommu_domain_free(iommu);
> +
> +	platform_device_unregister(to_platform_device(ar_snoc->fw.dev));
> +
> +	return 0;
> +}
> +
>  static const struct of_device_id ath10k_snoc_dt_match[] = {
>  	{ .compatible = "qcom,wcn3990-wifi",
>  	 .data = &drv_priv,
> @@ -1607,16 +1713,25 @@ static int ath10k_snoc_probe(struct
> platform_device *pdev)
>  		goto err_power_off;
>  	}
> 
> +	ret = ath10k_fw_init(ar);
> +	if (ret) {
> +		ath10k_err(ar, "failed to initialize firmware: %d\n", ret);
> +		goto err_power_off;
> +	}
> +
>  	ret = ath10k_qmi_init(ar, msa_size);
>  	if (ret) {
>  		ath10k_warn(ar, "failed to register wlfw qmi client: %d\n",
> ret);
> -		goto err_power_off;
> +		goto err_fw_deinit;
>  	}
> 
>  	ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n");
> 
>  	return 0;
> 
> +err_fw_deinit:
> +	ath10k_fw_deinit(ar);
> +
>  err_power_off:
>  	ath10k_hw_power_off(ar);
> 
> @@ -1648,6 +1763,7 @@ static int ath10k_snoc_remove(struct
> platform_device *pdev)
> 
>  	ath10k_core_unregister(ar);
>  	ath10k_hw_power_off(ar);
> +	ath10k_fw_deinit(ar);
>  	ath10k_snoc_free_irq(ar);
>  	ath10k_snoc_release_resource(ar);
>  	ath10k_qmi_deinit(ar);
> diff --git a/drivers/net/wireless/ath/ath10k/snoc.h
> b/drivers/net/wireless/ath/ath10k/snoc.h
> index c05df45..18e19fb 100644
> --- a/drivers/net/wireless/ath/ath10k/snoc.h
> +++ b/drivers/net/wireless/ath/ath10k/snoc.h
> @@ -55,6 +55,13 @@ struct regulator_bulk_data;
>  struct ath10k_snoc {
>  	struct platform_device *dev;
>  	struct ath10k *ar;
> +	unsigned int use_tz;
> +	struct video_firmware {
> +		struct device *dev;
> +		dma_addr_t fw_start_addr;
> +		struct iommu_domain *iommu_domain;
> +		size_t mapped_mem_size;
> +	} fw;
>  	void __iomem *mem;
>  	dma_addr_t mem_pa;
>  	struct ath10k_snoc_target_info target_info;
> --
> 2.7.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-04-15 17:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-25 11:01 [PATCH v2 0/3] Add support to handle targets without TrustZone Rakesh Pillai
2020-03-25 11:01 ` [PATCH v2 1/3] dt-bindings: ath10k: Add wifi-firmware subnode for wifi node Rakesh Pillai
2020-03-31 21:40   ` Rob Herring
2020-04-01  7:30     ` pillair
2020-03-25 11:01 ` [PATCH v2 2/3] ath10k: Setup the msa resources before qmi init Rakesh Pillai
2020-03-25 11:01 ` [PATCH v2 3/3] ath10k: Add support for targets without trustzone Rakesh Pillai
2020-04-15 17:33   ` pillair

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).