ソースを参照

qcacld-3.0: Add support for WLAN-IPA SMMU Stage 1 translation

Update WLAN-IPA datapath buffer sharing for SMMU Stage 1
translation support. When SMMU Stage 1 translation is enabled,
DMA APIs return IO virtual address(IOVA) instead of physical
address. This IOVA needs to be mapped to physical address by IPA
module before accessing them.

Change-Id: I6b24cde7b7805395053a8fd8f9afbad202e6105f
CRS-Fixed: 2072960
Himanshu Agarwal 7 年 前
コミット
edf30dc042

+ 5 - 0
Kbuild

@@ -2498,6 +2498,11 @@ ifeq ($(CONFIG_DYNAMIC_DEBUG),y)
 CDEFINES += -DFEATURE_MULTICAST_HOST_FW_MSGS
 endif
 
+#Flag to enable SMMU S1 support
+ifeq ($(CONFIG_ARCH_SDM845), y)
+CDEFINES += -DENABLE_SMMU_S1_TRANSLATION
+endif
+
 KBUILD_CPPFLAGS += $(CDEFINES)
 
 # Currently, for versions of gcc which support it, the kernel Makefile

+ 25 - 0
core/cds/inc/cds_api.h

@@ -593,4 +593,29 @@ bool cds_is_group_addr(uint8_t *mac_addr)
 uint32_t cds_get_arp_stats_gw_ip(void);
 void cds_incr_arp_stats_tx_tgt_delivered(void);
 void cds_incr_arp_stats_tx_tgt_acked(void);
+
+/**
+ * cds_smmu_mem_map_setup() - Check SMMU S1 stage enable
+ *                            status and setup wlan driver
+ * @osdev: Parent device instance
+ *
+ * This API checks if SMMU S1 translation is enabled in
+ * platform driver or not and sets it accordingly in driver.
+ *
+ * Return: none
+ */
+void cds_smmu_mem_map_setup(qdf_device_t osdev);
+
+/**
+ * cds_smmu_map_unmap() - Map / Unmap DMA buffer to IPA UC
+ * @map: Map / unmap operation
+ * @num_buf: Number of buffers in array
+ * @buf_arr: Buffer array of DMA mem mapping info
+ *
+ * This API maps/unmaps WLAN-IPA buffers if SMMU S1 translation
+ * is enabled.
+ *
+ * Return: Status of map operation
+ */
+int cds_smmu_map_unmap(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr);
 #endif /* if !defined __CDS_API_H */

+ 40 - 0
core/cds/src/cds_api.c

@@ -71,6 +71,13 @@
 #include "wlan_ocb_ucfg_api.h"
 #include "qdf_platform.h"
 
+#ifdef ENABLE_SMMU_S1_TRANSLATION
+#include "pld_common.h"
+#include <asm/dma-iommu.h>
+#include <linux/iommu.h>
+#endif
+/* Preprocessor Definitions and Constants */
+
 /* Preprocessor Definitions and Constants */
 
 /* Data definitions */
@@ -2836,3 +2843,36 @@ void cds_incr_arp_stats_tx_tgt_acked(void)
 	if (adapter)
 		adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt++;
 }
+
+#ifdef ENABLE_SMMU_S1_TRANSLATION
+void cds_smmu_mem_map_setup(qdf_device_t osdev)
+{
+	int attr = 0;
+	struct dma_iommu_mapping *mapping = pld_smmu_get_mapping(osdev->dev);
+
+	osdev->smmu_s1_enabled = false;
+	if (!mapping) {
+		cds_info("No SMMU mapping present");
+		return;
+	}
+
+	if ((iommu_domain_get_attr(mapping->domain,
+				   DOMAIN_ATTR_S1_BYPASS, &attr) == 0) &&
+				   !attr)
+		osdev->smmu_s1_enabled = true;
+}
+
+int cds_smmu_map_unmap(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
+{
+	return hdd_ipa_uc_smmu_map(map, num_buf, buf_arr);
+}
+#else
+void cds_smmu_mem_map_setup(qdf_device_t osdev)
+{
+}
+
+int cds_smmu_map_unmap(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
+{
+	return 0;
+}
+#endif

+ 18 - 1
core/hdd/inc/wlan_hdd_ipa.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -141,6 +141,18 @@ void hdd_ipa_uc_stat(struct hdd_adapter *adapter);
  */
 void hdd_ipa_uc_info(struct hdd_context *hdd_ctx);
 
+/**
+ * hdd_ipa_uc_smmu_map() - Map / Unmap DMA buffer to IPA UC
+ * @map: Map / unmap operation
+ * @num_buf: Number of buffers in array
+ * @buf_arr: Buffer array of DMA mem mapping info
+ *
+ * This API maps/unmaps WLAN-IPA buffers if SMMU S1 translation
+ * is enabled.
+ *
+ * Return: Status of map operation
+ */
+int hdd_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr);
 #else
 
 static inline QDF_STATUS hdd_ipa_init(struct hdd_context *hdd_ctx)
@@ -316,5 +328,10 @@ static inline void hdd_ipa_uc_info(struct hdd_context *hdd_ctx)
 {
 }
 
+static inline int hdd_ipa_uc_smmu_map(bool map, uint32_t num_buf,
+				      qdf_mem_info_t *buf_arr)
+{
+	return 0;
+}
 #endif /* IPA_OFFLOAD */
 #endif /* #ifndef HDD_IPA_H__ */

+ 1 - 0
core/hdd/src/wlan_hdd_driver_ops.c

@@ -390,6 +390,7 @@ static int wlan_hdd_probe(struct device *dev, void *bdev,
 		cds_set_load_in_progress(true);
 
 	hdd_init_qdf_ctx(dev, bdev, bus_type, (const struct hif_bus_id *)bid);
+	cds_smmu_mem_map_setup(cds_get_context(QDF_MODULE_ID_QDF_DEVICE));
 
 	if (reinit) {
 		ret = hdd_wlan_re_init();

+ 18 - 0
core/hdd/src/wlan_hdd_ipa.c

@@ -6378,4 +6378,22 @@ QDF_STATUS hdd_ipa_cleanup(struct hdd_context *hdd_ctx)
 
 	return ret;
 }
+
+int hdd_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
+{
+	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Map: %d Num_buf: %d", map, num_buf);
+
+	if (!num_buf) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "No buffers to map/unmap");
+		return 0;
+	}
+
+	if (map)
+		return ipa_create_wdi_mapping(num_buf,
+			   (struct ipa_wdi_buffer_info *)buf_arr);
+	else
+		return ipa_release_wdi_mapping(num_buf,
+			   (struct ipa_wdi_buffer_info *)buf_arr);
+}
+
 #endif /* IPA_OFFLOAD */