wlan: Add debugfs interface support for WoWL feature
Add debugfs interface and corresponding support for WoWL feature to WLAN
driver. The feature supports up to 16 WOWL patterns.
CRs-Fixed: 524374
Change-Id: I8a426d06d1f00bed73339c917a3ed28240b6540a
diff --git a/CORE/HDD/inc/wlan_hdd_debugfs.h b/CORE/HDD/inc/wlan_hdd_debugfs.h
new file mode 100644
index 0000000..7b912c8
--- /dev/null
+++ b/CORE/HDD/inc/wlan_hdd_debugfs.h
@@ -0,0 +1,24 @@
+/*
+* Copyright (c) 2013 Qualcomm Atheros, Inc.
+* All Rights Reserved.
+* Qualcomm Atheros Confidential and Proprietary.
+*/
+
+#ifndef _WLAN_HDD_DEBUGFS_H
+#define _WLAN_HDD_DEBUGFS_H
+
+#ifdef WLAN_OPEN_SOURCE
+VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter);
+void hdd_debugfs_exit(hdd_context_t *pHddCtx);
+#else
+inline VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter)
+{
+ return VOS_STATUS_SUCCESS;
+}
+inline void hdd_debugfs_exit(hdd_context_t *pHddCtx)
+{
+}
+#endif
+
+#endif /* #ifndef _WLAN_HDD_DEBUGFS_H */
+
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 6bc593f..88a7e41 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1026,6 +1026,9 @@
#ifdef FEATURE_WLAN_LPHB
lphbEnableStruct lphbEnableReq;
#endif /* FEATURE_WLAN_LPHB */
+
+ /* debugfs entry */
+ struct dentry *debugfs_phy;
};
diff --git a/CORE/HDD/inc/wlan_hdd_wowl.h b/CORE/HDD/inc/wlan_hdd_wowl.h
index d2d672d..82e3ff8 100644
--- a/CORE/HDD/inc/wlan_hdd_wowl.h
+++ b/CORE/HDD/inc/wlan_hdd_wowl.h
@@ -152,6 +152,32 @@
v_BOOL_t hdd_del_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn);
/**============================================================================
+ @brief hdd_add_wowl_ptrn_debugfs() - Function which will add a WoW pattern
+ to be used when PBM filtering is enabled and MP filtering is disabled
+
+ @param pAdapter : [in] pointer to the adapter
+ pattern_idx : [in] index of the pattern to be added
+ pattern_offset : [in] offset of the pattern in the frame payload
+ pattern_buf : [in] pointer to the pattern hex string to be added
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_add_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, v_U8_t pattern_idx,
+ v_U8_t pattern_offset, char *pattern_buf);
+
+/**============================================================================
+ @brief hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern
+
+ @param pAdapter : [in] pointer to the adapter
+ pattern_idx : [in] index of the pattern to be removed
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_del_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, v_U8_t pattern_idx);
+
+/**============================================================================
@brief hdd_enter_wowl() - Function which will enable WoWL. Atleast one
of MP and PBM must be enabled
diff --git a/CORE/HDD/src/wlan_hdd_debugfs.c b/CORE/HDD/src/wlan_hdd_debugfs.c
new file mode 100644
index 0000000..0337b4a
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_debugfs.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef WLAN_OPEN_SOURCE
+#include <wlan_hdd_includes.h>
+#include <wlan_hdd_wowl.h>
+
+#define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512
+
+static ssize_t wcnss_wowpattern_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ hdd_adapter_t *pAdapter = (hdd_adapter_t *)file->private_data;
+
+ char cmd[MAX_USER_COMMAND_SIZE_WOWL_PATTERN];
+ char *sptr, *token;
+ v_U8_t pattern_idx = 0;
+ v_U8_t pattern_offset = 0;
+ char *pattern_buf;
+
+ if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Invalid adapter or adapter has invalid magic.",
+ __func__);
+
+ return -EINVAL;
+ }
+
+ if (count > MAX_USER_COMMAND_SIZE_WOWL_PATTERN)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Command length is larger than %d bytes.",
+ __func__, MAX_USER_COMMAND_SIZE_WOWL_PATTERN);
+
+ return -EINVAL;
+ }
+
+ /* Get command from user */
+ if (copy_from_user(cmd, buf, count))
+ return -EFAULT;
+ cmd[count] = '\0';
+ sptr = cmd;
+
+ /* Get pattern idx */
+ token = strsep(&sptr, " ");
+ if (!token)
+ return -EINVAL;
+
+ if (kstrtou8(token, 0, &pattern_idx))
+ return -EINVAL;
+
+ /* Get pattern offset */
+ token = strsep(&sptr, " ");
+
+ /* Delete pattern if no further argument */
+ if (!token) {
+ hdd_del_wowl_ptrn_debugfs(pAdapter, pattern_idx);
+
+ return count;
+ }
+
+ if (kstrtou8(token, 0, &pattern_offset))
+ return -EINVAL;
+
+ /* Get pattern */
+ token = strsep(&sptr, " ");
+ if (!token)
+ return -EINVAL;
+
+ pattern_buf = token;
+ pattern_buf[strlen(pattern_buf) - 1] = '\0';
+
+ hdd_add_wowl_ptrn_debugfs(pAdapter, pattern_idx, pattern_offset,
+ pattern_buf);
+
+ return count;
+}
+
+static int wcnss_debugfs_open(struct inode *inode, struct file *file)
+{
+ if (inode->i_private)
+ {
+ file->private_data = inode->i_private;
+ }
+
+ return 0;
+}
+
+static const struct file_operations fops_wowpattern = {
+ .write = wcnss_wowpattern_write,
+ .open = wcnss_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter)
+{
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ pHddCtx->debugfs_phy = debugfs_create_dir("wlan_wcnss", 0);
+
+ if (NULL == pHddCtx->debugfs_phy)
+ return VOS_STATUS_E_FAILURE;
+
+ if (NULL == debugfs_create_file("wow_pattern", S_IRUSR | S_IWUSR,
+ pHddCtx->debugfs_phy, pAdapter, &fops_wowpattern))
+ return VOS_STATUS_E_FAILURE;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+void hdd_debugfs_exit(hdd_context_t *pHddCtx)
+{
+ debugfs_remove_recursive(pHddCtx->debugfs_phy);
+}
+#endif //#ifdef WLAN_OPEN_SOURCE
+
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 1ea73af..b868e32 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -123,6 +123,7 @@
#ifdef FEATURE_WLAN_TDLS
#include "wlan_hdd_tdls.h"
#endif
+#include "wlan_hdd_debugfs.h"
#ifdef MODULE
#define WLAN_MODULE_NAME module_name(THIS_MODULE)
@@ -5048,6 +5049,8 @@
}
}
+ hdd_debugfs_exit(pHddCtx);
+
// Unregister the Net Device Notifier
unregister_netdevice_notifier(&hdd_netdev_notifier);
@@ -5911,6 +5914,14 @@
#endif //WLAN_BTAMP_FEATURE
}
+ /* Open debugfs interface */
+ if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: hdd_debugfs_init failed!", __func__);
+ goto err_close_debugfs;
+ }
+
/* Register TM level change handler function to the platform */
status = hddDevTmRegisterNotifyCallback(pHddCtx);
if ( !VOS_IS_STATUS_SUCCESS( status ) )
@@ -6018,6 +6029,9 @@
hddDevTmUnregisterNotifyCallback(pHddCtx);
hddDeregisterPmOps(pHddCtx);
+err_close_debugfs:
+ hdd_debugfs_exit(pHddCtx);
+
#ifdef WLAN_BTAMP_FEATURE
err_bap_stop:
WLANBAP_Stop(pVosContext);
diff --git a/CORE/HDD/src/wlan_hdd_wowl.c b/CORE/HDD/src/wlan_hdd_wowl.c
index 05d2f5d..6299fae 100644
--- a/CORE/HDD/src/wlan_hdd_wowl.c
+++ b/CORE/HDD/src/wlan_hdd_wowl.c
@@ -61,7 +61,7 @@
#define WOWL_PTRN_MAX_SIZE 128
#define WOWL_PTRN_MASK_MAX_SIZE 16
-#define WOWL_MAX_PTRNS_ALLOWED 8
+#define WOWL_MAX_PTRNS_ALLOWED 16
#define WOWL_INTER_PTRN_TOKENIZER ';'
#define WOWL_INTRA_PTRN_TOKENIZER ':'
@@ -69,7 +69,9 @@
* Type Declarations
* -------------------------------------------------------------------------*/
-char *g_hdd_wowl_ptrns[WOWL_MAX_PTRNS_ALLOWED]; //Patterns 0-7
+static char *g_hdd_wowl_ptrns[WOWL_MAX_PTRNS_ALLOWED]; //Patterns 0-15
+static v_BOOL_t g_hdd_wowl_ptrns_debugfs[WOWL_MAX_PTRNS_ALLOWED] = {0};
+static v_U8_t g_hdd_wowl_ptrns_count = 0;
int hdd_parse_hex(unsigned char c)
{
@@ -346,6 +348,181 @@
}
/**============================================================================
+ @brief hdd_add_wowl_ptrn_debugfs() - Function which will add a WoW pattern
+ to be used when PBM filtering is enabled and MP filtering is disabled
+
+ @param pAdapter : [in] pointer to the adapter
+ pattern_idx : [in] index of the pattern to be added
+ pattern_offset : [in] offset of the pattern in the frame payload
+ pattern_buf : [in] pointer to the pattern hex string to be added
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_add_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, v_U8_t pattern_idx,
+ v_U8_t pattern_offset, char *pattern_buf)
+{
+ tSirWowlAddBcastPtrn localPattern;
+ eHalStatus halStatus;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ v_U8_t sessionId = pAdapter->sessionId;
+ v_U16_t pattern_len, i;
+
+ if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WoW pattern index %d is out of range (0 ~ %d).",
+ __func__, pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1);
+
+ return VOS_FALSE;
+ }
+
+ pattern_len = strlen(pattern_buf);
+
+ /* Since the pattern is a hex string, 2 characters represent 1 byte. */
+ if (pattern_len % 2)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Malformed WoW pattern!", __func__);
+
+ return VOS_FALSE;
+ }
+ else
+ pattern_len >>= 1;
+
+ if (!pattern_len || pattern_len > WOWL_PTRN_MAX_SIZE)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WoW pattern length %d is out of range (1 ~ %d).",
+ __func__, pattern_len, WOWL_PTRN_MAX_SIZE);
+
+ return VOS_FALSE;
+ }
+
+ localPattern.ucPatternId = pattern_idx;
+ localPattern.ucPatternByteOffset = pattern_offset;
+ localPattern.ucPatternSize = pattern_len;
+
+ /* Extract the pattern */
+ for (i = 0; i < localPattern.ucPatternSize; i++)
+ {
+ localPattern.ucPattern[i] =
+ (hdd_parse_hex(pattern_buf[0]) << 4) + hdd_parse_hex(pattern_buf[1]);
+
+ /* Skip to next byte */
+ pattern_buf += 2;
+ }
+
+ /* Generate bytemask by pattern length */
+ for (i = 0; i < (pattern_len >> 3); i++)
+ localPattern.ucPatternMask[i] = 0xFF;
+
+ localPattern.ucPatternMaskSize = i;
+
+ if (pattern_len % 8)
+ {
+ localPattern.ucPatternMask[i] = (1 << (pattern_len % 8)) - 1;
+ localPattern.ucPatternMaskSize += 1;
+ }
+
+ /* Register the pattern downstream */
+ halStatus = sme_WowlAddBcastPattern(hHal, &localPattern, sessionId);
+
+ if (!HAL_STATUS_SUCCESS(halStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_WowlAddBcastPattern failed with error code (%ld).",
+ __func__, halStatus);
+
+ return VOS_FALSE;
+ }
+
+ /* Enable WoW immediately after add a pattern. By default,
+ * disable magic packet mode and enable pattern byte matching mode. */
+ if (!hdd_enter_wowl(pAdapter, 0, 1))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: hdd_enter_wowl failed!", __func__);
+
+ return VOS_FALSE;
+ }
+
+ /* All is good. */
+ if (!g_hdd_wowl_ptrns_debugfs[pattern_idx])
+ {
+ g_hdd_wowl_ptrns_debugfs[pattern_idx] = 1;
+ g_hdd_wowl_ptrns_count++;
+ }
+
+ dump_hdd_wowl_ptrn(&localPattern);
+
+ return VOS_TRUE;
+}
+
+/**============================================================================
+ @brief hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern
+
+ @param pAdapter : [in] pointer to the adapter
+ pattern_idx : [in] index of the pattern to be removed
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_del_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, v_U8_t pattern_idx)
+{
+ tSirWowlDelBcastPtrn delPattern;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ eHalStatus halStatus;
+ v_U8_t sessionId = pAdapter->sessionId;
+
+ if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WoW pattern index %d is not in the range (0 ~ %d).",
+ __func__, pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1);
+
+ return VOS_FALSE;
+ }
+
+ if (!g_hdd_wowl_ptrns_debugfs[pattern_idx])
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WoW pattern %d is not in the table.",
+ __func__, pattern_idx);
+
+ return VOS_FALSE;
+ }
+
+ delPattern.ucPatternId = pattern_idx;
+ halStatus = sme_WowlDelBcastPattern(hHal, &delPattern, sessionId);
+
+ if (!HAL_STATUS_SUCCESS(halStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_WowlDelBcastPattern failed with error code (%ld).",
+ __func__, halStatus);
+
+ return VOS_FALSE;
+ }
+
+ g_hdd_wowl_ptrns_debugfs[pattern_idx] = 0;
+ g_hdd_wowl_ptrns_count--;
+
+ if (g_hdd_wowl_ptrns_count == 0)
+ {
+ if (!hdd_exit_wowl(pAdapter))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: hdd_exit_wowl failed!", __func__);
+
+ return VOS_FALSE;
+ }
+ }
+
+ return VOS_TRUE;
+}
+
+/**============================================================================
@brief hdd_enter_wowl() - Function which will enable WoWL. Atleast one
of MP and PBM must be enabled
diff --git a/Kbuild b/Kbuild
index 1167e20..301645c 100644
--- a/Kbuild
+++ b/Kbuild
@@ -118,14 +118,15 @@
HDD_OBJS := $(HDD_SRC_DIR)/bap_hdd_main.o \
$(HDD_SRC_DIR)/wlan_hdd_assoc.o \
$(HDD_SRC_DIR)/wlan_hdd_cfg.o \
+ $(HDD_SRC_DIR)/wlan_hdd_debugfs.o \
$(HDD_SRC_DIR)/wlan_hdd_dev_pwr.o \
$(HDD_SRC_DIR)/wlan_hdd_dp_utils.o \
$(HDD_SRC_DIR)/wlan_hdd_early_suspend.o \
$(HDD_SRC_DIR)/wlan_hdd_ftm.o \
$(HDD_SRC_DIR)/wlan_hdd_hostapd.o \
- $(HDD_SRC_DIR)/wlan_hdd_oemdata.o \
$(HDD_SRC_DIR)/wlan_hdd_main.o \
$(HDD_SRC_DIR)/wlan_hdd_mib.o \
+ $(HDD_SRC_DIR)/wlan_hdd_oemdata.o \
$(HDD_SRC_DIR)/wlan_hdd_scan.o \
$(HDD_SRC_DIR)/wlan_hdd_softap_tx_rx.o \
$(HDD_SRC_DIR)/wlan_hdd_tx_rx.o \