wlan: Add one more variable sent through debugfs for WoW
Add "mask" variable support for WoW feature through debugfs interface.
Also add explicitly enable/disable WoW support through debugfs.
Change-Id: I1c7a2253de55541fe2dbc0cba7ee2961f83313ca
CRs-Fixed: 576468
diff --git a/CORE/HDD/inc/wlan_hdd_wowl.h b/CORE/HDD/inc/wlan_hdd_wowl.h
index 82e3ff8..5ab7861 100644
--- a/CORE/HDD/inc/wlan_hdd_wowl.h
+++ b/CORE/HDD/inc/wlan_hdd_wowl.h
@@ -153,21 +153,24 @@
/**============================================================================
@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
+ sent from debugfs interface
@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
+ pattern_mask : [in] pointer to the pattern mask hex string
@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);
+ v_U8_t pattern_offset, char *pattern_buf,
+ char *pattern_mask);
/**============================================================================
@brief hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern
+ sent from debugfs interface
@param pAdapter : [in] pointer to the adapter
pattern_idx : [in] index of the pattern to be removed
diff --git a/CORE/HDD/src/wlan_hdd_debugfs.c b/CORE/HDD/src/wlan_hdd_debugfs.c
index c15d222..ab90322 100644
--- a/CORE/HDD/src/wlan_hdd_debugfs.c
+++ b/CORE/HDD/src/wlan_hdd_debugfs.c
@@ -31,9 +31,103 @@
#include <wlan_hdd_includes.h>
#include <wlan_hdd_wowl.h>
+#define MAX_USER_COMMAND_SIZE_WOWL_ENABLE 8
#define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512
#define MAX_USER_COMMAND_SIZE_FRAME 4096
+static ssize_t wcnss_wowenable_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_ENABLE + 1];
+ char *sptr, *token;
+ v_U8_t wow_enable = 0;
+ v_U8_t wow_mp = 0;
+ v_U8_t wow_pbm = 0;
+
+ 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 (!sme_IsFeatureSupportedByFW(WOW))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Wake-on-Wireless feature is not supported "
+ "in firmware!", __func__);
+
+ return -EINVAL;
+ }
+
+ if (count > MAX_USER_COMMAND_SIZE_WOWL_ENABLE)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Command length is larger than %d bytes.",
+ __func__, MAX_USER_COMMAND_SIZE_WOWL_ENABLE);
+
+ return -EINVAL;
+ }
+
+ /* Get command from user */
+ if (copy_from_user(cmd, buf, count))
+ return -EFAULT;
+ cmd[count] = '\0';
+ sptr = cmd;
+
+ /* Get enable or disable wow */
+ token = strsep(&sptr, " ");
+ if (!token)
+ return -EINVAL;
+ if (kstrtou8(token, 0, &wow_enable))
+ return -EINVAL;
+
+ /* Disable wow */
+ if (!wow_enable) {
+ if (!hdd_exit_wowl(pAdapter))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: hdd_exit_wowl failed!", __func__);
+
+ return -EFAULT;
+ }
+
+ return count;
+ }
+
+ /* Get enable or disable magic packet mode */
+ token = strsep(&sptr, " ");
+ if (!token)
+ return -EINVAL;
+ if (kstrtou8(token, 0, &wow_mp))
+ return -EINVAL;
+ if (wow_mp > 1)
+ wow_mp = 1;
+
+ /* Get enable or disable pattern byte matching mode */
+ token = strsep(&sptr, " ");
+ if (!token)
+ return -EINVAL;
+ if (kstrtou8(token, 0, &wow_pbm))
+ return -EINVAL;
+ if (wow_pbm > 1)
+ wow_pbm = 1;
+
+ if (!hdd_enter_wowl(pAdapter, wow_mp, wow_pbm))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: hdd_enter_wowl failed!", __func__);
+
+ return -EFAULT;
+ }
+
+ return count;
+}
+
static ssize_t wcnss_wowpattern_write(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
{
@@ -44,6 +138,7 @@
v_U8_t pattern_idx = 0;
v_U8_t pattern_offset = 0;
char *pattern_buf;
+ char *pattern_mask;
if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
{
@@ -105,10 +200,17 @@
return -EINVAL;
pattern_buf = token;
- pattern_buf[strlen(pattern_buf) - 1] = '\0';
+
+ /* Get pattern mask */
+ token = strsep(&sptr, " ");
+ if (!token)
+ return -EINVAL;
+
+ pattern_mask = token;
+ pattern_mask[strlen(pattern_mask) - 1] = '\0';
hdd_add_wowl_ptrn_debugfs(pAdapter, pattern_idx, pattern_offset,
- pattern_buf);
+ pattern_buf, pattern_mask);
return count;
}
@@ -149,7 +251,7 @@
}
/* Get command from user */
- if (count < MAX_USER_COMMAND_SIZE_FRAME)
+ if (count <= MAX_USER_COMMAND_SIZE_FRAME)
cmd = vos_mem_malloc(count + 1);
else
{
@@ -328,6 +430,13 @@
return 0;
}
+static const struct file_operations fops_wowenable = {
+ .write = wcnss_wowenable_write,
+ .open = wcnss_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
static const struct file_operations fops_wowpattern = {
.write = wcnss_wowpattern_write,
.open = wcnss_debugfs_open,
@@ -350,6 +459,10 @@
if (NULL == pHddCtx->debugfs_phy)
return VOS_STATUS_E_FAILURE;
+ if (NULL == debugfs_create_file("wow_enable", S_IRUSR | S_IWUSR,
+ pHddCtx->debugfs_phy, pAdapter, &fops_wowenable))
+ 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;
diff --git a/CORE/HDD/src/wlan_hdd_wowl.c b/CORE/HDD/src/wlan_hdd_wowl.c
index f7e5c68..dfb22af 100644
--- a/CORE/HDD/src/wlan_hdd_wowl.c
+++ b/CORE/HDD/src/wlan_hdd_wowl.c
@@ -349,24 +349,26 @@
/**============================================================================
@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
+ sent from debugfs interface
@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
+ pattern_mask : [in] pointer to the pattern mask hex string
@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)
+ v_U8_t pattern_offset, char *pattern_buf,
+ char *pattern_mask)
{
tSirWowlAddBcastPtrn localPattern;
eHalStatus halStatus;
tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
v_U8_t sessionId = pAdapter->sessionId;
- v_U16_t pattern_len, i;
+ v_U16_t pattern_len, mask_len, i;
if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1))
{
@@ -413,16 +415,28 @@
pattern_buf += 2;
}
- /* Generate bytemask by pattern length */
- for (i = 0; i < (pattern_len >> 3); i++)
- localPattern.ucPatternMask[i] = 0xFF;
-
- localPattern.ucPatternMaskSize = i;
-
+ /* Get pattern mask size by pattern length */
+ localPattern.ucPatternMaskSize = pattern_len >> 3;
if (pattern_len % 8)
- {
- localPattern.ucPatternMask[i] = (1 << (pattern_len % 8)) - 1;
localPattern.ucPatternMaskSize += 1;
+
+ mask_len = strlen(pattern_mask);
+ if ((mask_len % 2) || (localPattern.ucPatternMaskSize != (mask_len >> 1)))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Malformed WoW pattern mask!", __func__);
+
+ return VOS_FALSE;
+ }
+
+ /* Extract the pattern mask */
+ for (i = 0; i < localPattern.ucPatternMaskSize; i++)
+ {
+ localPattern.ucPatternMask[i] =
+ (hdd_parse_hex(pattern_mask[0]) << 4) + hdd_parse_hex(pattern_mask[1]);
+
+ /* Skip to next byte */
+ pattern_mask += 2;
}
/* Register the pattern downstream */
@@ -437,16 +451,6 @@
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])
{
@@ -461,6 +465,7 @@
/**============================================================================
@brief hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern
+ sent from debugfs interface
@param pAdapter : [in] pointer to the adapter
pattern_idx : [in] index of the pattern to be removed
@@ -508,17 +513,6 @@
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;
}