qcacld-2.0: ADD SCPC feature
This feature will save new calibrated data in the RAM instead of
an on board OTP.
Once SCPC feature is enabled, new calibrated data indicated by FW
in FTM mode will be cached in RAM. The cached calibrated data will
be patched to the board data before it is downloaded to target.
Change-Id: I07400d0edbae3e2013ee47373d120716013450c0
CRs-Fixed: 967577
diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c
index 86cc918..d2e103d 100644
--- a/CORE/SERVICES/BMI/ol_fw.c
+++ b/CORE/SERVICES/BMI/ol_fw.c
@@ -747,6 +747,13 @@
OS_MEMCPY(tempEeprom, (u_int8_t *)fw_entry->data, fw_entry_size);
+ status = vos_update_boarddata(tempEeprom, fw_entry_size);
+ if (EOK != status) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("wlan: update boarddata failed, status=%d.\n",
+ status));
+ }
+
switch (scn->target_type) {
default:
board_data_size = 0;
diff --git a/CORE/SERVICES/COMMON/wma_api.h b/CORE/SERVICES/COMMON/wma_api.h
index 4d3073b..2f82083 100644
--- a/CORE/SERVICES/COMMON/wma_api.h
+++ b/CORE/SERVICES/COMMON/wma_api.h
@@ -172,4 +172,6 @@
}
#endif
+extern int wma_scpc_event_handler(void *handle, u_int8_t *event, u_int32_t len);
+
#endif
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index df65c65..ba0ff11 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -86,6 +86,8 @@
#include "wdi_out.h"
#include "wdi_in.h"
+#include "vos_cnss.h"
+
#include "vos_utils.h"
#include "tl_shim.h"
#if defined(QCA_WIFI_FTM)
@@ -30208,6 +30210,88 @@
return 0;
}
+#if defined(QCA_WIFI_FTM) && defined(WLAN_SCPC_FEATURE)
+/**
+ * wma_scpc_event_handler() - handler for scpc event from firmware
+ * @handle: wma context
+ * @event_buf: pointer to the event buffer
+ * @len: length of the event buffer
+ *
+ * Once SCPC feature is enabled in FTM mode, firmware will do calibration
+ * and indicates calibrated data in an SCPC message.
+ *
+ * This function is used to parse SCPC message. Calibrated data in an SCPC
+ * message is formated like this:
+ * patch1 offset(byte3~0), patch1 length(byte7~4), patch1 data
+ * ......
+ * patchn offset(byte3~0), patchn length(byte7~4), patchn data
+ * All data patches are 4bytes aligned. But the length indicated here is
+ * not multiple of 4.
+ *
+ * Return: 0 on success.
+ */
+int wma_scpc_event_handler(void *handle, u_int8_t *event_buf, u_int32_t len)
+{
+ u_int8_t *buf;
+ u_int32_t length;
+ u_int32_t i;
+ u_int32_t n;
+ WMI_PDEV_UTF_SCPC_EVENTID_param_tlvs *param_buf;
+ wmi_scpc_event_fixed_param *scpc_event;
+ struct _bd {
+ u_int32_t offset;
+ u_int32_t length;
+ u_int8_t data[0];
+ } *bd_data;
+
+ WMA_LOGD("WMA event <---- SCPC\n");
+ if ((event_buf == NULL) || (len < sizeof(wmi_scpc_event_fixed_param))) {
+ WMA_LOGE("%s: invalid pointer", __func__);
+ return -EINVAL;
+ }
+
+ param_buf = (WMI_PDEV_UTF_SCPC_EVENTID_param_tlvs *)event_buf;
+ scpc_event = param_buf->fixed_param;
+ length = len - sizeof(wmi_scpc_event_fixed_param);
+
+
+ buf = (u_int8_t *)scpc_event + sizeof(wmi_scpc_event_fixed_param);
+
+ WMA_LOGD("%s: section count is %d, data length is %d, tag is 0x%x.\n",
+ __func__, scpc_event->num_patch, length, *(u_int32_t *)buf);
+
+ /* skip the tag */
+ buf += sizeof(u_int32_t);
+
+ i = n = 0;
+ bd_data = (struct _bd *)&buf[n];
+ n += roundup((sizeof(struct _bd) + bd_data->length), 4);
+
+ while ((n < length) && (i < scpc_event->num_patch)) {
+ bd_data = (struct _bd *)&buf[n];
+
+ WMA_LOGD("%s: board data patch%i, offset= %d, length= %d.\n",
+ __func__, i, bd_data->offset, bd_data->length);
+ /* cache the data section */
+ vos_cache_boarddata(bd_data->offset,
+ bd_data->length, bd_data->data);
+
+ n += roundup((sizeof(struct _bd) + bd_data->length), 4);
+ i++;
+ }
+
+ WMA_LOGD("%s: %d patches in message, %d cached.\n",
+ __func__, scpc_event->num_patch, i);
+
+ return 0;
+}
+#else
+int wma_scpc_event_handler(void *handle, u_int8_t *event_buf, u_int32_t len)
+{
+ return 0;
+}
+#endif
+
/* function : wma_start
* Description :
* Args :
diff --git a/CORE/SERVICES/WMI/wmi_unified.c b/CORE/SERVICES/WMI/wmi_unified.c
index 667a414..732321e 100644
--- a/CORE/SERVICES/WMI/wmi_unified.c
+++ b/CORE/SERVICES/WMI/wmi_unified.c
@@ -1012,6 +1012,14 @@
pr_debug("%s: WMI event ID is 0x%x\n", __func__, id);
#endif
+ /* This event will be earlier than WMI ready. */
+ if (id == WMI_PDEV_UTF_SCPC_EVENTID) {
+ WMA_LOGD("%s: get WMI_PDEV_UTF_SCPC_EVENTID\n", __func__);
+ wma_scpc_event_handler(wmi_handle->scn_handle,
+ wmi_cmd_struct_ptr, len);
+ goto end;
+ }
+
if (id >= WMI_EVT_GRP_START_ID(WMI_GRP_START)) {
u_int32_t idx = 0;
diff --git a/CORE/VOSS/inc/vos_cnss.h b/CORE/VOSS/inc/vos_cnss.h
index ac51e18..bdee9fa 100644
--- a/CORE/VOSS/inc/vos_cnss.h
+++ b/CORE/VOSS/inc/vos_cnss.h
@@ -186,6 +186,17 @@
{
return true;
}
+
+static inline int vos_update_boarddata(unsigned char *buf, unsigned int len)
+{
+ return 0;
+}
+
+static inline int vos_cache_boarddata(unsigned int offset,
+ unsigned int len, unsigned char *buf)
+{
+ return 0;
+}
#else
static inline void vos_init_work(struct work_struct *work, work_func_t func)
{
@@ -467,5 +478,30 @@
return cnss_pcie_shadow_control(dev, enable);
}
#endif
+
+#if defined(CONFIG_CNSS_SDIO) && defined(WLAN_SCPC_FEATURE)
+static inline int vos_update_boarddata(unsigned char *buf, unsigned int len)
+{
+ return cnss_update_boarddata(buf, len);
+}
+
+static inline int vos_cache_boarddata(unsigned int offset,
+ unsigned int len, unsigned char *buf)
+{
+ return cnss_cache_boarddata(buf, len, offset);
+}
+#else
+static inline int vos_update_boarddata(unsigned char *buf, unsigned int len)
+{
+ return 0;
+}
+
+static inline int vos_cache_boarddata(unsigned int offset,
+ unsigned int len, unsigned char *buf)
+{
+ return 0;
+}
#endif
+#endif
+
#endif/* _VOS_CNSS_H */
diff --git a/Kbuild b/Kbuild
index c5ece74..a9e2569 100644
--- a/Kbuild
+++ b/Kbuild
@@ -952,6 +952,10 @@
-DFEATURE_WLAN_CH144 \
-DHTC_CRP_DEBUG
+ifeq ($(CONFIG_SCPC_FEATURE), y)
+CDEFINES += -DWLAN_SCPC_FEATURE
+endif
+
ifeq ($(CONFIG_QCA_WIFI_SDIO), 1)
CDEFINES += -DCONFIG_HL_SUPPORT \
-DCONFIG_AR6320_SUPPORT \