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
diff --git a/Kbuild b/Kbuild
index e5a376a..a63a48f 100644
--- a/Kbuild
+++ b/Kbuild
@@ -2498,6 +2498,11 @@
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
diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h
index 95f4ead..df46040 100644
--- a/core/cds/inc/cds_api.h
+++ b/core/cds/inc/cds_api.h
@@ -593,4 +593,29 @@
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 */
diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c
index ffaa6c9..f0f4045 100644
--- a/core/cds/src/cds_api.c
+++ b/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 @@
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
diff --git a/core/hdd/inc/wlan_hdd_ipa.h b/core/hdd/inc/wlan_hdd_ipa.h
index 825d104..4e3bae9 100644
--- a/core/hdd/inc/wlan_hdd_ipa.h
+++ b/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_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 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__ */
diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c
index 8507d75..d1a4a2e 100644
--- a/core/hdd/src/wlan_hdd_driver_ops.c
+++ b/core/hdd/src/wlan_hdd_driver_ops.c
@@ -390,6 +390,7 @@
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();
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c
index 198ae0d..3c29e00 100644
--- a/core/hdd/src/wlan_hdd_ipa.c
+++ b/core/hdd/src/wlan_hdd_ipa.c
@@ -6378,4 +6378,22 @@
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 */