aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaan Külahlı <kaankulahli@gmail.com>2017-05-25 19:54:16 +0300
committerGitHub <noreply@github.com>2017-05-25 19:54:16 +0300
commit943acc22babac805296a8d6de42f424f8c00df5a (patch)
treeb710cb20d9b8c1e50a7705564ed08a968eb4c163
parent6f93f25b482cb3833bad393a2f4cde8a0d1a69ca (diff)
parent14f0a97da192d0cf20ae234389925827d9c2c119 (diff)
Merge pull request #3 from kernel-hut/cm-14.1HEADn7.1
pull request
-rw-r--r--Documentation/ABI/testing/sysfs-devices-online20
-rw-r--r--arch/arm64/configs/zc550kl-custom_defconfig2
-rw-r--r--arch/arm64/configs/zc550kl-perf_defconfig2
-rw-r--r--arch/arm64/configs/ze500kg-custom_defconfig2
-rw-r--r--arch/arm64/configs/ze500kl-custom_defconfig2
-rw-r--r--drivers/base/core.c130
-rw-r--r--drivers/platform/msm/mhi/mhi_sys.c28
-rw-r--r--drivers/soc/qcom/Kconfig16
-rw-r--r--drivers/soc/qcom/Makefile2
-rw-r--r--drivers/soc/qcom/core_ctl_helper.c62
-rw-r--r--drivers/soc/qcom/peripheral-loader.c2
-rw-r--r--drivers/soc/qcom/socinfo.c40
-rw-r--r--drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c16
-rw-r--r--drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h62
-rw-r--r--drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h63
-rw-r--r--drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wmm.h10
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c1
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c491
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c7
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c1
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c32
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c166
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c17
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c33
-rw-r--r--drivers/staging/prima/CORE/MAC/inc/aniGlobal.h7
-rw-r--r--drivers/staging/prima/CORE/MAC/inc/sirApi.h55
-rw-r--r--drivers/staging/prima/CORE/MAC/inc/wniApi.h1
-rw-r--r--drivers/staging/prima/CORE/MAC/src/include/sirParams.h7
-rw-r--r--drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c1
-rw-r--r--drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c54
-rw-r--r--drivers/staging/prima/CORE/SME/inc/sme_Api.h13
-rw-r--r--drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c12
-rw-r--r--drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c164
-rw-r--r--drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c4
-rw-r--r--drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h9
-rw-r--r--drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c47
-rw-r--r--drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c8
-rw-r--r--drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h2
-rw-r--r--drivers/staging/prima/CORE/VOSS/inc/vos_api.h7
-rw-r--r--drivers/staging/prima/CORE/VOSS/inc/vos_packet.h24
-rw-r--r--drivers/staging/prima/CORE/VOSS/src/vos_api.c265
-rw-r--r--drivers/staging/prima/CORE/VOSS/src/vos_packet.c31
-rw-r--r--drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h14
-rw-r--r--drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c403
-rw-r--r--drivers/staging/prima/CORE/WDA/src/wlan_qct_wda_ds.c4
-rw-r--r--drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h53
-rw-r--r--drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h11
-rw-r--r--drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h3
-rw-r--r--drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h35
-rw-r--r--drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c316
-rw-r--r--drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c6
-rw-r--r--drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h7
-rw-r--r--drivers/staging/prima/CORE/WDI/DP/src/wlan_qct_wdi_ds.c15
-rw-r--r--drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c9
-rw-r--r--drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h4
-rw-r--r--drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c19
-rw-r--r--drivers/staging/prima/riva/inc/wlan_hal_msg.h69
-rw-r--r--drivers/usb/phy/phy-ab8500-usb.c2
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c2
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c2
-rw-r--r--drivers/usb/phy/phy.c4
-rw-r--r--include/linux/compiler-gcc6.h65
-rw-r--r--include/linux/device.h21
-rw-r--r--init/Kconfig10
-rw-r--r--kernel/sched/Makefile1
-rw-r--r--kernel/sched/core_ctl.c (renamed from drivers/soc/qcom/core_ctl.c)177
-rw-r--r--sound/soc/codecs/msm8x16-wcd.h5
-rw-r--r--sound/soc/codecs/wcd-mbhc-v2.h2
68 files changed, 2898 insertions, 279 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-online b/Documentation/ABI/testing/sysfs-devices-online
new file mode 100644
index 00000000000..f990026c074
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-online
@@ -0,0 +1,20 @@
+What: /sys/devices/.../online
+Date: April 2013
+Contact: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+ The /sys/devices/.../online attribute is only present for
+ devices whose bus types provide .online() and .offline()
+ callbacks. The number read from it (0 or 1) reflects the value
+ of the device's 'offline' field. If that number is 1 and '0'
+ (or 'n', or 'N') is written to this file, the device bus type's
+ .offline() callback is executed for the device and (if
+ successful) its 'offline' field is updated accordingly. In
+ turn, if that number is 0 and '1' (or 'y', or 'Y') is written to
+ this file, the device bus type's .online() callback is executed
+ for the device and (if successful) its 'offline' field is
+ updated as appropriate.
+
+ After a successful execution of the bus type's .offline()
+ callback the device cannot be used for any purpose until either
+ it is removed (i.e. device_del() is called for it), or its bus
+ type's .online() is exeucted successfully.
diff --git a/arch/arm64/configs/zc550kl-custom_defconfig b/arch/arm64/configs/zc550kl-custom_defconfig
index 6df7e4830d7..6b1e2df73da 100644
--- a/arch/arm64/configs/zc550kl-custom_defconfig
+++ b/arch/arm64/configs/zc550kl-custom_defconfig
@@ -552,7 +552,7 @@ CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
CONFIG_MSM_SCM=y
-CONFIG_MSM_CORE_CTL=y
+CONFIG_SCHED_CORE_CTL=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_EXT2_FS=y
diff --git a/arch/arm64/configs/zc550kl-perf_defconfig b/arch/arm64/configs/zc550kl-perf_defconfig
index d5a2fc09657..9f5c9656514 100644
--- a/arch/arm64/configs/zc550kl-perf_defconfig
+++ b/arch/arm64/configs/zc550kl-perf_defconfig
@@ -490,7 +490,7 @@ CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
CONFIG_MSM_SCM=y
-CONFIG_MSM_CORE_CTL=y
+CONFIG_SCHED_CORE_CTL=y
CONFIG_MSM_CORE_CTL_HELPER=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
diff --git a/arch/arm64/configs/ze500kg-custom_defconfig b/arch/arm64/configs/ze500kg-custom_defconfig
index 5f4fa66fc29..3294755dba5 100644
--- a/arch/arm64/configs/ze500kg-custom_defconfig
+++ b/arch/arm64/configs/ze500kg-custom_defconfig
@@ -557,7 +557,7 @@ CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
CONFIG_MSM_SCM=y
-CONFIG_MSM_CORE_CTL=y
+CONFIG_SCHED_CORE_CTL=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_TEXURA_ARM64=y
diff --git a/arch/arm64/configs/ze500kl-custom_defconfig b/arch/arm64/configs/ze500kl-custom_defconfig
index f516da93cfb..4057f3194bc 100644
--- a/arch/arm64/configs/ze500kl-custom_defconfig
+++ b/arch/arm64/configs/ze500kl-custom_defconfig
@@ -555,7 +555,7 @@ CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
CONFIG_MSM_SCM=y
-CONFIG_MSM_CORE_CTL=y
+CONFIG_SCHED_CORE_CTL=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_TEXURA_ARM64=y
diff --git a/drivers/base/core.c b/drivers/base/core.c
index a1b4e620f96..60d4786c4cc 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -403,6 +403,36 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
static struct device_attribute uevent_attr =
__ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
+static ssize_t show_online(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ bool val;
+
+ lock_device_hotplug();
+ val = !dev->offline;
+ unlock_device_hotplug();
+ return sprintf(buf, "%u\n", val);
+}
+
+static ssize_t store_online(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ bool val;
+ int ret;
+
+ ret = strtobool(buf, &val);
+ if (ret < 0)
+ return ret;
+
+ lock_device_hotplug();
+ ret = val ? device_online(dev) : device_offline(dev);
+ unlock_device_hotplug();
+ return ret < 0 ? ret : count;
+}
+
+static struct device_attribute online_attr =
+ __ATTR(online, S_IRUGO | S_IWUSR, show_online, store_online);
+
static int device_add_attributes(struct device *dev,
struct device_attribute *attrs)
{
@@ -516,6 +546,12 @@ static int device_add_attrs(struct device *dev)
if (error)
goto err_remove_type_groups;
+ if (device_supports_offline(dev) && !dev->offline_disabled) {
+ error = device_create_file(dev, &online_attr);
+ if (error)
+ goto err_remove_type_groups;
+ }
+
return 0;
err_remove_type_groups:
@@ -536,6 +572,7 @@ static void device_remove_attrs(struct device *dev)
struct class *class = dev->class;
const struct device_type *type = dev->type;
+ device_remove_file(dev, &online_attr);
device_remove_groups(dev, dev->groups);
if (type)
@@ -1460,6 +1497,99 @@ EXPORT_SYMBOL_GPL(put_device);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);
+static DEFINE_MUTEX(device_hotplug_lock);
+
+void lock_device_hotplug(void)
+{
+ mutex_lock(&device_hotplug_lock);
+}
+
+void unlock_device_hotplug(void)
+{
+ mutex_unlock(&device_hotplug_lock);
+}
+
+static int device_check_offline(struct device *dev, void *not_used)
+{
+ int ret;
+
+ ret = device_for_each_child(dev, NULL, device_check_offline);
+ if (ret)
+ return ret;
+
+ return device_supports_offline(dev) && !dev->offline ? -EBUSY : 0;
+}
+
+/**
+ * device_offline - Prepare the device for hot-removal.
+ * @dev: Device to be put offline.
+ *
+ * Execute the device bus type's .offline() callback, if present, to prepare
+ * the device for a subsequent hot-removal. If that succeeds, the device must
+ * not be used until either it is removed or its bus type's .online() callback
+ * is executed.
+ *
+ * Call under device_hotplug_lock.
+ */
+int device_offline(struct device *dev)
+{
+ int ret;
+
+ if (dev->offline_disabled)
+ return -EPERM;
+
+ ret = device_for_each_child(dev, NULL, device_check_offline);
+ if (ret)
+ return ret;
+
+ device_lock(dev);
+ if (device_supports_offline(dev)) {
+ if (dev->offline) {
+ ret = 1;
+ } else {
+ ret = dev->bus->offline(dev);
+ if (!ret) {
+ kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
+ dev->offline = true;
+ }
+ }
+ }
+ device_unlock(dev);
+
+ return ret;
+}
+
+/**
+ * device_online - Put the device back online after successful device_offline().
+ * @dev: Device to be put back online.
+ *
+ * If device_offline() has been successfully executed for @dev, but the device
+ * has not been removed subsequently, execute its bus type's .online() callback
+ * to indicate that the device can be used again.
+ *
+ * Call under device_hotplug_lock.
+ */
+int device_online(struct device *dev)
+{
+ int ret = 0;
+
+ device_lock(dev);
+ if (device_supports_offline(dev)) {
+ if (dev->offline) {
+ ret = dev->bus->online(dev);
+ if (!ret) {
+ kobject_uevent(&dev->kobj, KOBJ_ONLINE);
+ dev->offline = false;
+ }
+ } else {
+ ret = 1;
+ }
+ }
+ device_unlock(dev);
+
+ return ret;
+}
+
struct root_device {
struct device dev;
struct module *owner;
diff --git a/drivers/platform/msm/mhi/mhi_sys.c b/drivers/platform/msm/mhi/mhi_sys.c
index 07cd5f8b03c..231c70b7905 100644
--- a/drivers/platform/msm/mhi/mhi_sys.c
+++ b/drivers/platform/msm/mhi/mhi_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -187,22 +187,6 @@ static const struct file_operations mhi_dbgfs_ev_fops = {
.write = NULL,
};
-static ssize_t mhi_dbgfs_trigger_msi(struct file *fp, const char __user *buf,
- size_t count, loff_t *offp)
-{
- u32 msi_nr = 0;
- void *irq_ctxt = &((mhi_devices.device_list[0]).pcie_device->dev);
- if (copy_from_user(&msi_nr, buf, sizeof(msi_nr)))
- return -ENOMEM;
- mhi_msi_handlr(msi_nr, irq_ctxt);
- return 0;
-}
-
-static const struct file_operations mhi_dbgfs_trigger_msi_fops = {
- .read = NULL,
- .write = mhi_dbgfs_trigger_msi,
-};
-
static ssize_t mhi_dbgfs_state_read(struct file *fp, char __user *buf,
size_t count, loff_t *offp)
{
@@ -311,7 +295,6 @@ int mhi_init_debugfs(struct mhi_device_ctxt *mhi_dev_ctxt)
{
struct dentry *mhi_chan_stats;
struct dentry *mhi_state_stats;
- struct dentry *mhi_msi_trigger;
struct dentry *mhi_ev_stats;
mhi_dev_ctxt->mhi_parent_folder =
debugfs_create_dir("mhi", NULL);
@@ -340,21 +323,12 @@ int mhi_init_debugfs(struct mhi_device_ctxt *mhi_dev_ctxt)
&mhi_dbgfs_state_fops);
if (mhi_state_stats == NULL)
goto clean_ev_stats;
- mhi_msi_trigger = debugfs_create_file("mhi_msi_trigger",
- 0444,
- mhi_dev_ctxt->mhi_parent_folder,
- mhi_dev_ctxt,
- &mhi_dbgfs_trigger_msi_fops);
- if (mhi_msi_trigger == NULL)
- goto clean_state;
mhi_dev_ctxt->chan_info = kmalloc(MHI_LOG_SIZE, GFP_KERNEL);
if (mhi_dev_ctxt->chan_info == NULL)
goto clean_all;
return 0;
clean_all:
- debugfs_remove(mhi_msi_trigger);
-clean_state:
debugfs_remove(mhi_state_stats);
clean_ev_stats:
debugfs_remove(mhi_ev_stats);
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 2f524d78545..05b3e9c3c09 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -546,22 +546,6 @@ config MSM_PACMAN
This driver allows reconfiguration of the Bus Access Manager
Low Speed Peripheral (BLSP) ownership.
-config MSM_CORE_CTL_HELPER
- tristate "Core control helper functions for dynamically hotplug CPUs"
- help
- Provide helper functions for core control driver. Core control
- driver dynamicatlly hotplugs CPUs from kernel based on current
- system load and state. It also supports limiting min and
- max online CPUs from userspace.
-
-config MSM_CORE_CTL
- select MSM_CORE_CTL_HELPER
- tristate "Core control driver to dynamically hotplug CPUs"
- help
- Support for dynamicatlly hotplugging CPUs from kernel based on
- current system load and state. It also supports limiting min and
- max online CPUs from userspace.
-
config MSM_PERFORMANCE
tristate "Core control driver to support userspace hotplug requests"
help
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 2eb79f0b841..2621f65fc7e 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -56,8 +56,6 @@ obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.o
obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o ocmem_rdm.o ocmem_core.o
obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o
-obj-$(CONFIG_MSM_CORE_CTL_HELPER) += core_ctl_helper.o
-obj-$(CONFIG_MSM_CORE_CTL) += core_ctl.o
ifdef CONFIG_MSM_SUBSYSTEM_RESTART
obj-y += subsystem_notif.o
diff --git a/drivers/soc/qcom/core_ctl_helper.c b/drivers/soc/qcom/core_ctl_helper.c
deleted file mode 100644
index 3b25d9811cf..00000000000
--- a/drivers/soc/qcom/core_ctl_helper.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/cpu.h>
-#include <linux/cpufreq.h>
-#include <linux/ktime.h>
-#include <linux/hrtimer.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <soc/qcom/core_ctl.h>
-
-void core_ctl_block_hotplug(void)
-{
- get_online_cpus();
-}
-EXPORT_SYMBOL(core_ctl_block_hotplug);
-
-void core_ctl_unblock_hotplug(void)
-{
- put_online_cpus();
-}
-EXPORT_SYMBOL(core_ctl_unblock_hotplug);
-
-s64 core_ctl_get_time(void)
-{
- return ktime_to_ms(ktime_get());
-}
-EXPORT_SYMBOL(core_ctl_get_time);
-
-struct cpufreq_policy *core_ctl_get_policy(int cpu)
-{
- return cpufreq_cpu_get(cpu);
-}
-EXPORT_SYMBOL(core_ctl_get_policy);
-
-void core_ctl_put_policy(struct cpufreq_policy *policy)
-{
- cpufreq_cpu_put(policy);
-}
-EXPORT_SYMBOL(core_ctl_put_policy);
-
-struct device *core_ctl_find_cpu_device(unsigned cpu)
-{
- return get_cpu_device(cpu);
-}
-EXPORT_SYMBOL(core_ctl_find_cpu_device);
-
-int __ref core_ctl_online_core(unsigned int cpu)
-{
- return cpu_up(cpu);
-}
-EXPORT_SYMBOL(core_ctl_online_core);
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index 085345454ca..c8006ca3792 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -381,6 +381,8 @@ static int pil_alloc_region(struct pil_priv *priv, phys_addr_t min_addr,
if (region == NULL) {
pil_err(priv->desc, "Failed to allocate relocatable region of size %zx\n",
size);
+ priv->region_start = 0;
+ priv->region_end = 0;
return -ENOMEM;
}
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 7f699c6d2aa..cd7c27bbfa2 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2015,2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -52,6 +52,7 @@
#define SMEM_IMAGE_VERSION_OEM_OFFSET 96
#define SMEM_IMAGE_VERSION_PARTITION_APPS 10
+static DECLARE_RWSEM(current_image_rwsem);
enum {
HW_PLATFORM_UNKNOWN = 0,
HW_PLATFORM_SURF = 1,
@@ -800,7 +801,9 @@ msm_get_image_version(struct device *dev,
__func__);
return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "Unknown");
}
+ down_read(&current_image_rwsem);
string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ up_read(&current_image_rwsem);
return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s\n",
string_address);
}
@@ -813,15 +816,20 @@ msm_set_image_version(struct device *dev,
{
char *store_address;
- if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ down_read(&current_image_rwsem);
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) {
+ up_read(&current_image_rwsem);
return count;
+ }
store_address = socinfo_get_image_version_base_address();
if (IS_ERR_OR_NULL(store_address)) {
pr_err("%s : Failed to get image version base address",
__func__);
+ up_read(&current_image_rwsem);
return count;
}
store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ up_read(&current_image_rwsem);
snprintf(store_address, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s", buf);
return count;
}
@@ -840,7 +848,9 @@ msm_get_image_variant(struct device *dev,
return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE,
"Unknown");
}
+ down_read(&current_image_rwsem);
string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ up_read(&current_image_rwsem);
string_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET;
return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s\n",
string_address);
@@ -854,15 +864,20 @@ msm_set_image_variant(struct device *dev,
{
char *store_address;
- if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ down_read(&current_image_rwsem);
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) {
+ up_read(&current_image_rwsem);
return count;
+ }
store_address = socinfo_get_image_version_base_address();
if (IS_ERR_OR_NULL(store_address)) {
pr_err("%s : Failed to get image version base address",
__func__);
+ up_read(&current_image_rwsem);
return count;
}
store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ up_read(&current_image_rwsem);
store_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET;
snprintf(store_address, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s", buf);
return count;
@@ -881,7 +896,9 @@ msm_get_image_crm_version(struct device *dev,
__func__);
return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "Unknown");
}
+ down_read(&current_image_rwsem);
string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ up_read(&current_image_rwsem);
string_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s\n",
string_address);
@@ -895,15 +912,20 @@ msm_set_image_crm_version(struct device *dev,
{
char *store_address;
- if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ down_read(&current_image_rwsem);
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) {
+ up_read(&current_image_rwsem);
return count;
+ }
store_address = socinfo_get_image_version_base_address();
if (IS_ERR_OR_NULL(store_address)) {
pr_err("%s : Failed to get image version base address",
__func__);
+ up_read(&current_image_rwsem);
return count;
}
store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ up_read(&current_image_rwsem);
store_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s", buf);
return count;
@@ -914,8 +936,14 @@ msm_get_image_number(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n",
+ int ret;
+
+ down_read(&current_image_rwsem);
+ ret = snprintf(buf, PAGE_SIZE, "%d\n",
current_image);
+ up_read(&current_image_rwsem);
+ return ret;
+
}
static ssize_t
@@ -927,10 +955,12 @@ msm_select_image(struct device *dev, struct device_attribute *attr,
ret = kstrtoint(buf, 10, &digit);
if (ret)
return ret;
+ down_write(&current_image_rwsem);
if (0 <= digit && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT)
current_image = digit;
else
current_image = 0;
+ up_write(&current_image_rwsem);
return count;
}
diff --git a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c
index c7f7235b0a8..de64b93c89e 100644
--- a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c
+++ b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -3445,6 +3445,12 @@ static wpt_status dxeTXPushFrame
//HDXE_ASSERT(0);
}
+ if(wpalIsArpPkt(palPacket))
+ {
+ HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
+ "%s :ARP packet", __func__);
+ }
+
/* Everything is ready
* Trigger to start DMA */
status = wpalWriteRegister(channelEntry->channelRegister.chDXECtrlRegAddr,
@@ -3695,6 +3701,14 @@ static wpt_status dxeTXCompFrame
}
return status;
}
+
+ if(wpalIsArpPkt(currentCtrlBlk->xfrFrame))
+ {
+ HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
+ "%s :ARP packet DMA-ed ", __func__);
+ wpalUpdateTXArpFWdeliveredStats();
+ }
+
hostCtxt->txCompCB(hostCtxt->clientCtxt,
currentCtrlBlk->xfrFrame,
eWLAN_PAL_STATUS_SUCCESS);
diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h
index f00390dcc22..d1ca157f87e 100644
--- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -197,6 +197,11 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES = 101,
QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105,
+
+ /* Start / Stop the NUD stats collections */
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET = 149,
+ /* Get the NUD stats, represented by the enum qca_attr_nud_stats_get */
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET = 150,
};
enum qca_nl80211_vendor_subcmds_index {
@@ -232,6 +237,63 @@ enum qca_nl80211_vendor_subcmds_index {
QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX,
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX,
+};
+
+/**
+ * qca_wlan_vendor_attr_nud_stats_set: attribute to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carry the requisite
+ * information to start / stop the NUD stats collection.
+ */
+enum qca_attr_nud_stats_set {
+ QCA_ATTR_NUD_STATS_SET_INVALID = 0,
+
+ /* Flag to Start / Stop the NUD stats collection
+ * Start - If included , Stop - If not included
+ */
+ QCA_ATTR_NUD_STATS_SET_START = 1,
+ /* IPv4 address of Default Gateway (in network byte order) */
+ QCA_ATTR_NUD_STATS_GW_IPV4 = 2,
+
+ /* keep last */
+ QCA_ATTR_NUD_STATS_SET_LAST,
+ QCA_ATTR_NUD_STATS_SET_MAX =
+ QCA_ATTR_NUD_STATS_SET_LAST - 1,
+};
+
+/**
+ * qca_attr_nud_stats_get: attribute to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET. This carry the requisite
+ * NUD stats collected when queried.
+ */
+enum qca_attr_nud_stats_get {
+ QCA_ATTR_NUD_STATS_GET_INVALID = 0,
+ /* ARP Request Count from net dev */
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV = 1,
+ /* ARP Request Count sent to lower MAC from upper MAC */
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC = 2,
+ /* ARP Request Count received by lower MAC from upper MAC */
+ QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC = 3,
+ /* ARP Request Count successfully transmitted by the device */
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS = 4,
+ /* ARP Response Count received by lower MAC */
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC = 5,
+ /* ARP Response Count received by upper MAC */
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC = 6,
+ /* ARP Response Count delivered to netdev */
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV = 7,
+ /* ARP Response Count delivered to netdev */
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP = 8,
+ /*
+ * Flag indicating if the Stations Link to AP is active.
+ * Active Link - If exists, Inactive link - If not included
+ */
+ QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE= 9,
+ QCA_ATTR_NUD_STATS_AP_LINK_DAD= 10,
+ /* keep last */
+ QCA_ATTR_NUD_STATS_GET_LAST,
+ QCA_ATTR_NUD_STATS_GET_MAX =
+ QCA_ATTR_NUD_STATS_GET_LAST - 1,
};
enum qca_wlan_vendor_attr
diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h
index 610c6f88e54..dd20161009f 100644
--- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h
+++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h
@@ -101,6 +101,7 @@
#define SOFTAP_BSS_STARTED (4)
#define DEVICE_IFACE_OPENED (5)
#define TDLS_INIT_DONE (6)
+#define SOFTAP_INIT_DONE (7)
/** Maximum time(ms)to wait for disconnect to complete **/
#define WLAN_WAIT_TIME_DISCONNECT 5000
@@ -376,6 +377,35 @@ typedef struct hdd_pmf_stats_s
} hdd_pmf_stats_t;
#endif
+typedef enum
+{
+ HDD_TX_FRAME_IN_NOT_ASSOCIATED_STATE = 0,
+ HDD_VOS_PACKET_RETURNED_BY_VOSS_IS_NULL,
+ HDD_WLANTL_STAPKTPENDING_RETURNED_ERROR_CODE,
+ HDD_INSERT_TX_QUEUE_FAILED,
+ HDD_FAILED_TO_SIGNAL_TL,
+ HDD_ERROR_ATTACHING_SKB,
+ HDD_FAILURE_EXTRACTING_SKB_FROM_VOS_PKT,
+ HDD_FAILURE_WALKING_PACKET_CHAIN,
+ HDD_STA_RX_ARP_PACKET_REFUSED_IN_NET_STACK
+} HDD_PACKET_DROP_CAUSE;
+
+typedef struct hdd_arp_stats_s
+{
+ uint16 tx_arp_req_count;
+ uint16 rx_arp_rsp_count;
+ uint16 txDropped;
+ uint16 rxDropped;
+ uint16 rxDelivered;
+ uint16 rxRefused;
+ uint16 tx_host_fw_sent;
+ uint16 rx_host_drop_reorder;
+ uint16_t tx_fw_cnt;
+ uint16_t rx_fw_cnt;
+ uint16_t tx_ack_cnt;
+ HDD_PACKET_DROP_CAUSE reason;
+} hdd_arp_stats_t;
+
typedef struct hdd_stats_s
{
tCsrSummaryStatsInfo summary_stat;
@@ -386,6 +416,7 @@ typedef struct hdd_stats_s
tCsrPerStaStatsInfo perStaStats;
hdd_tx_rx_stats_t hddTxRxStats;
hdd_chip_reset_stats_t hddChipResetStats;
+ hdd_arp_stats_t hddArpStats;
#ifdef WLAN_FEATURE_11W
hdd_pmf_stats_t hddPmfStats;
#endif
@@ -1216,6 +1247,9 @@ struct hdd_adapter_s
/* Currently used antenna Index*/
int antennaIndex;
+ bool nud_set_arp_stats;
+ bool con_status;
+ bool dad;
};
#define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
@@ -1273,6 +1307,10 @@ typedef struct
#define WLAN_WAIT_TIME_LL_STATS 800
+#define WLAN_WAIT_TIME_NUD_STATS 800
+#define WLAN_NUD_STATS_LEN 800
+#define WLAN_NUD_STATS_ARP_PKT_TYPE 1
+
/* FW memory dump feature
@TODO : Move this code to a separate file later */
#define PROCFS_MEMDUMP_DIR "debug"
@@ -1320,6 +1358,15 @@ struct hdd_ll_stats_context {
struct completion response_event;
};
#endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */
+
+/**
+ * struct hdd_nud_stats_context - hdd NUD stats context
+ *
+ * @response_event: NUD stats request wait event
+ */
+struct hdd_nud_stats_context {
+ struct completion response_event;
+};
#ifdef WLAN_FEATURE_EXTSCAN
/**
* struct hdd_ext_scan_context - hdd ext scan context
@@ -1605,6 +1652,7 @@ struct hdd_context_s
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
struct hdd_ll_stats_context ll_stats_context;
#endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */
+ struct hdd_nud_stats_context nud_stats_context;
#ifdef WLAN_FEATURE_EXTSCAN
struct hdd_ext_scan_context ext_scan_context;
@@ -1638,6 +1686,8 @@ struct hdd_context_s
v_U8_t last_scan_reject_session_id;
scan_reject_states last_scan_reject_reason;
v_TIME_t last_scan_reject_timestamp;
+
+ uint32_t track_arp_ip;
};
typedef enum {
@@ -1955,6 +2005,19 @@ static inline void hdd_init_ll_stat_ctx(void)
return;
}
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
+
+/**
+ * hdd_init_nud_stats_ctx() - initialize NUD stats context
+ * @hdd_ctx: Pointer to hdd context
+ *
+ * Return: none
+ */
+static inline void hdd_init_nud_stats_ctx(hdd_context_t *hdd_ctx)
+{
+ init_completion(&hdd_ctx->nud_stats_context.response_event);
+ return;
+}
+
void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter);
void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy);
void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx);
diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wmm.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wmm.h
index ca4db65c53f..4e1eb237b83 100644
--- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wmm.h
+++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wmm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -415,4 +415,12 @@ VOS_STATUS hdd_wmm_adapter_clear( hdd_adapter_t *pAdapter );
===========================================================================*/
void hdd_log_ip_addr(struct sk_buff *skb);
+/**============================================================================
+ @brief hdd_get_arp_src_ip() - Function to get ARP src IP addr
+ @param pAdapter : [in] pointer to os packet
+
+ @return : IP address
+ ===========================================================================*/
+uint32_t hdd_get_arp_src_ip(struct sk_buff *skb);
+
#endif /* #ifndef _WLAN_HDD_WMM_H */
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c
index 4fc44c2557a..b7c935de763 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c
@@ -1258,6 +1258,7 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *
pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BE] = 0;
pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BK] = 0;
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
+ pAdapter->dad = false;
// Clear saved connection information in HDD
hdd_connRemoveConnectInfo( pHddStaCtx );
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c
index 4e2f02bd701..66c732e235c 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -7464,6 +7464,455 @@ static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
return ret;
}
+
+/*
+ * define short names for the global vendor params
+ * used by wlan_hdd_cfg80211_setarp_stats_cmd()
+ */
+#define STATS_SET_INVALID \
+ QCA_ATTR_NUD_STATS_SET_INVALID
+#define STATS_SET_START \
+ QCA_ATTR_NUD_STATS_SET_START
+#define STATS_GW_IPV4 \
+ QCA_ATTR_NUD_STATS_GW_IPV4
+#define STATS_SET_MAX \
+ QCA_ATTR_NUD_STATS_SET_MAX
+
+const struct nla_policy
+qca_wlan_vendor_set_nud_stats[STATS_SET_MAX +1] =
+{
+ [STATS_SET_START] = {.type = NLA_FLAG },
+ [STATS_GW_IPV4] = {.type = NLA_U32 },
+};
+
+/**
+ * hdd_test_con_alive() - check connection alive
+ * @adapter: pointer to adapter
+ *
+ * Return: true if SME command is sent of false otherwise
+ */
+static bool hdd_test_con_alive(hdd_adapter_t *adapter)
+{
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+ if (eHAL_STATUS_SUCCESS != sme_test_con_alive(hdd_ctx->hHal)) {
+ hddLog(LOGE, FL("could not send ADDBA"));
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * hdd_set_nud_stats_cb() - hdd callback api to get status
+ * @data: pointer to adapter
+ * @rsp: status
+ *
+ * Return: None
+ */
+static void hdd_set_nud_stats_cb(void *data, VOS_STATUS rsp)
+{
+
+ hdd_adapter_t *adapter = (hdd_adapter_t *)data;
+
+ if (NULL == adapter)
+ return;
+
+ if (VOS_STATUS_SUCCESS == rsp) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s success received STATS_SET_START", __func__);
+ if (adapter->nud_set_arp_stats)
+ hdd_test_con_alive(adapter);
+ } else {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START Failed!!", __func__);
+ }
+ return;
+}
+
+/**
+ * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to apfind configuration data.
+ * @data_len: the length in byte of apfind data.
+ *
+ * This is called when wlan driver needs to send arp stats to
+ * firmware.
+ *
+ * Return: An error code or 0 on success.
+ */
+static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct nlattr *tb[STATS_SET_MAX + 1];
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(adapter))->pvosContext;
+ setArpStatsParams arp_stats_params;
+ int err = 0;
+
+ ENTER();
+
+ err = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != err)
+ return err;
+
+ if (!sme_IsFeatureSupportedByFW(NUD_DEBUG)) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s NUD_DEBUG feature not supported by firmware!!", __func__);
+ return -EINVAL;
+ }
+
+ err = nla_parse(tb, STATS_SET_MAX, data, data_len,
+ qca_wlan_vendor_set_nud_stats);
+ if (err)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START ATTR", __func__);
+ return err;
+ }
+
+ if (tb[STATS_SET_START])
+ {
+ if (!tb[STATS_GW_IPV4]) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START CMD", __func__);
+ return -EINVAL;
+ }
+ arp_stats_params.flag = true;
+ adapter->nud_set_arp_stats = true;
+ arp_stats_params.ip_addr = nla_get_u32(tb[STATS_GW_IPV4]);
+ } else {
+ arp_stats_params.flag = false;
+ adapter->nud_set_arp_stats = false;
+ }
+ if (!arp_stats_params.flag) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s STATS_SET_START Cleared!!", __func__);
+ hdd_ctx->track_arp_ip = 0;
+ vos_mem_zero(&adapter->hdd_stats.hddArpStats, sizeof(adapter->hdd_stats.hddArpStats));
+ }
+
+ arp_stats_params.pkt_type = 1; // ARP packet type
+
+ if (arp_stats_params.flag) {
+ hdd_ctx->track_arp_ip = arp_stats_params.ip_addr;
+ WLANTL_SetARPFWDatapath(pVosContext, true);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s Set FW in data path for ARP with tgt IP :%d",
+ __func__, hdd_ctx->track_arp_ip);
+ }
+ else {
+ WLANTL_SetARPFWDatapath(pVosContext, false);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s Remove FW from data path", __func__);
+ }
+
+ arp_stats_params.rsp_cb_fn = hdd_set_nud_stats_cb;
+ arp_stats_params.data_ctx = adapter;
+
+ if (eHAL_STATUS_SUCCESS !=
+ sme_set_nud_debug_stats(hdd_ctx->hHal, &arp_stats_params)) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START CMD Failed!!", __func__);
+ return -EINVAL;
+ }
+
+ EXIT();
+
+ return err;
+}
+
+/**
+ * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to apfind configuration data.
+ * @data_len: the length in byte of apfind data.
+ *
+ * This is called when wlan driver needs to send arp stats to
+ * firmware.
+ *
+ * Return: An error code or 0 on success.
+ */
+static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ int ret;
+
+ vos_ssr_protect(__func__);
+ ret = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
+ vos_ssr_unprotect(__func__);
+
+ return ret;
+}
+#undef STATS_SET_INVALID
+#undef STATS_SET_START
+#undef STATS_GW_IPV4
+#undef STATS_SET_MAX
+
+/*
+ * define short names for the global vendor params
+ * used by wlan_hdd_cfg80211_setarp_stats_cmd()
+ */
+#define STATS_GET_INVALID \
+ QCA_ATTR_NUD_STATS_SET_INVALID
+#define COUNT_FROM_NETDEV \
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
+#define COUNT_TO_LOWER_MAC \
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
+#define RX_COUNT_BY_LOWER_MAC \
+ QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
+#define COUNT_TX_SUCCESS \
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
+#define RSP_RX_COUNT_BY_LOWER_MAC \
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
+#define RSP_RX_COUNT_BY_UPPER_MAC \
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
+#define RSP_COUNT_TO_NETDEV \
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
+#define RSP_COUNT_OUT_OF_ORDER_DROP \
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
+#define AP_LINK_ACTIVE \
+ QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
+#define AP_LINK_DAD \
+ QCA_ATTR_NUD_STATS_AP_LINK_DAD
+#define STATS_GET_MAX \
+ QCA_ATTR_NUD_STATS_GET_MAX
+
+const struct nla_policy
+qca_wlan_vendor_get_nud_stats[STATS_GET_MAX +1] =
+{
+ [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
+ [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
+ [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
+ [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
+ [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
+ [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
+ [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
+ [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
+ [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
+ [AP_LINK_DAD] = {.type = NLA_FLAG },
+};
+
+/**
+ * hdd_con_alive_cb() - Call back to get the connection status
+ * @context: pointer to adapter
+ *
+ * Return: None
+ */
+static void hdd_con_alive_cb(void *context, bool status)
+{
+ hdd_adapter_t *adapter = (hdd_adapter_t *)context;
+ adapter->con_status = status;
+}
+
+/**
+ * hdd_get_con_alive() - get the connection status
+ * @adapter: pointer to adapter
+ *
+ * Return: true if SME command is sent of false otherwise
+ */
+static bool hdd_get_con_alive(hdd_adapter_t *adapter)
+{
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ getConStatusParams conStatusParams;
+
+ conStatusParams.rsp_cb_fn = hdd_con_alive_cb;
+ conStatusParams.data_ctx = adapter;
+
+ if (eHAL_STATUS_SUCCESS != sme_get_con_alive(hdd_ctx->hHal,
+ &conStatusParams))
+ {
+ hddLog(LOGE, FL("could not get connection status"));
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * hdd_con_test_DELBA() - delete the BA session
+ * @adapter: pointer to adapter
+ *
+ * Return: true if SME command is sent of false otherwise
+ */
+static bool hdd_con_test_DELBA(hdd_adapter_t *adapter)
+{
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
+ uint8_t sta_id = pHddStaCtx->conn_info.staId[0];
+
+ ENTER();
+
+ if (eHAL_STATUS_SUCCESS != sme_test_con_delba((hdd_ctx->hHal), sta_id,
+ adapter->sessionId)) {
+ hddLog(LOGE, FL("could not send DELBA "));
+ return false;
+ }
+
+ return true;
+}
+
+static void hdd_get_nud_stats_cb(void *data, rsp_stats *rsp)
+{
+
+ hdd_adapter_t *adapter = (hdd_adapter_t *)data;
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ struct hdd_nud_stats_context *context;
+ int status;
+
+ ENTER();
+
+ if (NULL == adapter)
+ return;
+
+ status = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != status) {
+ return;
+ }
+
+ if (!rsp) {
+ hddLog(LOGE, FL("data is null"));
+ return;
+ }
+
+ adapter->hdd_stats.hddArpStats.tx_fw_cnt = rsp->tx_fw_cnt;
+ adapter->hdd_stats.hddArpStats.rx_fw_cnt = rsp->rx_fw_cnt;
+ adapter->hdd_stats.hddArpStats.tx_ack_cnt = rsp->tx_ack_cnt;
+ adapter->dad |= rsp->dad;
+
+ spin_lock(&hdd_context_lock);
+ context = &hdd_ctx->nud_stats_context;
+ complete(&context->response_event);
+ spin_unlock(&hdd_context_lock);
+
+ return;
+}
+static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ int err = 0;
+ unsigned long rc;
+ struct hdd_nud_stats_context *context;
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+ getArpStatsParams arp_stats_params;
+ struct sk_buff *skb;
+
+ ENTER();
+
+ err = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != err)
+ return err;
+
+ hdd_get_con_alive(adapter);
+
+ arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
+ arp_stats_params.get_rsp_cb_fn = hdd_get_nud_stats_cb;
+ arp_stats_params.data_ctx = adapter;
+
+ spin_lock(&hdd_context_lock);
+ context = &hdd_ctx->nud_stats_context;
+ INIT_COMPLETION(context->response_event);
+ spin_unlock(&hdd_context_lock);
+
+ if (!sme_IsFeatureSupportedByFW(NUD_DEBUG)) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s NUD_DEBUG feature not supported by firmware!!", __func__);
+ return -EINVAL;
+ }
+
+ if (eHAL_STATUS_SUCCESS !=
+ sme_get_nud_debug_stats(hdd_ctx->hHal, &arp_stats_params)) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START CMD Failed!!", __func__);
+ return -EINVAL;
+ }
+
+ rc = wait_for_completion_timeout(&context->response_event,
+ msecs_to_jiffies(WLAN_WAIT_TIME_NUD_STATS));
+ if (!rc)
+ {
+ hddLog(LOGE,
+ FL("Target response timed out request "));
+ return -ETIMEDOUT;
+ }
+
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+ WLAN_NUD_STATS_LEN);
+ if (!skb)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
+ __func__);
+ return -ENOMEM;
+ }
+
+ if (nla_put_u16(skb, COUNT_FROM_NETDEV,
+ adapter->hdd_stats.hddArpStats.tx_arp_req_count) ||
+ nla_put_u16(skb, COUNT_TO_LOWER_MAC,
+ adapter->hdd_stats.hddArpStats.tx_host_fw_sent) ||
+ nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hddArpStats.tx_fw_cnt) ||
+ nla_put_u16(skb, COUNT_TX_SUCCESS,
+ adapter->hdd_stats.hddArpStats.tx_ack_cnt) ||
+ nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hddArpStats.rx_fw_cnt) ||
+ nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
+ adapter->hdd_stats.hddArpStats.rx_arp_rsp_count) ||
+ nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
+ adapter->hdd_stats.hddArpStats.rxDelivered) ||
+ nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
+ adapter->hdd_stats.hddArpStats.rx_host_drop_reorder)) {
+ hddLog(LOGE, FL("nla put fail"));
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ if (adapter->con_status) {
+ nla_put_flag(skb, AP_LINK_ACTIVE);
+ adapter->con_status = false;
+ hdd_con_test_DELBA(adapter);
+ }
+ if (adapter->dad)
+ nla_put_flag(skb, AP_LINK_DAD);
+
+ hdd_ctx->track_arp_ip = 0;
+ cfg80211_vendor_cmd_reply(skb);
+ return err;
+}
+
+static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ int ret;
+
+ vos_ssr_protect(__func__);
+ ret = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
+ vos_ssr_unprotect(__func__);
+
+ return ret;
+}
+
+#undef QCA_ATTR_NUD_STATS_SET_INVALID
+#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
+#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
+#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
+#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
+#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
+#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
+#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
+#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
+#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
+#undef QCA_ATTR_NUD_STATS_GET_MAX
+
const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] =
{
{
@@ -7709,7 +8158,23 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] =
WIPHY_VENDOR_CMD_NEED_NETDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlan_hdd_cfg80211_wifi_configuration_set
- }
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlan_hdd_cfg80211_set_nud_stats
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlan_hdd_cfg80211_get_nud_stats
+ },
};
/* vendor specific events */
@@ -7840,7 +8305,10 @@ struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
.vendor_id = QCA_NL80211_VENDOR_ID,
.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
},
-
+ [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
+ .vendor_id = QCA_NL80211_VENDOR_ID,
+ .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
+ },
};
/*
@@ -9235,7 +9703,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
eCsrAuthType RSNAuthType;
eCsrEncryptionType RSNEncryptType;
eCsrEncryptionType mcRSNEncryptType;
- int status = VOS_STATUS_SUCCESS;
+ int status = VOS_STATUS_SUCCESS, ret = 0;
tpWLAN_SAPEventCB pSapEventCallback;
hdd_hostapd_state_t *pHostapdState;
v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
@@ -9680,12 +10148,15 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
}
pConfig->acsBandSwitchThreshold = iniConfig->acsBandSwitchThreshold;
+ set_bit(SOFTAP_INIT_DONE, &pHostapdAdapter->event_flags);
+
pSapEventCallback = hdd_hostapd_SAPEventCB;
if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
(v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
{
hddLog(LOGE,FL("SAP Start Bss fail"));
- return -EINVAL;
+ ret = -EINVAL;
+ goto error;
}
hddLog(LOG1,
@@ -9728,6 +10199,9 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
EXIT();
return 0;
+error:
+ clear_bit(SOFTAP_INIT_DONE, &pHostapdAdapter->event_flags);
+ return ret;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
@@ -10007,6 +10481,8 @@ static int __wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
// Reset WNI_CFG_PROBE_RSP Flags
wlan_hdd_reset_prob_rspies(pAdapter);
+ clear_bit(SOFTAP_INIT_DONE, &pAdapter->event_flags);
+
pAdapter->sessionCtx.ap.beacon = NULL;
kfree(old);
#ifdef WLAN_FEATURE_P2P_DEBUG
@@ -10086,6 +10562,8 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
return -ENODEV;
}
+ clear_bit(SOFTAP_INIT_DONE, &pAdapter->event_flags);
+
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
@@ -14681,6 +15159,11 @@ static int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter )
(eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
(eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
{
+ /* Indicate disconnect to SME so that in-progress connection or preauth
+ * can be aborted
+ */
+ sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId);
spin_lock_bh(&pAdapter->lock_for_active_session);
if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
{
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c
index f7547fe5e9a..3817d5ca9bc 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c
@@ -2335,9 +2335,10 @@ static void hdd_ssr_restart_sap(hdd_context_t *hdd_ctx)
while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
adapter = adapter_node->pAdapter;
if (adapter && adapter->device_mode == WLAN_HDD_SOFTAP) {
- hddLog(VOS_TRACE_LEVEL_INFO, FL("in sap mode %p"),
- adapter);
- wlan_hdd_start_sap(adapter);
+ if (test_bit(SOFTAP_INIT_DONE, &adapter->event_flags)) {
+ hddLog(VOS_TRACE_LEVEL_INFO, FL("Restart prev SAP session"));
+ wlan_hdd_start_sap(adapter);
+ }
}
status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
adapter_node = next;
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c
index 9d79eb2184c..0a38b2d48eb 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c
@@ -11801,6 +11801,7 @@ int hdd_wlan_startup(struct device *dev )
hdd_init_ll_stats_ctx(pHddCtx);
+ hdd_init_nud_stats_ctx(pHddCtx);
#ifdef CONFIG_ENABLE_LINUX_REG
init_completion(&pHddCtx->linux_reg_req);
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c
index 2e4852ce114..d2225a4f2a6 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -132,9 +132,8 @@ static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
tANI_U8* pbFrames,
tANI_U8 frameType );
-static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
+static v_BOOL_t wlan_hdd_is_type_p2p_action( const u8 *buf )
{
- tActionFrmType actionFrmType;
const u8 *ouiPtr;
if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
@@ -158,14 +157,23 @@ static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
return VOS_FALSE;
}
- actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
- if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
- actionFrmType != WLAN_HDD_GO_NEG_REQ &&
- actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
- actionFrmType != WLAN_HDD_PROV_DIS_REQ )
- return VOS_TRUE;
- else
- return VOS_FALSE;
+ return VOS_TRUE;
+}
+
+static bool hdd_p2p_is_action_type_rsp( const u8 *buf )
+{
+ tActionFrmType actionFrmType;
+
+ if ( wlan_hdd_is_type_p2p_action(buf) )
+ {
+ actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
+ if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
+ actionFrmType != WLAN_HDD_GO_NEG_REQ &&
+ actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
+ actionFrmType != WLAN_HDD_PROV_DIS_REQ )
+ return VOS_TRUE;
+ }
+ return VOS_FALSE;
}
eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
@@ -1293,7 +1301,7 @@ int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
if ((type == SIR_MAC_MGMT_FRAME) &&
(subType == SIR_MAC_MGMT_ACTION) &&
- (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
+ wlan_hdd_is_type_p2p_action(&buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET]))
{
actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
#ifdef WLAN_FEATURE_P2P_DEBUG
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c
index 3cae5479a19..a3a73db4367 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -819,6 +819,7 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
v_BOOL_t txSuspended = VOS_FALSE;
struct sk_buff *skb1;
+ v_BOOL_t arp_pkt;
if (NULL == pHddCtx) {
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
@@ -835,6 +836,17 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
+ arp_pkt = vos_is_arp_pkt(skb, false);
+
+ if (arp_pkt)
+ {
+ if (pHddCtx->track_arp_ip && vos_check_arp_req_target_ip(skb, false)) {
+ ++pAdapter->hdd_stats.hddArpStats.tx_arp_req_count;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :ARP packet received form net_dev", __func__);
+ }
+ }
+
//Get TL Q index corresponding to Qdisc queue index/AC.
qid = hdd_QdiscAcToTlAC[skb->queue_mapping];
ac = qid;
@@ -852,6 +864,15 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
FL("Tx frame in not associated state in %d context"),
pAdapter->device_mode);
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_TX_FRAME_IN_NOT_ASSOCIATED_STATE;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s :Tx frame in not associated state, ARP packet Dropped ",
+ __func__);
+ }
++pAdapter->stats.tx_dropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
@@ -895,6 +916,15 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
"%s: WLANTL_STAPktPending() returned error code %d",
__func__, status);
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_WLANTL_STAPKTPENDING_RETURNED_ERROR_CODE;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s:ARP Packet Dropped WLANTL_STAPktPending returned error %d",
+ __func__, status);
+ }
++pAdapter->stats.tx_dropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
@@ -966,6 +996,14 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if ( !VOS_IS_STATUS_SUCCESS( status ) )
{
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_INSERT_TX_QUEUE_FAILED;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s:Insert Tx queue failed. ARP packet dropped", __func__);
+ }
++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
++pAdapter->stats.tx_dropped;
@@ -1027,6 +1065,15 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb1 = pktNode->skb;
kfree_skb(skb1);
}
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILED_TO_SIGNAL_TL;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: ARP packet Dropped : Failed to signal TL for QId=%d",
+ __func__, qid );
+ }
++pAdapter->stats.tx_dropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
@@ -1938,6 +1985,7 @@ VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
tANI_U8 acAdmitted, i;
v_U8_t proto_type = 0;
WLANTL_ACEnumType actualAC;
+ v_BOOL_t arp_pkt;
//Sanity check on inputs
if ( ( NULL == vosContext ) ||
@@ -2075,10 +2123,20 @@ VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
vos_pkt_return_packet(pVosPacket);
return VOS_STATUS_E_FAILURE;
}
+ arp_pkt = vos_is_arp_pkt(skb, false);
//Attach skb to VOS packet.
status = vos_pkt_set_os_packet( pVosPacket, skb );
if (status != VOS_STATUS_SUCCESS)
{
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_ERROR_ATTACHING_SKB;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s :Error attaching skb,ARP packet droped", __func__);
+ }
+
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
vos_pkt_return_packet(pVosPacket);
++pAdapter->stats.tx_dropped;
@@ -2090,6 +2148,16 @@ VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
//Just being paranoid. To be removed later
if(pVosPacket == NULL)
{
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_VOS_PACKET_RETURNED_BY_VOSS_IS_NULL;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :VOS packet returned by VOSS is NULL,ARP packet droped",
+ __func__);
+ }
+
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: VOS packet returned by VOSS is NULL", __func__);
++pAdapter->stats.tx_dropped;
++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
@@ -2148,6 +2216,12 @@ VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
+ if(pPktMetaInfo->ucIsArp)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :STA TX ARP Received in TL ",__func__);
+ }
+
#ifdef FEATURE_WLAN_WAPI
// Override usIsEapol value when its zero for WAPI case
pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
@@ -2543,6 +2617,40 @@ VOS_STATUS hdd_rx_packet_monitor_cbk(v_VOID_t *vosContext,vos_pkt_t *pVosPacket
return status;
}
+bool hdd_is_duplicate_ip_arp(struct sk_buff *skb)
+{
+ struct in_ifaddr **ifap = NULL;
+ struct in_ifaddr *ifa = NULL;
+ struct in_device *in_dev;
+ uint32_t arp_ip,if_ip;
+
+ if (NULL == skb)
+ return false;
+
+ arp_ip = hdd_get_arp_src_ip(skb);
+
+ if(!skb->dev) return false;
+
+ in_dev = __in_dev_get_rtnl(skb->dev);
+
+ if (in_dev) {
+ for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
+ ifap = &ifa->ifa_next) {
+ if (!strcmp(skb->dev->name, ifa->ifa_label))
+ break;
+ }
+ }
+ if (ifa && ifa->ifa_local) {
+
+ if_ip = ntohl(ifa->ifa_local);
+ if (if_ip == arp_ip) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**============================================================================
@brief hdd_rx_packet_cbk() - Receive callback registered with TL.
TL will call this to notify the HDD when one or more packets were
@@ -2569,6 +2677,8 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
vos_pkt_t* pVosPacket;
vos_pkt_t* pNextVosPacket;
v_U8_t proto_type;
+ v_BOOL_t arp_pkt;
+ bool track_arp_resp = false;
//Sanity check on inputs
if ( ( NULL == vosContext ) ||
@@ -2609,6 +2719,14 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
// both "success" and "empty" are acceptable results
if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
{
+
+ if(hdd_IsARP(pVosPacket))
+ {
+ ++pAdapter->hdd_stats.hddArpStats.rxDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILURE_WALKING_PACKET_CHAIN;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: ARP packet Drop: Failure walking packet chain", __func__);
+ }
++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
"%s: Failure walking packet chain", __func__);
@@ -2619,6 +2737,15 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_FALSE );
if(!VOS_IS_STATUS_SUCCESS( status ))
{
+
+ if(hdd_IsARP(pVosPacket))
+ {
+ ++pAdapter->hdd_stats.hddArpStats.rxDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILURE_EXTRACTING_SKB_FROM_VOS_PKT;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: ARP packet Dropped: Failure extracting skb from vos pkt",
+ __func__);
+ }
++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
"%s: Failure extracting skb from vos pkt", __func__);
@@ -2680,6 +2807,18 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
}
}
+ arp_pkt = vos_is_arp_pkt(skb, false);
+
+ if (arp_pkt)
+ {
+ if (pHddCtx->track_arp_ip && vos_check_arp_rsp_src_ip(skb, false)) {
+ ++pAdapter->hdd_stats.hddArpStats.rx_arp_rsp_count;
+ track_arp_resp = true;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :STA RX ARP received",__func__);
+ }
+ }
+
if (pHddCtx->rx_wow_dump) {
if (!(VOS_PKT_PROTO_TYPE_ARP & proto_type) &&
!(VOS_PKT_PROTO_TYPE_EAPOL & proto_type))
@@ -2703,6 +2842,14 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
++pAdapter->stats.rx_packets;
pAdapter->stats.rx_bytes += skb->len;
+
+ if (arp_pkt)
+ {
+ pAdapter->dad |= hdd_is_duplicate_ip_arp(skb);
+ if(pAdapter->dad)
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s :Duplicate IP detected",__func__);
+ }
#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
HDD_WAKE_LOCK_DURATION,
@@ -2719,11 +2866,30 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
if (NET_RX_SUCCESS == rxstat)
{
+
+ if (arp_pkt)
+ {
+ if (track_arp_resp) {
+ ++pAdapter->hdd_stats.hddArpStats.rxDelivered;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "STA RX ARP packet Delivered to net stack");
+ }
+ }
+
++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
}
else
{
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.rxRefused;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_STA_RX_ARP_PACKET_REFUSED_IN_NET_STACK;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s :STA RX ARP packet Refused in net stack", __func__);
+ }
+
++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
}
// now process the next packet in the chain
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c
index ef66b168523..5cadb459d21 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c
@@ -6919,6 +6919,7 @@ static int __iw_get_char_setnone(struct net_device *dev,
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
hdd_tx_rx_stats_t *pStats = &pAdapter->hdd_stats.hddTxRxStats;
hdd_chip_reset_stats_t *pResetStats = &pHddCtx->hddChipResetStats;
+ hdd_arp_stats_t *parpStats = &pAdapter->hdd_stats.hddArpStats;
snprintf(extra, WE_MAX_STR_LEN,
@@ -6939,6 +6940,11 @@ static int __iw_get_char_setnone(struct net_device *dev,
"\nchains %u, packets %u, dropped %u, delivered %u, refused %u"
"\n\nResetsStats"
"\n TotalLogp %u Cmd53 %u MutexRead %u MIF-Error %u FW-Heartbeat %u Others %u"
+ "\n"
+ "\n\nARP Transmit"
+ "\nTransmit Count %u, dropped %u"
+ "\n\nARP Receive"
+ "\nReceive Count %u, dropped %u, Delivered %u, Refused %u, Drop Reason %u"
"\n",
pStats->txXmitCalled,
pStats->txXmitDropped,
@@ -7012,7 +7018,16 @@ static int __iw_get_char_setnone(struct net_device *dev,
pResetStats->totalMutexReadFailures,
pResetStats->totalMIFErrorFailures,
pResetStats->totalFWHearbeatFailures,
- pResetStats->totalUnknownExceptions
+ pResetStats->totalUnknownExceptions,
+
+ parpStats->tx_arp_req_count,
+ parpStats->txDropped,
+
+ parpStats->rx_arp_rsp_count,
+ parpStats->rxDropped,
+ parpStats->rxDelivered,
+ parpStats->rxRefused,
+ parpStats->reason
);
wrqu->data.length = strlen(extra);
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c
index e854ad27170..b91f0c8407f 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1960,6 +1960,37 @@ void hdd_log_ip_addr(struct sk_buff *skb)
}
/**============================================================================
+ @brief hdd_get_arp_src_ip() - Function to get ARP src IP addr
+ @param skb : [in] pointer to OS packet (sk_buff)
+ @return : IP addr
+ ===========================================================================*/
+uint32_t hdd_get_arp_src_ip(struct sk_buff *skb)
+{
+ struct arphdr *arp;
+ unsigned char *arp_ptr;
+ uint32_t src_ip;
+
+#define ARP_HDR_SIZE ( sizeof(__be16)*3 + sizeof(unsigned char)*2 )
+#define ARP_SENDER_HW_ADDRESS_SZ (6)
+#define ARP_SENDER_IP_ADDRESS_SZ (4)
+
+ arp = (struct arphdr *)skb->data;
+
+ arp_ptr = (unsigned char *)arp + ARP_HDR_SIZE;
+ arp_ptr += ARP_SENDER_HW_ADDRESS_SZ;
+
+ memcpy(&src_ip, arp_ptr, ARP_SENDER_IP_ADDRESS_SZ);
+
+ src_ip=ntohl(src_ip);
+
+ return src_ip;
+
+#undef ARP_HDR_SIZE
+#undef ARP_SENDER_HW_ADDRESS_SZ
+#undef ARP_SENDER_IP_ADDRESS_SZ
+}
+
+/**============================================================================
@brief hdd_wmm_classify_pkt() - Function which will classify an OS packet
into a WMM AC based on either 802.1Q or DSCP
diff --git a/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h b/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h
index 1d50dbfa1b2..ad2df331f60 100644
--- a/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h
+++ b/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h
@@ -260,6 +260,12 @@ typedef struct {
v_TIME_t failed_timestamp[MAX_TIDS];
} tLimStaBAInfo;
+typedef struct {
+ bool tx_aggr;
+ uint8_t sta_id;
+ uint8_t tid;
+} t_test_status_bainfo;
+
typedef struct sAniSirLim
{
////////////////////////////////////// TIMER RELATED START ///////////////////////////////////////////
@@ -914,6 +920,7 @@ tLimMlmOemDataRsp *gpLimMlmOemDataRsp;
tANI_U32 txBdToken;
tANI_U32 EnableTdls2040BSSCoexIE;
tLimStaBAInfo staBaInfo[WLAN_MAX_STA_COUNT];
+ t_test_status_bainfo test_status_bainfo;
} tAniSirLim, *tpAniSirLim;
typedef struct sLimMgmtFrameRegistration
diff --git a/drivers/staging/prima/CORE/MAC/inc/sirApi.h b/drivers/staging/prima/CORE/MAC/inc/sirApi.h
index 3539665ae83..af6bf039314 100644
--- a/drivers/staging/prima/CORE/MAC/inc/sirApi.h
+++ b/drivers/staging/prima/CORE/MAC/inc/sirApi.h
@@ -2929,11 +2929,10 @@ typedef struct sSmeDelBAPeerInd
// Message Type
tANI_U16 mesgType;
- tSirMacAddr bssId;//BSSID
-
// Message Length
tANI_U16 mesgLen;
+ tSirMacAddr bssId;//BSSID
// Station Index
tANI_U16 staIdx;
@@ -3789,11 +3788,57 @@ typedef struct
tANI_U32 reserved2;
}tAniLoggingInitRsp, *tpAniLoggingInitRsp;
+/**
+ * struct rsp_stats - arp packet stats
+ * @status: success or failure
+ * @tx_fw_cnt: tx packets count
+ * @tx_ack_cnt: tx acknowledgement count
+ */
+typedef struct {
+ uint32_t status;
+ uint16_t dad;
+ uint16_t tx_fw_cnt;
+ uint16_t tx_ack_cnt;
+ uint16_t rx_fw_cnt;
+} rsp_stats;
+
+typedef void(*setArpStatsReqCb)(void *data, VOS_STATUS rsp);
+
+/**
+ * struct setArpStatsParams - set/reset arp stats
+ * @flag: enable/disable stats
+ * @pkt_type: type of packet(1 - arp)
+ * @ip_addr: subnet ipv4 address in case of encrypted packets
+ * @rsp_cb_fn: FW response callback api
+ * @data_ctx: parameter for callback api
+ */
+typedef struct {
+ uint8_t flag;
+ uint8_t pkt_type;
+ uint32_t ip_addr;
+ setArpStatsReqCb rsp_cb_fn;
+ void *data_ctx;
+} setArpStatsParams, *psetArpStatsParams;
+
+typedef void(*getArpStatsReqCb)(void *data, rsp_stats *rsp);
+/**
+ * struct getArpStatsParams - get arp stats from firmware
+ * @pkt_type: packet type(1 - ARP)
+ * @get_rsp_cb_fn: FW response callback api
+ * @data_ctx: parameter for callback api
+ */
+typedef struct {
+ uint8_t pkt_type;
+ getArpStatsReqCb get_rsp_cb_fn;
+ void *data_ctx;
+} getArpStatsParams, *pgetArpStatsParams;
+
typedef void(*FWLoggingInitReqCb)(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp);
typedef void ( *tGetFrameLogCallback) (void *pContext);
typedef void(*RssiMonitorReqCb)(void *rssiMonitorCbContext, VOS_STATUS status);
typedef void(*pktFilterReqCb)(void *data, tANI_U32 status);
+
typedef struct sAniGetFrameLogReq
{
tANI_U16 msgType;
@@ -6063,5 +6108,11 @@ typedef struct {
tANI_U32 value;
} tModifyRoamParamsReqParams, * tpModifyRoamParamsReqParams;
+typedef void(*hdd_conAliveCb)(void *data, bool status);
+
+typedef struct {
+ hdd_conAliveCb rsp_cb_fn;
+ void *data_ctx;
+}getConStatusParams, *pgetConStatusParams;
#endif /* __SIR_API_H */
diff --git a/drivers/staging/prima/CORE/MAC/inc/wniApi.h b/drivers/staging/prima/CORE/MAC/inc/wniApi.h
index ff69d7f4504..bdea77c7c0c 100644
--- a/drivers/staging/prima/CORE/MAC/inc/wniApi.h
+++ b/drivers/staging/prima/CORE/MAC/inc/wniApi.h
@@ -235,6 +235,7 @@ enum eWniMsgTypes
eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER,
eWNI_SME_GET_SNR_REQ,
eWNI_SME_LOST_LINK_PARAMS_IND,
+ eWNI_SME_DEL_TEST_BA,
//General Power Save Messages
eWNI_PMC_MSG_TYPES_BEGIN,
eWNI_PMC_PWR_SAVE_CFG,
diff --git a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h
index b91e2fe6378..5dfe0eaf51a 100644
--- a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h
+++ b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h
@@ -144,6 +144,7 @@ typedef enum {
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
PER_BASED_ROAMING = 63,
#endif
+ NUD_DEBUG = 68,
//MAX_FEATURE_SUPPORTED = 128
} placeHolderInCapBitmap;
@@ -765,6 +766,12 @@ typedef struct sSirMbMsgP2p
#define SIR_HAL_PER_ROAM_SCAN_TRIGGER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 289)
#endif
#define SIR_HAL_UPDATE_CFG_INT_PARAM (SIR_HAL_ITC_MSG_TYPES_BEGIN + 290)
+/* ARP Debug stats */
+#define SIR_HAL_SET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 301)
+#define SIR_HAL_GET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 302)
+
+#define SIR_HAL_TRIGGER_ADD_BA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 303)
+#define SIR_HAL_GET_CON_STATUS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 304)
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
// CFG message types
diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index cb83c73df28..e8b9fced0b3 100644
--- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -1625,6 +1625,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
case eWNI_SME_MAC_SPOOF_ADDR_IND:
case eWNI_SME_REGISTER_MGMT_FRAME_CB:
+ case eWNI_SME_DEL_TEST_BA:
// These messages are from HDD
limProcessNormalHddMsg(pMac, limMsg, false); //no need to response to hdd
break;
diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index 1eafb0ef678..cead21d75b1 100644
--- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -5519,6 +5519,57 @@ static void lim_register_mgmt_frame_ind_cb(tpAniSirGlobal pMac,
limLog(pMac, LOGE, FL("sme_req->callback is null"));
}
+static void lim_delba_con_status(tpAniSirGlobal pMac,
+ void *msg_buf)
+{
+ tpSmeDelBAPeerInd delba_params;
+ tpDphHashNode pSta;
+ tANI_U16 aid;
+ tLimBAState curBaState;
+ tpPESession psessionEntry;
+ tANI_U8 sessionId;
+
+ delba_params = (tpSmeDelBAPeerInd)msg_buf;
+
+ psessionEntry = peFindSessionByBssid(pMac, delba_params->bssId, &sessionId);
+ if (!psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));)
+ return;
+ }
+
+ pSta = dphLookupHashEntry(pMac, delba_params->bssId, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if(!pSta)
+ {
+ limLog(pMac, LOGE,
+ FL("STA context not found - ignoring BA Delete IND from HAL"));
+ return;
+ }
+
+ LIM_GET_STA_BA_STATE(pSta, delba_params->baTID, &curBaState);
+ if( eLIM_BA_STATE_IDLE != curBaState )
+ {
+ limLog(pMac, LOGE,
+ FL("Received unexpected BA Delete IND when STA BA state is %d"),
+ curBaState);
+ return;
+ }
+
+ if(eSIR_SUCCESS != limPostMlmDelBAReq(pMac, pSta,
+ delba_params->baDirection,
+ delba_params->baTID,
+ eSIR_MAC_PEER_REJECT_MECHANISIM_REASON,
+ psessionEntry)) {
+ limLog(pMac, LOGE, FL("Post DEL BA request failed"));
+ }
+ else
+ {
+ limLog(pMac, LOG1, FL(" Delete BA session StaId %d on tid %d"),
+ delba_params->staIdx, delba_params->baTID);
+ }
+}
+
/**
* limProcessSmeReqMessages()
*
@@ -5865,6 +5916,9 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
case eWNI_SME_REGISTER_MGMT_FRAME_CB:
lim_register_mgmt_frame_ind_cb(pMac, pMsgBuf);
break;
+ case eWNI_SME_DEL_TEST_BA:
+ lim_delba_con_status(pMac, pMsgBuf);
+ break;
default:
vos_mem_free((v_VOID_t*)pMsg->bodyptr);
pMsg->bodyptr = NULL;
diff --git a/drivers/staging/prima/CORE/SME/inc/sme_Api.h b/drivers/staging/prima/CORE/SME/inc/sme_Api.h
index 41a1640ae52..cf65a45270b 100644
--- a/drivers/staging/prima/CORE/SME/inc/sme_Api.h
+++ b/drivers/staging/prima/CORE/SME/inc/sme_Api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -3961,4 +3961,15 @@ eHalStatus sme_remove_bssid_from_scan_list(tHalHandle hal,
void sme_set_mgmt_frm_via_wq5(tHalHandle hHal,
tANI_BOOLEAN sendMgmtPktViaWQ5);
eHalStatus sme_update_cfg_int_param(tHalHandle hHal, tANI_U32 cfg_id);
+
+/* ARP DEBUG STATS */
+eHalStatus sme_set_nud_debug_stats(tHalHandle hHal,
+ psetArpStatsParams pSetStatsParam);
+eHalStatus sme_get_nud_debug_stats(tHalHandle hHal,
+ pgetArpStatsParams pGetStatsParam);
+eHalStatus sme_test_con_alive(tHalHandle hHal);
+eHalStatus sme_get_con_alive(tHalHandle hHal,
+ pgetConStatusParams conStatusParams);
+eHalStatus sme_test_con_delba(tHalHandle hHal, uint8_t sta_id,
+ uint8_t session_id);
#endif //#if !defined( __SME_API_H )
diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c b/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c
index 947489cd87e..23ab858c355 100644
--- a/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c
+++ b/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c
@@ -2281,6 +2281,18 @@ static tANI_S32 csrFindSelfCongestionScore(tpAniSirGlobal pMac,
if (pSession == NULL)
return -1;
+ if (bssInfo->rssi < pMac->roam.configParam.PERMinRssiThresholdForRoam) {
+ smsLog(pMac, LOG1,
+ FL("Current AP has low rssi=%d than %d"), bssInfo->rssi,
+ pMac->roam.configParam.PERMinRssiThresholdForRoam);
+ /*
+ * Make Current candidate score as zero which will cause roaming
+ * in low RSSI scenarios
+ */
+ pMac->currentBssScore = 0;
+ return 0;
+ }
+
for (i = 0; i <= pMac->PERroamCandidatesCnt; i++)
if (pMac->candidateChannelInfo[i].channelNumber == bssInfo->channelId)
break;
diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c
index 158b36adb58..dbcbccb66d4 100644
--- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c
+++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c
@@ -14419,3 +14419,167 @@ void sme_set_mgmt_frm_via_wq5(tHalHandle hHal, tANI_BOOLEAN sendMgmtPktViaWQ5)
}
return;
}
+
+/* ARP DEBUG STATS */
+
+/**
+ * sme_set_nud_debug_stats() - sme api to set nud debug stats
+ * @hHal: handle to hal
+ * @pSetStatsParam: pointer to set stats param
+ */
+eHalStatus sme_set_nud_debug_stats(tHalHandle hHal,
+ setArpStatsParams *pSetStatsParam)
+{
+ setArpStatsParams *arp_set_param;
+ vos_msg_t msg;
+
+ arp_set_param = vos_mem_malloc(sizeof(*arp_set_param));
+ if (arp_set_param == NULL) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Memory allocation failure"));
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ vos_mem_copy(arp_set_param, pSetStatsParam, sizeof(*arp_set_param));
+
+ msg.type = WDA_SET_ARP_STATS_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = arp_set_param;
+
+ if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Not able to post message to WDA"));
+ vos_mem_free(arp_set_param);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**
+ * sme_get_nud_debug_stats() - sme api to get nud debug stats
+ * @hHal: handle to hal
+ * @pGetStatsParam: pointer to set stats param
+ */
+eHalStatus sme_get_nud_debug_stats(tHalHandle hHal,
+ getArpStatsParams *pGetStatsParam)
+{
+ getArpStatsParams *arpGetParams;
+ vos_msg_t msg;
+
+ arpGetParams = vos_mem_malloc(sizeof(*arpGetParams));
+ if (arpGetParams == NULL) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Memory allocation failure"));
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ vos_mem_copy(arpGetParams, pGetStatsParam, sizeof(*arpGetParams));
+
+ msg.type = WDA_GET_ARP_STATS_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = arpGetParams;
+
+ if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Not able to post message to WDA"));
+ vos_mem_free(arpGetParams);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+eHalStatus sme_test_con_alive(tHalHandle hHal)
+{
+ vos_msg_t wdaMsg = {0};
+
+ wdaMsg.type = WDA_TRIGGER_ADD_BA_REQ;
+ wdaMsg.bodyptr = NULL;
+ wdaMsg.reserved = 0;
+
+ if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_WDA, &wdaMsg))
+ return VOS_STATUS_E_FAILURE;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+
+eHalStatus sme_get_con_alive(tHalHandle hHal,
+ pgetConStatusParams conStatusParams)
+{
+ vos_msg_t wdaMsg = {0};
+ pgetConStatusParams statusParams;
+ VOS_STATUS vosStatus;
+
+ statusParams = vos_mem_malloc(sizeof(getConStatusParams));
+ if (NULL == statusParams) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Memory allocation failure"));
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ vos_mem_copy(statusParams, conStatusParams, sizeof(getConStatusParams));
+ wdaMsg.type = WDA_GET_CON_STATUS;
+ wdaMsg.bodyptr = statusParams;
+ wdaMsg.reserved = 0;
+
+ vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &wdaMsg);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL(" Not able to post message"));
+ vos_mem_free(statusParams);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+eHalStatus sme_test_con_delba(tHalHandle hHal, uint8_t sta_id,
+ uint8_t session_id)
+{
+ tpSmeDelBAPeerInd msg;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, session_id);
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ if (!CSR_IS_SESSION_VALID(pMac, session_id))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Session is invalid"));
+ return status;
+ }
+
+ if (!pMac->lim.test_status_bainfo.tx_aggr)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("BA session not established"));
+ return status;
+ }
+
+ if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme))
+ {
+ msg = vos_mem_malloc(sizeof(tSmeDelBAPeerInd));
+ if (NULL == msg)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Memory allocation failure"));
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ msg->staIdx = sta_id;
+ msg->baTID = pMac->lim.test_status_bainfo.tid;
+ vos_mem_copy(msg->bssId, pSession->connectedProfile.bssid,
+ sizeof(tSirMacAddr));
+ msg->baDirection = eBA_INITIATOR;
+
+ msg->mesgType = eWNI_SME_DEL_TEST_BA;
+ msg->mesgLen = sizeof(tSmeDelBAPeerInd);
+
+ status = palSendMBMessage(pMac->hHdd, msg);
+
+ sme_ReleaseGlobalLock(&pMac->sme);
+ }
+
+ return status;
+}
diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c
index 12a8a6b5a40..0da70dc30c0 100644
--- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -906,6 +906,10 @@ tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg )
CASE_RETURN_STRING(WDA_MON_STOP_REQ);
CASE_RETURN_STRING(WDA_SPOOF_MAC_ADDR_REQ);
CASE_RETURN_STRING(WDA_LOST_LINK_PARAMS_IND);
+ CASE_RETURN_STRING(WDA_SET_ARP_STATS_REQ);
+ CASE_RETURN_STRING(WDA_GET_ARP_STATS_REQ);
+ CASE_RETURN_STRING(WDA_TRIGGER_ADD_BA_REQ);
+ CASE_RETURN_STRING(WDA_GET_CON_STATUS);
default:
return((tANI_U8*) "UNKNOWN" );
break;
diff --git a/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h b/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h
index 9b80e046023..35d9f7d976b 100644
--- a/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h
+++ b/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h
@@ -3376,4 +3376,13 @@ void WLANTL_ResetRxSSN(v_PVOID_t pvosGCtx, uint8_t ucSTAId);
* Return: none
*/
void WLANTL_SetDataPktFilter(v_PVOID_t pvosGCtx, uint8_t ucSTAId, bool flag);
+
+/**
+ * WLANTL_SetARPFWDatapath() - keep or remove FW in data path for ARP
+ * @pvosGCtx: global vos context
+ * @flag: value to keep or remove FW from data path
+ *
+ * Return: void
+ */
+void WLANTL_SetARPFWDatapath(void * pvosGCtx, bool flag);
#endif /* #ifndef WLAN_QCT_WLANTL_H */
diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c
index ae95be50dd7..09754b8a967 100644
--- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c
+++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c
@@ -2752,8 +2752,8 @@ WLANTL_TxBAPFrm
ucWDSEnabled, extraHeadSpace, pMetaInfo->ucType,
&pTLCb->atlSTAClients[ucStaId]->wSTADesc.vSelfMACAddress,
pMetaInfo->ucTID, 0 /* No ACK */, pMetaInfo->usTimeStamp,
- pMetaInfo->ucIsEapol || pMetaInfo->ucIsWai, pMetaInfo->ucUP,
- pMetaInfo->ucTxBdToken);
+ pMetaInfo->ucIsEapol || pMetaInfo->ucIsWai, pMetaInfo->ucIsArp,
+ pMetaInfo->ucUP, pMetaInfo->ucTxBdToken);
if ( VOS_STATUS_SUCCESS != vosStatus )
{
@@ -3694,7 +3694,7 @@ WLANTL_TxMgmtFrm
vosStatus = WDA_DS_BuildTxPacketInfo( pvosGCtx, vosFrmBuf , &vDestMacAddr,
1 /* always 802.11 frames*/, &usPktLen, uQosHdr /*qos not enabled !!!*/,
0 /* WDS off */, 0, wFrmType, pvAddr2MacAddr, ucTid,
- ucAckResponse, usTimeStamp, 0, 0, ucTxBdToken);
+ ucAckResponse, usTimeStamp, 0, 0, 0, ucTxBdToken);
if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
@@ -7887,8 +7887,8 @@ WLANTL_STATxConn
extraHeadSpace,
ucTypeSubtype, &pClientSTA->wSTADesc.vSelfMACAddress,
ucTid, txFlag,
- tlMetaInfo.usTimeStamp, tlMetaInfo.ucIsEapol || tlMetaInfo.ucIsWai, tlMetaInfo.ucUP,
- tlMetaInfo.ucTxBdToken);
+ tlMetaInfo.usTimeStamp, tlMetaInfo.ucIsEapol || tlMetaInfo.ucIsWai,
+ tlMetaInfo.ucIsArp, tlMetaInfo.ucUP, tlMetaInfo.ucTxBdToken);
if ( VOS_STATUS_SUCCESS != vosStatus )
{
@@ -8307,6 +8307,18 @@ WLANTL_STATxAuth
#endif /* FEATURE_WLAN_TDLS */
if( tlMetaInfo.ucIsArp )
{
+ if (pTLCb->track_arp)
+ {
+ if (vos_check_arp_req_target_ip(vosDataBuff->pSkb, true))
+ {
+ ucTxFlag |= HAL_USE_FW_IN_TX_PATH;
+ ucTxFlag |= HAL_TXCOMP_REQUESTED_MASK;
+ tlMetaInfo.ucTxBdToken = ++ pTLCb->txbd_token;
+ TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
+ "%s: ARP packet FW in data path", __func__));
+ }
+ }
+
if (pStaClient->arpOnWQ5)
{
ucTxFlag |= HAL_USE_FW_IN_TX_PATH;
@@ -8331,7 +8343,7 @@ WLANTL_STATxAuth
extraHeadSpace,
ucTypeSubtype, &pStaClient->wSTADesc.vSelfMACAddress,
ucTid, ucTxFlag, tlMetaInfo.usTimeStamp,
- tlMetaInfo.ucIsEapol, tlMetaInfo.ucUP,
+ tlMetaInfo.ucIsEapol, tlMetaInfo.ucIsArp, tlMetaInfo.ucUP,
tlMetaInfo.ucTxBdToken);
if(!VOS_IS_STATUS_SUCCESS(vosStatus))
@@ -13816,6 +13828,29 @@ void WLANTL_ResetRxSSN(v_PVOID_t pvosGCtx, uint8_t ucSTAId)
}
}
+/**
+ * WLANTL_SetARPFWDatapath() - keep or remove FW in data path for ARP
+ *
+ * @flag: value to keep or remove FW from data path
+ *
+ * Return: void
+ */
+void WLANTL_SetARPFWDatapath(void * pvosGCtx, bool flag)
+{
+
+ WLANTL_CbType* pTLCb = NULL;
+
+ pTLCb = VOS_GET_TL_CB(pvosGCtx);
+ if (NULL == pTLCb) {
+ TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid TL pointer from pvosGCtx", __func__));
+ return;
+ }
+
+ pTLCb->track_arp = flag;
+
+}
+
#ifdef WLAN_FEATURE_RMC
VOS_STATUS WLANTL_RmcInit
(
diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c
index f9405850412..ccfcfb0c699 100644
--- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c
+++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1165,6 +1165,12 @@ VOS_STATUS WLANTL_MSDUReorder
TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
"(QCUR_FWDBUF) dropping old frame, SN=%d LastSN=%d",
CSN, currentReorderInfo->LastSN));
+ if (vos_is_arp_pkt((*vosDataBuff)->pSkb, true))
+ {
+ if (vos_check_arp_rsp_src_ip((*vosDataBuff)->pSkb, true))
+ vos_update_arp_rx_drop_reorder();
+ }
+
status = vos_pkt_return_packet(*vosDataBuff);
if (!VOS_IS_STATUS_SUCCESS(status))
{
diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h b/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h
index 4d23eb22781..fdb5898b8fb 100644
--- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h
+++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h
@@ -967,6 +967,8 @@ typedef struct
WLANTL_RoamMonitorType gDsRxRoamStats;
#endif
+ uint8_t track_arp;
+ uint32_t txbd_token;
}WLANTL_CbType;
diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_api.h b/drivers/staging/prima/CORE/VOSS/inc/vos_api.h
index b1b846cd3f9..898a039c4b7 100644
--- a/drivers/staging/prima/CORE/VOSS/inc/vos_api.h
+++ b/drivers/staging/prima/CORE/VOSS/inc/vos_api.h
@@ -526,4 +526,11 @@ v_BOOL_t vos_is_probe_rsp_offload_enabled(void);
void vos_smd_dump_stats(void);
void vos_log_wdi_event(uint16 msg, vos_wdi_trace_event_type event);
void vos_dump_wdi_events(void);
+
+bool vos_check_arp_target_ip(void *pSkb, bool conversion);
+bool vos_check_arp_req_target_ip(void *pSkb, bool conversion);
+bool vos_check_arp_src_ip(void *pSkb, bool conversion);
+bool vos_check_arp_rsp_src_ip(void *pSkb, bool conversion);
+void vos_update_arp_fw_tx_delivered(void);
+void vos_update_arp_rx_drop_reorder(void);
#endif // if !defined __VOS_NVITEM_H
diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h b/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h
index 3aa0a33b55e..06e8e2c9ef2 100644
--- a/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h
+++ b/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -53,6 +53,16 @@
#define VOS_PKT_PROTO_TYPE_EAPOL 0x02
#define VOS_PKT_PROTO_TYPE_DHCP 0x04
#define VOS_PKT_PROTO_TYPE_ARP 0x08
+
+/* ARP packet offset values */
+#define VOS_PKT_ARP_OPCODE_OFFSET 20
+#define VOS_PKT_ARPOP_REQUEST 1
+#define VOS_PKT_ARPOP_REPLY 2
+#define VOS_ARP_TARGET_IP_OFFSET 38
+#define VOS_ARP_SRC_IP_OFFSET 28
+
+#define VOS_80211_8023_HEADER_OFFSET 20
+
/*--------------------------------------------------------------------------
Type declarations
------------------------------------------------------------------------*/
@@ -1170,4 +1180,16 @@ v_PVOID_t vos_get_pkt_end(vos_pkt_t *pPacket);
*/
v_VOID_t vos_recover_tail(vos_pkt_t *pPacket);
+/**
+ @breaf vos_is_arp_pkt() - Check the packet is ARP or not.
+
+ @param
+ pskb - pointer to skb
+ is_translated - header translation check
+ @return
+ TRUE - if packet is ARP
+ FALSE -if packet is not ARP
+*/
+bool vos_is_arp_pkt(void *pskb, bool is_translated);
+
#endif // !defined( __VOS_PKT_H )
diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_api.c b/drivers/staging/prima/CORE/VOSS/src/vos_api.c
index f218b8e5d3a..881a2b59bd6 100644
--- a/drivers/staging/prima/CORE/VOSS/src/vos_api.c
+++ b/drivers/staging/prima/CORE/VOSS/src/vos_api.c
@@ -3664,3 +3664,268 @@ void vos_dump_wdi_events(void)
gvos_wdi_msg_trace[i].message);
}
}
+/**
+ * vos_check_arp_target_ip() - check if the Target IP is gateway IP
+ * @pPacket: pointer to vos packet
+ * @conversion: 802.3 to 802.11 frame conversion
+ *
+ * Return: true if the IP is of gateway or false otherwise
+ */
+bool vos_check_arp_target_ip(void *pSkb, bool conversion)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ hdd_context_t *pHddCtx = NULL;
+ struct sk_buff *skb;
+ uint8_t offset;
+
+ if(!pVosContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return false;
+ }
+
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+ if(!pHddCtx) {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is Null", __func__);
+ return false;
+ }
+
+ if (unlikely(NULL == pSkb))
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: NULL pointer", __func__);
+ return false;
+ }
+
+ skb = (struct sk_buff *)pSkb;
+
+ if (conversion)
+ offset = VOS_ARP_TARGET_IP_OFFSET + VOS_80211_8023_HEADER_OFFSET;
+ else
+ offset = VOS_ARP_TARGET_IP_OFFSET;
+
+ if (pHddCtx->track_arp_ip ==
+ (v_U32_t)(*(v_U32_t *)(skb->data + offset)))
+ return true;
+
+ return false;
+}
+
+/**
+ * vos_check_arp_req_target_ip() - check if the ARP is request and
+ target IP is gateway
+ * @pPacket: pointer to vos packet
+ * @conversion: 802.3 to 802.11 frame conversion
+ *
+ * Return: true if the IP is of gateway or false otherwise
+ */
+bool vos_check_arp_req_target_ip(void *pSkb, bool conversion)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ struct sk_buff *skb;
+ uint8_t offset;
+
+ if(!pVosContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return false;
+ }
+
+ if (unlikely(NULL == pSkb))
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: NULL pointer", __func__);
+ return false;
+ }
+
+ skb = (struct sk_buff *)pSkb;
+
+ if (conversion)
+ offset = VOS_PKT_ARP_OPCODE_OFFSET + VOS_80211_8023_HEADER_OFFSET;
+ else
+ offset = VOS_PKT_ARP_OPCODE_OFFSET;
+
+ if (htons(VOS_PKT_ARPOP_REQUEST) ==
+ (uint16_t)(*(uint16_t *)(skb->data + offset)))
+ {
+ if (vos_check_arp_target_ip(skb, conversion))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * vos_check_arp_src_ip() - check if the ARP response src IP is gateway IP
+ * @pPacket: pointer to vos packet
+ * @conversion: 802.3 to 802.11 frame conversion
+ *
+ * Return: true if the IP is of gateway or false otherwise
+ */
+bool vos_check_arp_src_ip(void *pSkb, bool conversion)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ hdd_context_t *pHddCtx = NULL;
+ struct sk_buff *skb;
+ uint8_t offset;
+
+ if(!pVosContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return false;
+ }
+
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+ if(!pHddCtx) {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is Null", __func__);
+ return false;
+ }
+
+ if (unlikely(NULL == pSkb))
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: NULL pointer", __func__);
+ return false;
+ }
+
+ skb = (struct sk_buff *)pSkb;
+
+ if (conversion)
+ offset = VOS_ARP_SRC_IP_OFFSET + VOS_80211_8023_HEADER_OFFSET;
+ else
+ offset = VOS_ARP_SRC_IP_OFFSET;
+
+ if (pHddCtx->track_arp_ip ==
+ (v_U32_t)(*(v_U32_t *)(skb->data + offset)))
+ return true;
+
+ return false;
+}
+
+/**
+ * vos_check_arp_rsp_src_ip() - check if the ARP is request and
+ target IP is gateway
+ * @pPacket: pointer to vos packet
+ * @conversion: 802.3 to 802.11 frame conversion
+ *
+ * Return: true if the IP is of gateway or false otherwise
+ */
+bool vos_check_arp_rsp_src_ip(void *pSkb, bool conversion)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ struct sk_buff *skb;
+ uint8_t offset;
+
+ if(!pVosContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return false;
+ }
+
+ if (unlikely(NULL == pSkb))
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: NULL pointer", __func__);
+ return false;
+ }
+
+ skb = (struct sk_buff *)pSkb;
+
+ if (conversion)
+ offset = VOS_PKT_ARP_OPCODE_OFFSET + VOS_80211_8023_HEADER_OFFSET;
+ else
+ offset = VOS_PKT_ARP_OPCODE_OFFSET;
+
+ if (htons(VOS_PKT_ARPOP_REPLY) ==
+ (uint16_t)(*(uint16_t *)(skb->data + offset)))
+ {
+ if (vos_check_arp_src_ip(skb, conversion))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * vos_update_arp_fw_tx_delivered() - update the ARP stats host to FW deliver
+ * count
+ *
+ * Return: None
+ */
+void vos_update_arp_fw_tx_delivered(void)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ hdd_context_t *pHddCtx = NULL;
+ hdd_adapter_t * pAdapter;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ uint8_t status;
+
+ if(!pVosContext) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return;
+ }
+
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+ if(!pHddCtx) {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is Null", __func__);
+ return;
+ }
+
+ status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
+
+ while (NULL != pAdapterNode && 0 == status)
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+ break;
+
+ status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
+ pAdapterNode = pNext;
+ }
+
+ pAdapter->hdd_stats.hddArpStats.tx_host_fw_sent++;
+}
+
+/**
+ * vos_update_arp_rx_drop_reorder() - update the RX ARP stats drop due
+ * reorder logic at host
+ *
+ * Return: None
+ */
+void vos_update_arp_rx_drop_reorder(void)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ hdd_context_t *pHddCtx = NULL;
+ hdd_adapter_t * pAdapter;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ uint8_t status;
+
+ if(!pVosContext) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return;
+ }
+
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+ if(!pHddCtx) {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is Null", __func__);
+ return;
+ }
+
+ status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
+
+ while (NULL != pAdapterNode && 0 == status)
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+ break;
+
+ status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
+ pAdapterNode = pNext;
+ }
+
+ pAdapter->hdd_stats.hddArpStats.rx_host_drop_reorder++;
+}
diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_packet.c b/drivers/staging/prima/CORE/VOSS/src/vos_packet.c
index 43daf9f7d37..733217687af 100644
--- a/drivers/staging/prima/CORE/VOSS/src/vos_packet.c
+++ b/drivers/staging/prima/CORE/VOSS/src/vos_packet.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -3100,6 +3100,35 @@ v_U8_t vos_pkt_get_proto_type
return pkt_proto_type;
}
+bool vos_is_arp_pkt(void *pskb, bool is_translated)
+{
+ v_U16_t ether_type;
+ struct sk_buff *skb = NULL;
+#define HEADER_OFFSET_802_11 20
+
+ if (NULL == pskb)
+ {
+ return FALSE;
+ }
+
+ skb = (struct sk_buff *)pskb;
+
+ if (is_translated)
+ ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_ETH_TYPE_OFFSET + HEADER_OFFSET_802_11));
+ else
+ ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_ETH_TYPE_OFFSET));
+
+ if (VOS_PKT_PROT_ARP_ETH_TYPE == VOS_SWAP_U16(ether_type))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+#undef HEADER_OFFSET_802_11
+}
+
v_PVOID_t vos_get_pkt_head(vos_pkt_t *pPacket)
{
struct sk_buff *skb;
diff --git a/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h b/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h
index d058e45ac0d..fdc768d8ca4 100644
--- a/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h
+++ b/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -525,6 +525,10 @@ typedef struct
uint8_t mgmt_pktfree_fail;
vos_lock_t mgmt_pkt_lock;
+ /* debug connection status */
+ bool tx_aggr;
+ uint8_t sta_id;
+ uint8_t tid;
} tWDA_CbContext ;
typedef struct
@@ -1291,6 +1295,12 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb);
#define WDA_START_RSSI_MONITOR_REQ SIR_HAL_RSSI_MON_START_REQ
#define WDA_STOP_RSSI_MONITOR_REQ SIR_HAL_RSSI_MON_STOP_REQ
+/* ARP Debug */
+#define WDA_SET_ARP_STATS_REQ SIR_HAL_SET_ARP_STATS_REQ
+#define WDA_GET_ARP_STATS_REQ SIR_HAL_GET_ARP_STATS_REQ
+#define WDA_TRIGGER_ADD_BA_REQ SIR_HAL_TRIGGER_ADD_BA_REQ
+#define WDA_GET_CON_STATUS SIR_HAL_GET_CON_STATUS
+
tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg);
eHalStatus WDA_SetRegDomain(void * clientCtxt, v_REGDOMAIN_t regId,
@@ -1598,6 +1608,7 @@ WDA_DS_FinishULA
txFlag
timeStamp
ucIsEapol
+ ucIsArp
ucUP
OUT
@@ -1627,6 +1638,7 @@ WDA_DS_BuildTxPacketInfo
v_U32_t txFlag,
v_U32_t timeStamp,
v_U8_t ucIsEapol,
+ v_U8_t ucIsArp,
v_U8_t ucUP,
v_U32_t ucTxBdToken
);
diff --git a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c
index d6df4091f01..f88a83b8398 100644
--- a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c
+++ b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c
@@ -165,7 +165,12 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd,
static VOS_STATUS wdaCreateTimers(tWDA_CbContext *pWDA) ;
static VOS_STATUS wdaDestroyTimers(tWDA_CbContext *pWDA);
bool WDA_AllowAddBA(tpAniSirGlobal pMAc, tANI_U8 staId, tANI_U8 tid);
-void WDA_BaCheckActivity(tWDA_CbContext *pWDA) ;
+void WDA_BaCheckActivity(tWDA_CbContext *pWDA, bool test_con);
+
+/* check connection status */
+void WDA_GetConnectionStatus(tWDA_CbContext *pWDA,
+ getConStatusParams *conStatusParams);
+
void WDA_TimerTrafficStatsInd(tWDA_CbContext *pWDA);
void WDA_HALDumpCmdCallback(WDI_HALDumpCmdRspParamsType *wdiRspParams, void* pUserData);
#ifdef WLAN_FEATURE_VOWIFI_11R
@@ -15302,6 +15307,266 @@ VOS_STATUS WDA_ProcessTLPauseInd(tWDA_CbContext *pWDA, v_U32_t params)
return WLANTL_SuspendDataTx(pWDA->pVosContext, &staId, NULL);
}
+/**
+ * WDA_SetARPStatsParamsRspCallback() - WDA callback api to set/reset arp stats
+ * @wdiSetStatsRsp: pointer to set stats response
+ * @user_data: user data
+ *
+ * Return: None
+ */
+void WDA_SetARPStatsParamsRspCallback(
+ WDI_SetARPStatsRspParamsType *wdiSetStatsRsp,
+ void *user_data)
+{
+ tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data;
+ setArpStatsParams *arpStatsParams;
+
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "ENTER <------ %s " ,__func__);
+
+ if(NULL == wda_params)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: wda_params received NULL", __func__);
+ VOS_ASSERT(0);
+ return;
+ }
+
+ if(NULL == wda_params->wdaMsgParam)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: wda_params->wdaMsgParam is NULL", __func__);
+ VOS_ASSERT(0);
+ vos_mem_free(wda_params->wdaWdiApiMsgParam);
+ vos_mem_free(wda_params);
+ return;
+ }
+
+ arpStatsParams = (setArpStatsParams *)wda_params->wdaMsgParam;
+ if(arpStatsParams->rsp_cb_fn)
+ {
+ arpStatsParams->rsp_cb_fn(arpStatsParams->data_ctx,
+ CONVERT_WDI2VOS_STATUS(wdiSetStatsRsp->status));
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: ARP stats callback is NULL", __func__);
+ }
+
+ vos_mem_free(wda_params->wdaWdiApiMsgParam);
+ vos_mem_free(wda_params->wdaMsgParam);
+ vos_mem_free(wda_params);
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "EXIT <------ %s " ,__func__);
+ return;
+}
+
+/**
+ * WDA_GetARPStatsParamsRspCallback() - WDA callback api to get arp stats
+ * @wdiGetStatsRsp: pointer to get stats response
+ * @user_data: user data
+ *
+ * Return: None
+ */
+void WDA_GetARPStatsParamsRspCallback(
+ WDI_GetARPStatsRspParamsType *wdiGetStatsRsp,
+ void *user_data)
+{
+ tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data;
+ getArpStatsParams *arpStatsParams;
+
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "ENTER <------ %s " ,__func__);
+
+ if(NULL == wda_params)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: wda_params received NULL", __func__);
+ VOS_ASSERT(0);
+ return;
+ }
+
+ if(NULL == wda_params->wdaMsgParam)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: wda_params->wdaMsgParam is NULL", __func__);
+ VOS_ASSERT(0);
+ vos_mem_free(wda_params->wdaWdiApiMsgParam);
+ vos_mem_free(wda_params);
+ return;
+ }
+
+ arpStatsParams = (getArpStatsParams *)wda_params->wdaMsgParam;
+ if(arpStatsParams->get_rsp_cb_fn)
+ {
+ arpStatsParams->get_rsp_cb_fn(arpStatsParams->data_ctx,
+ (rsp_stats *)wdiGetStatsRsp);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: ARP stats callback is NULL", __func__);
+ }
+
+ vos_mem_free(wda_params->wdaWdiApiMsgParam);
+ vos_mem_free(wda_params->wdaMsgParam);
+ vos_mem_free(wda_params);
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "EXIT <------ %s " ,__func__);
+ return;
+}
+
+/**
+ * WDA_ProcessSetARPStatsReq() - WDA api to process set arp stats command
+ * @pWDA: wda handle
+ * @pSetStatsParams: pointer to set arp stats
+ *
+ * Return: VOS_STATUS
+ * 0 Success else failure
+ */
+VOS_STATUS WDA_ProcessSetARPStatsReq(tWDA_CbContext *pWDA,
+ setArpStatsParams *pSetStatsParams)
+{
+ WDI_SetARPStatsParamsInfoType *wdiSetStatsParam;
+ tWDA_ReqParams *wda_params;
+ WDI_Status wdi_status = WDI_STATUS_SUCCESS;
+
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+ FL("---> %s"), __func__);
+
+ if(NULL == pSetStatsParams)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: pSetStatsParams received NULL",
+ __func__);
+ VOS_ASSERT(0) ;
+ return VOS_STATUS_E_FAULT;
+ }
+
+ wdiSetStatsParam = (WDI_SetARPStatsParamsInfoType *)
+ vos_mem_malloc(sizeof(*wdiSetStatsParam));
+ if (!wdiSetStatsParam) {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "Failed to allocate buffer to send "
+ "set_dhcp_server_offload cmd");
+ vos_mem_free(pSetStatsParams);
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ vos_mem_zero(wdiSetStatsParam, sizeof(*wdiSetStatsParam));
+
+ wda_params = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ;
+ if(NULL == wda_params)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: VOS MEM Alloc Failure", __func__);
+ VOS_ASSERT(0);
+ vos_mem_free(wdiSetStatsParam);
+ vos_mem_free(pSetStatsParams);
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ wdiSetStatsParam->flag = pSetStatsParams->flag;
+ wdiSetStatsParam->pkt_type = pSetStatsParams->pkt_type;
+ wdiSetStatsParam->ip_addr = pSetStatsParams->ip_addr;
+
+ /* Store Params pass it to WDI */
+ wda_params->wdaWdiApiMsgParam = (void *)wdiSetStatsParam;
+ wda_params->pWdaContext = pWDA;
+ /* Store param pointer as passed in by caller */
+ wda_params->wdaMsgParam = pSetStatsParams;
+
+ wdi_status = WDI_SetARPStatsReq(wdiSetStatsParam,
+ (WDI_SetARPStatsRspCb)WDA_SetARPStatsParamsRspCallback,
+ wda_params);
+
+ if(IS_WDI_STATUS_FAILURE(wdi_status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failure, free all the memory", __func__);
+ vos_mem_free(wda_params->wdaWdiApiMsgParam) ;
+ vos_mem_free(wda_params->wdaMsgParam);
+ vos_mem_free(wda_params);
+ }
+
+ return wdi_status;
+}
+
+/**
+ * WDA_ProcessGetARPStatsReq() - WDA api to process get arp stats command
+ * @pWDA: wda handle
+ * @pGetStatsParams: pointer to get arp stats
+ *
+ * Return: VOS_STATUS
+ * 0 Success else failure
+ */
+VOS_STATUS WDA_ProcessGetARPStatsReq(tWDA_CbContext *pWDA,
+ getArpStatsParams *pGetStatsParams)
+{
+ WDI_GetARPStatsParamsInfoType *wdiGetStatsParam;
+ tWDA_ReqParams *wda_params;
+ WDI_Status wdi_status = WDI_STATUS_SUCCESS;
+
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+ FL("---> %s"), __func__);
+
+ if(NULL == pGetStatsParams)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: pGetStatsParams received NULL",
+ __func__);
+ VOS_ASSERT(0) ;
+ return VOS_STATUS_E_FAULT;
+ }
+
+ wdiGetStatsParam = (WDI_GetARPStatsParamsInfoType *)
+ vos_mem_malloc(sizeof(*wdiGetStatsParam));
+ if (!wdiGetStatsParam) {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "Failed to allocate buffer to send "
+ "set_dhcp_server_offload cmd");
+ vos_mem_free(pGetStatsParams);
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ vos_mem_zero(wdiGetStatsParam, sizeof(*wdiGetStatsParam));
+
+ wda_params = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ;
+ if(NULL == wda_params)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: VOS MEM Alloc Failure", __func__);
+ VOS_ASSERT(0);
+ vos_mem_free(wdiGetStatsParam);
+ vos_mem_free(pGetStatsParams);
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ wdiGetStatsParam->pkt_type = pGetStatsParams->pkt_type;
+
+ /* Store Params pass it to WDI */
+ wda_params->wdaWdiApiMsgParam = (void *)wdiGetStatsParam;
+ wda_params->pWdaContext = pWDA;
+ /* Store param pointer as passed in by caller */
+ wda_params->wdaMsgParam = pGetStatsParams;
+
+ wdi_status = WDI_GetARPStatsReq(wdiGetStatsParam,
+ (WDI_GetARPStatsRspCb)WDA_GetARPStatsParamsRspCallback,
+ wda_params);
+
+ if(IS_WDI_STATUS_FAILURE(wdi_status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failure, free all the memory", __func__);
+ vos_mem_free(wda_params->wdaWdiApiMsgParam) ;
+ vos_mem_free(wda_params->wdaMsgParam);
+ vos_mem_free(wda_params);
+ }
+
+ return wdi_status;
+}
+
/*
* FUNCTION: WDA_McProcessMsg
* Trigger DAL-AL to start CFG download
@@ -15924,16 +16189,26 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg )
/* timer related messages */
case WDA_TIMER_BA_ACTIVITY_REQ:
{
- WDA_BaCheckActivity(pWDA) ;
+ WDA_BaCheckActivity(pWDA, false);
break ;
}
-
/* timer related messages */
case WDA_TIMER_TRAFFIC_STATS_IND:
{
WDA_TimerTrafficStatsInd(pWDA);
break;
}
+ /* Connection status related messages */
+ case WDA_TRIGGER_ADD_BA_REQ:
+ {
+ WDA_BaCheckActivity(pWDA, true);
+ break;
+ }
+ case WDA_GET_CON_STATUS:
+ {
+ WDA_GetConnectionStatus(pWDA, (getConStatusParams *)pMsg->bodyptr);
+ break;
+ }
#ifdef WLAN_FEATURE_VOWIFI_11R
case WDA_AGGR_QOS_REQ:
{
@@ -16290,6 +16565,16 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg )
WDA_ProcessTLPauseInd(pWDA, pMsg->bodyval);
break;
}
+ case WDA_SET_ARP_STATS_REQ:
+ {
+ WDA_ProcessSetARPStatsReq(pWDA, (setArpStatsParams *)pMsg->bodyptr);
+ break;
+ }
+ case WDA_GET_ARP_STATS_REQ:
+ {
+ WDA_ProcessGetARPStatsReq(pWDA, (getArpStatsParams *)pMsg->bodyptr);
+ break;
+ }
default:
{
VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
@@ -17639,10 +17924,45 @@ bool WDA_AllowAddBA(tpAniSirGlobal pMac, tANI_U8 staId, tANI_U8 tid)
return true;
}
+void WDA_GetConnectionStatus(tWDA_CbContext *pWDA,
+ getConStatusParams *conStatusParams)
+{
+ tpAniSirGlobal pMac;
+ uint8_t sta_id, tid;
+ bool tx_aggr;
+ bool status = false;
+
+ pMac = (tpAniSirGlobal)VOS_GET_MAC_CTXT(pWDA->pVosContext);
+ if (NULL == pMac)
+ {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+ "%s: pMac is NULL",__func__);
+ return;
+ }
+
+ tx_aggr= pMac->lim.test_status_bainfo.tx_aggr;
+ sta_id = pMac->lim.test_status_bainfo.sta_id;
+ tid = pMac->lim.test_status_bainfo.tid;
+
+ if (tx_aggr && WDA_GET_BA_TXFLAG(pWDA, sta_id, tid))
+ status = true;
+
+ if (conStatusParams->rsp_cb_fn)
+ conStatusParams->rsp_cb_fn(conStatusParams->data_ctx, status);
+}
+
+static void WDA_StoreTestBAInfo(tpAniSirGlobal pMac, bool tx_aggr,
+ uint8_t sta_id, uint8_t tid)
+{
+ pMac->lim.test_status_bainfo.tx_aggr = tx_aggr;
+ pMac->lim.test_status_bainfo.sta_id= sta_id;
+ pMac->lim.test_status_bainfo.tid = tid;
+}
+
/*
* BA Activity check timer handler
*/
-void WDA_BaCheckActivity(tWDA_CbContext *pWDA)
+void WDA_BaCheckActivity(tWDA_CbContext *pWDA, bool test_con)
{
tANI_U8 curSta = 0 ;
tANI_U8 tid = 0 ;
@@ -17652,6 +17972,7 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA)
tANI_U32 val;
WDI_TriggerBAReqCandidateType baCandidate[WDA_MAX_STA] = {{0}} ;
tpAniSirGlobal pMac;
+ bool found = false;
if (NULL == pWDA)
{
@@ -17695,6 +18016,12 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA)
for(curSta = 0 ; curSta < pWDA->wdaMaxSta ; curSta++)
{
tANI_U32 currentOperChan = pWDA->wdaStaInfo[curSta].currentOperChan;
+ WLANTL_STAStateType tlSTAState;
+ tANI_U8 validStaIndex = pWDA->wdaStaInfo[curSta].ucValidStaIndex;
+
+ if (found)
+ break;
+
#ifdef WLAN_SOFTAP_VSTA_FEATURE
// We can only do BA on "hard" STAs.
if (!(IS_HWSTA_IDX(curSta)))
@@ -17702,41 +18029,47 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA)
continue;
}
#endif //WLAN_SOFTAP_VSTA_FEATURE
+
+ if (!((WDA_VALID_STA_INDEX == validStaIndex) &&
+ (VOS_STATUS_SUCCESS == WDA_TL_GET_STA_STATE(pWDA->pVosContext,
+ curSta, &tlSTAState))))
+ continue;
+
+ if (WLANTL_STA_AUTHENTICATED != tlSTAState)
+ continue;
+
+ if(val && ((currentOperChan >= SIR_11B_CHANNEL_BEGIN) &&
+ (currentOperChan <= SIR_11B_CHANNEL_END))) {
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+ "%s: BTC disabled aggregation - dont start"
+ "TX ADDBA req",__func__);
+ continue;
+ }
+
for(tid = 0 ; tid < STACFG_MAX_TC ; tid++)
{
- WLANTL_STAStateType tlSTAState ;
tANI_U32 txPktCount = 0 ;
- tANI_U8 validStaIndex = pWDA->wdaStaInfo[curSta].ucValidStaIndex ;
- if((WDA_VALID_STA_INDEX == validStaIndex) &&
- (VOS_STATUS_SUCCESS == WDA_TL_GET_STA_STATE( pWDA->pVosContext,
- curSta, &tlSTAState)) &&
- (VOS_STATUS_SUCCESS == WDA_TL_GET_TX_PKTCOUNT( pWDA->pVosContext,
- curSta, tid, &txPktCount)))
+ if (VOS_STATUS_SUCCESS == WDA_TL_GET_TX_PKTCOUNT( pWDA->pVosContext,
+ curSta, tid, &txPktCount))
{
-#if 0
- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_LOW,
- "************* %d:%d, %d ",curSta, txPktCount,
- pWDA->wdaStaInfo[curSta].framesTxed[tid]);
-#endif
- if(val && ( (currentOperChan >= SIR_11B_CHANNEL_BEGIN) &&
- (currentOperChan <= SIR_11B_CHANNEL_END)))
- {
- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
- "%s: BTC disabled aggregation - dont start "
- "TX ADDBA req",__func__);
- }
- else if(!WDA_GET_BA_TXFLAG(pWDA, curSta, tid)
- && (WLANTL_STA_AUTHENTICATED == tlSTAState)
- && WDA_AllowAddBA(pMac, curSta, tid)
- && (((eSYSTEM_STA_IN_IBSS_ROLE ==
- pWDA->wdaGlobalSystemRole) && txPktCount )
- || (txPktCount >= WDA_LAST_POLLED_THRESHOLD(pWDA,
- curSta, tid))))
+ if(!WDA_GET_BA_TXFLAG(pWDA, curSta, tid) &&
+ WDA_AllowAddBA(pMac, curSta, tid) &&
+ (((eSYSTEM_STA_IN_IBSS_ROLE == pWDA->wdaGlobalSystemRole)
+ && txPktCount) ||
+ (txPktCount >= WDA_LAST_POLLED_THRESHOLD(pWDA, curSta, tid)) ||
+ test_con))
{
/* get prepare for sending message to HAL */
//baCandidate[baCandidateCount].staIdx = curSta ;
baCandidate[baCandidateCount].ucTidBitmap |= 1 << tid ;
newBaCandidate = WDA_ENABLE_BA ;
+
+ /* Trigger only one BA request to check connection status */
+ if (test_con) {
+ WDA_StoreTestBAInfo(pMac, true, curSta, tid);
+ found = true;
+ break;
+ }
}
pWDA->wdaStaInfo[curSta].framesTxed[tid] = txPktCount ;
}
@@ -17805,6 +18138,14 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA)
}
else
{
+ if (test_con)
+ {
+ WDA_StoreTestBAInfo(pMac, false, pWDA->wdaMaxSta, STACFG_MAX_TC);
+ VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+ "%s: ADDBA to test connection status no valid Tid found",
+ __func__);
+ }
+
VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_LOW,
"There is no TID for initiating BA");
}
@@ -17824,6 +18165,7 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA)
}
return ;
}
+
/*
* WDA common routine to create timer used by WDA.
*/
@@ -17907,6 +18249,7 @@ static VOS_STATUS wdaCreateTimers(tWDA_CbContext *pWDA)
}
return VOS_STATUS_SUCCESS ;
}
+
/*
* WDA common routine to destroy timer used by WDA.
*/
diff --git a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda_ds.c b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda_ds.c
index 2e303fb400d..b4a9bbba7e3 100644
--- a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda_ds.c
+++ b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda_ds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -436,6 +436,7 @@ WDA_DS_BuildTxPacketInfo
v_U32_t txFlag,
v_U32_t timeStamp,
v_U8_t ucIsEapol,
+ v_U8_t ucIsArp,
v_U8_t ucUP,
v_U32_t ucTxBdToken
)
@@ -497,6 +498,7 @@ WDA_DS_BuildTxPacketInfo
pTxMetaInfo->ac = ucUP;
pTxMetaInfo->fUP = uTid;
pTxMetaInfo->isEapol = ucIsEapol;
+ pTxMetaInfo->isArp = ucIsArp;
pTxMetaInfo->fdisableFrmXlt = ucDisableFrmXtl;
pTxMetaInfo->frmType = ( ( typeSubtype & 0x30 ) >> 4 );
pTxMetaInfo->typeSubtype = typeSubtype;
diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h
index 6f0864d8af3..f76970efd8d 100644
--- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -8449,6 +8449,9 @@ typedef void (*WDI_WifiConfigSetRspCb) (WDI_WifconfigSetRsp *wdiRsp, void *pUse
typedef void (*WDI_AntennaDivSelRspCb)(WDI_Status status,
void *resp, void *pUserData);
+typedef void (*wdi_nud_set_arp_rsp_cb)(void *event_data,void *user_data);
+typedef void (*wdi_nud_get_arp_rsp_cb)(void *event_data,void *user_data);
+
/*========================================================================
* Function Declarations and Documentation
==========================================================================*/
@@ -12237,4 +12240,54 @@ WDI_SetAllowedActionFramesInd(
);
void WDI_SetMgmtPktViaWQ5(wpt_boolean sendMgmtPktViaWQ5);
+
+/* ARP DEBUG STATS */
+typedef struct
+{
+ wpt_uint8 flag;
+ wpt_uint8 pkt_type;
+ wpt_uint32 ip_addr;
+} WDI_SetARPStatsParamsInfoType;
+
+typedef struct
+{
+ wpt_uint32 status;
+} WDI_SetARPStatsRspParamsType;
+
+typedef void (*WDI_SetARPStatsRspCb)(WDI_SetARPStatsRspParamsType* StatsRsp,
+ void* pUserData);
+
+WDI_Status
+WDI_SetARPStatsReq
+(
+ WDI_SetARPStatsParamsInfoType *pwdiSetStatsReqParams,
+ WDI_SetARPStatsRspCb wdiSetARPStatsRspCb,
+ void* pUserData
+);
+
+/* ARP DEBUG STATS */
+typedef struct
+{
+ wpt_uint8 pkt_type;
+} WDI_GetARPStatsParamsInfoType;
+
+typedef struct
+{
+ wpt_uint32 status;
+ wpt_uint16 dad;
+ wpt_uint16 tx_fw_cnt;
+ wpt_uint16 rx_fw_cnt;
+ wpt_uint16 tx_ack_cnt;
+} WDI_GetARPStatsRspParamsType;
+
+typedef void (*WDI_GetARPStatsRspCb)(WDI_GetARPStatsRspParamsType* StatsRsp,
+ void* pUserData);
+
+WDI_Status
+WDI_GetARPStatsReq
+(
+ WDI_GetARPStatsParamsInfoType *pwdiGetStatsReqParams,
+ WDI_GetARPStatsRspCb wdiGetARPStatsRspCb,
+ void* pUserData
+);
#endif /* #ifndef WLAN_QCT_WDI_H */
diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h
index e42c1833a95..c828c4b2ea5 100644
--- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h
+++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1113,10 +1113,13 @@ typedef struct
This is filled by Host in Virgo 1.0 but it gets filled by ADU in
Virgo2.0/Libra. Queue ID */
wpt_uint32 queueId:5;
-
- wpt_uint32 reserved5:7;
+
+ wpt_uint32 isArp:1;
+
+ wpt_uint32 reserved5:6;
#else
- wpt_uint32 reserved5:7;
+ wpt_uint32 reserved5:6;
+ wpt_uint32 isArp:1;
wpt_uint32 queueId:5;
wpt_uint32 bdRate:2;
wpt_uint32 ap:2;
diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h
index 465946ebae8..85446f1b6dd 100644
--- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h
+++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -435,6 +435,7 @@ WDI_FillTxBd
wpt_uint8 ucProtMgmtFrame,
wpt_uint32 uTimeStamp,
wpt_uint8 isEapol,
+ wpt_uint8 isArp,
wpt_uint8* staIndex,
wpt_uint32 txBdToken
);
diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index 7debb41ad07..4b74e41fbe3 100644
--- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -493,6 +493,9 @@ typedef enum
WDI_PER_ROAM_SCAN_OFFLOAD_REQ = 116,
WDI_PER_ROAM_SCAN_TRIGGER_REQ = 117,
#endif
+/* ARP DEBUG STATS */
+ WDI_FW_ARP_STATS_REQ = 118,
+ WDI_FW_GET_ARP_STATS_REQ = 119,
WDI_MAX_REQ,
@@ -870,6 +873,8 @@ typedef enum
WDI_PER_ROAM_SCAN_OFFLOAD_RSP = 116,
WDI_PER_ROAM_SCAN_TRIGGER_RSP = 117,
#endif
+ WDI_FW_ARP_STATS_RSP = 118,
+ WDI_FW_GET_ARP_STATS_RSP = 119,
/*-------------------------------------------------------------------------
Indications
@@ -6676,5 +6681,33 @@ WDI_ProcessSetAllowedActionFramesInd
WDI_ControlBlockType* pWDICtx,
WDI_EventInfoType* pEventData
);
+
+WDI_Status
+WDI_ProcessSetArpStatsReq
+(
+ WDI_ControlBlockType* pWDICtx,
+ WDI_EventInfoType* pEventData
+);
+
+WDI_Status
+WDI_ProcessSetArpStatsResp
+(
+ WDI_ControlBlockType* pWDICtx,
+ WDI_EventInfoType* pEventData
+);
+
+WDI_Status
+WDI_ProcessGetArpStatsReq
+(
+ WDI_ControlBlockType* pWDICtx,
+ WDI_EventInfoType* pEventData
+);
+
+WDI_Status
+WDI_ProcessGetArpStatsResp
+(
+ WDI_ControlBlockType* pWDICtx,
+ WDI_EventInfoType* pEventData
+);
#endif /*WLAN_QCT_WDI_I_H*/
diff --git a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c
index 62acabfa049..b4dac6967b8 100644
--- a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -220,6 +220,11 @@ static placeHolderInCapBitmap supportEnabledFeatures[] =
,WIFI_CONFIG //61
,ANTENNA_DIVERSITY_SELECTION //62
,PER_BASED_ROAMING //63
+ ,FEATURE_NOT_SUPPORTED //64
+ ,FEATURE_NOT_SUPPORTED //65
+ ,FEATURE_NOT_SUPPORTED //66
+ ,FEATURE_NOT_SUPPORTED //67
+ ,NUD_DEBUG //68
};
/*--------------------------------------------------------------------------
@@ -516,6 +521,10 @@ WDI_ReqProcFuncType pfnReqProcTbl[WDI_MAX_UMAC_IND] =
NULL,
NULL,
#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */
+
+ WDI_ProcessSetArpStatsReq, /* WDI_FW_ARP_STATS_REQ */
+ WDI_ProcessGetArpStatsReq, /* WDI_FW_GET_ARP_STATS_REQ */
+
/*-------------------------------------------------------------------------
Indications
-------------------------------------------------------------------------*/
@@ -837,6 +846,9 @@ WDI_RspProcFuncType pfnRspProcTbl[WDI_MAX_RESP] =
NULL,
NULL,
#endif
+/* ARP Debug Stats*/
+ WDI_ProcessSetArpStatsResp, /* WDI_FW_ARP_STATS_RSP */
+ WDI_ProcessGetArpStatsResp, /* WDI_FW_GET_ARP_STATS_RSP */
/*---------------------------------------------------------------------
Indications
---------------------------------------------------------------------*/
@@ -1297,6 +1309,11 @@ static char *WDI_getReqMsgString(wpt_uint16 wdiReqMsgId)
CASE_RETURN_STRING( WDI_ANTENNA_DIVERSITY_SELECTION_REQ );
CASE_RETURN_STRING( WDI_MODIFY_ROAM_PARAMS_IND );
CASE_RETURN_STRING( WDI_SET_ALLOWED_ACTION_FRAMES_IND );
+ CASE_RETURN_STRING( WDI_FW_ARP_STATS_REQ );
+ CASE_RETURN_STRING( WDI_FW_GET_ARP_STATS_REQ );
+#ifdef WLAN_FEATURE_APFIND
+ CASE_RETURN_STRING( WDI_SET_AP_FIND_IND );
+#endif
default:
return "Unknown WDI MessageId";
}
@@ -1305,6 +1322,84 @@ static char *WDI_getReqMsgString(wpt_uint16 wdiReqMsgId)
/**
+ * WDI_ProcessSetArpStatsResp() - WDI api to process set arp stats response
+ * @wdi_ctx: wdi context
+ * @event_data: event data
+ *
+ * Return: WDI_Status
+ */
+WDI_Status
+WDI_ProcessSetArpStatsResp
+(
+ WDI_ControlBlockType *wdi_ctx,
+ WDI_EventInfoType *event_data
+)
+{
+ wdi_nud_set_arp_rsp_cb nud_set_arp_rsp_callback;
+
+ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+ "%s: Enter ", __func__);
+ /*-------------------------------------------------------------------
+ Sanity check
+ -----------------------------------------------------------------*/
+ if ((NULL == wdi_ctx) || (NULL == event_data) ||
+ (NULL == event_data->pEventData))
+ {
+ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+ "%s: Invalid parameters", __func__);
+ WDI_ASSERT(0);
+ return WDI_STATUS_E_FAILURE;
+ }
+
+ nud_set_arp_rsp_callback =
+ (wdi_nud_set_arp_rsp_cb)wdi_ctx->pfncRspCB;
+
+ nud_set_arp_rsp_callback((void *) event_data->pEventData,
+ wdi_ctx->pRspCBUserData);
+
+ return WDI_STATUS_SUCCESS;
+}
+
+/**
+ * WDI_ProcessGetArpStatsResp() - WDI api to process get arp stats response
+ * @wdi_ctx: wdi context
+ * @event_data: event data
+ *
+ * Return: WDI_Status
+ */
+WDI_Status
+WDI_ProcessGetArpStatsResp
+(
+ WDI_ControlBlockType *wdi_ctx,
+ WDI_EventInfoType *event_data
+)
+{
+ wdi_nud_get_arp_rsp_cb nud_get_arp_rsp_callback;
+
+ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+ "%s: Enter ", __func__);
+ /*-------------------------------------------------------------------
+ Sanity check
+ -----------------------------------------------------------------*/
+ if ((NULL == wdi_ctx) || (NULL == event_data) ||
+ (NULL == event_data->pEventData))
+ {
+ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+ "%s: Invalid parameters", __func__);
+ WDI_ASSERT(0);
+ return WDI_STATUS_E_FAILURE;
+ }
+
+ nud_get_arp_rsp_callback =
+ (wdi_nud_get_arp_rsp_cb)wdi_ctx->pfncRspCB;
+
+ nud_get_arp_rsp_callback((void *) event_data->pEventData,
+ wdi_ctx->pRspCBUserData);
+
+ return WDI_STATUS_SUCCESS;
+}
+
+/**
@brief WDI_getRespMsgString prints the WDI resonse message in string.
@param wdiRespMsgId: WDI Message response Id
@@ -1641,6 +1736,11 @@ void WDI_TraceHostFWCapabilities(tANI_U32 *capabilityBitmap)
"%s", "PER_BASED_ROAMING");
pCapStr += strlen("PER_BASED_ROAMING");
break;
+ case NUD_DEBUG:
+ snprintf(pCapStr, sizeof("NUD_DEBUG"),
+ "%s", "NUD_DEBUG");
+ pCapStr += strlen("NUD_DEEBUG");
+ break;
}
*pCapStr++ = ',';
*pCapStr++ = ' ';
@@ -24750,6 +24850,10 @@ WDI_2_HAL_REQ_TYPE
case WDI_PER_ROAM_SCAN_TRIGGER_REQ:
return WLAN_HAL_PER_ROAM_SCAN_TRIGGER_REQ;
#endif
+ case WDI_FW_ARP_STATS_REQ:
+ return WLAN_HAL_FW_SET_CLEAR_ARP_STATS_REQ;
+ case WDI_FW_GET_ARP_STATS_REQ:
+ return WLAN_HAL_FW_GET_ARP_STATS_REQ;
default:
return WLAN_HAL_MSG_MAX;
}
@@ -25119,6 +25223,10 @@ case WLAN_HAL_DEL_STA_SELF_RSP:
case WLAN_HAL_PER_ROAM_SCAN_TRIGGER_RSP:
return WDI_PER_ROAM_SCAN_TRIGGER_RSP;
#endif
+ case WLAN_HAL_FW_SET_CLEAR_ARP_STATS_RSP:
+ return WDI_FW_ARP_STATS_RSP;
+ case WLAN_HAL_FW_GET_ARP_STATS_RSP:
+ return WDI_FW_GET_ARP_STATS_RSP;
default:
return eDRIVER_TYPE_MAX;
}
@@ -38195,3 +38303,211 @@ WDI_Status WDI_SetAllowedActionFramesInd(
return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
}
+
+/**
+ * WDI_ProcessSetArpStatsReq() - WDI api to process arp stats request
+ * @pWDICtx: wdi context
+ * @pEventData: event data
+ *
+ * Return: WDI_Status
+ */
+WDI_Status
+WDI_ProcessSetArpStatsReq
+(
+ WDI_ControlBlockType* pWDICtx,
+ WDI_EventInfoType* pEventData
+)
+{
+ WDI_SetARPStatsParamsInfoType *pSetARPStatsReqParams;
+ WDI_SetARPStatsRspCb wdiSetARPStatsRspCb;
+ wpt_uint8* pSendBuffer;
+ wpt_uint16 usDataOffset;
+ wpt_uint16 usSendSize;
+ WDI_Status wdi_status;
+ tHalStatsArpReqMsg statsReqParams;
+
+ VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+ "%s: %d Enter",__func__, __LINE__);
+
+ if (( NULL == pEventData ) || ( NULL == pEventData->pEventData) ||
+ ( NULL == pWDICtx ) )
+ {
+ WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+ "%s: Invalid parameters", __func__);
+ WDI_ASSERT(0);
+ return WDI_STATUS_E_FAILURE;
+ }
+
+ pSetARPStatsReqParams =
+ (WDI_SetARPStatsParamsInfoType *)pEventData->pEventData;
+ wdiSetARPStatsRspCb = (WDI_SetARPStatsRspCb)pEventData->pCBfnc;
+
+ if ((WDI_STATUS_SUCCESS != WDI_GetMessageBuffer(pWDICtx, WDI_FW_ARP_STATS_REQ,
+ sizeof(statsReqParams.statsArpReqParams),
+ &pSendBuffer, &usDataOffset, &usSendSize))||
+ ( usSendSize < (usDataOffset + sizeof(statsReqParams.statsArpReqParams))))
+ {
+ WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+ "Unable to get send buffer in set bss key req %p %p %p",
+ pEventData, pSetARPStatsReqParams, wdiSetARPStatsRspCb);
+ WDI_ASSERT(0);
+ return WDI_STATUS_E_FAILURE;
+ }
+
+ statsReqParams.statsArpReqParams.set_clr = pSetARPStatsReqParams->flag;
+ statsReqParams.statsArpReqParams.pkt_type =
+ pSetARPStatsReqParams->pkt_type;
+ statsReqParams.statsArpReqParams.ip_addr = pSetARPStatsReqParams->ip_addr;
+
+ wpalMemoryCopy( pSendBuffer+usDataOffset,
+ &statsReqParams.statsArpReqParams,
+ sizeof(statsReqParams.statsArpReqParams));
+
+ wdi_status = WDI_SendMsg(pWDICtx, pSendBuffer, usSendSize,
+ wdiSetARPStatsRspCb, pEventData->pUserData,
+ WDI_FW_ARP_STATS_RSP);
+
+ VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+ "%s: %d Exit",__func__, __LINE__);
+ return wdi_status;
+}
+
+/**
+ * WDI_SetARPStatsReq() - WDI api to process set arp stats request
+ * @pwdiSetStatsReqParams: pointer to set stats params
+ * @wdiSetStatsRspCb: pointer to set response callback
+ * @pUserData: user data
+ *
+ * Return: WDI_Status
+ */
+WDI_Status
+WDI_SetARPStatsReq
+(
+ WDI_SetARPStatsParamsInfoType* pwdiSetStatsReqParams,
+ WDI_SetARPStatsRspCb wdiSetStatsRspCb,
+ void* pUserData
+)
+{
+ WDI_EventInfoType wdiEventData;
+
+ if (eWLAN_PAL_FALSE == gWDIInitialized )
+ {
+ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+ "WDI API call before module is initialized - Fail request");
+
+ return WDI_STATUS_E_NOT_ALLOWED;
+ }
+
+ wdiEventData.wdiRequest = WDI_FW_ARP_STATS_REQ;
+ wdiEventData.pEventData = pwdiSetStatsReqParams;
+ wdiEventData.uEventDataSize = sizeof(*pwdiSetStatsReqParams);
+ wdiEventData.pCBfnc = wdiSetStatsRspCb;
+ wdiEventData.pUserData = pUserData;
+
+ return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+
+}/*WDI_GetARPStatsReq*/
+
+/**
+ * WDI_ProcessGetArpStatsReq() - WDI api to process get arp stats request
+ * @pWDICtx: wdi context
+ * @pEventData: event data
+ *
+ * Return: WDI_Status
+ */
+WDI_Status
+WDI_ProcessGetArpStatsReq
+(
+ WDI_ControlBlockType* pWDICtx,
+ WDI_EventInfoType* pEventData
+)
+{
+ WDI_GetARPStatsParamsInfoType *pGetARPStatsReqParams;
+ WDI_GetARPStatsRspCb wdiGetARPStatsRspCb;
+ wpt_uint8* pSendBuffer;
+ wpt_uint16 usDataOffset;
+ wpt_uint16 usSendSize;
+ WDI_Status wdi_status;
+ tHalStatsGetArpReqMsg statsReqParams;
+
+ VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+ "%s: %d Enter",__func__, __LINE__);
+
+ if (( NULL == pEventData ) || ( NULL == pEventData->pEventData) ||
+ ( NULL == pWDICtx ) )
+ {
+ WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+ "%s: Invalid parameters", __func__);
+ WDI_ASSERT(0);
+ return WDI_STATUS_E_FAILURE;
+ }
+
+ pGetARPStatsReqParams =
+ (WDI_GetARPStatsParamsInfoType *)pEventData->pEventData;
+ wdiGetARPStatsRspCb = (WDI_GetARPStatsRspCb)pEventData->pCBfnc;
+
+ if ((WDI_STATUS_SUCCESS != WDI_GetMessageBuffer(pWDICtx,
+ WDI_FW_GET_ARP_STATS_REQ,
+ sizeof(statsReqParams.statsGetArpReqParams),
+ &pSendBuffer, &usDataOffset, &usSendSize))||
+ ( usSendSize < (usDataOffset +
+ sizeof(statsReqParams.statsGetArpReqParams))))
+ {
+ WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+ "Unable to get send buffer in set bss key req %p %p %p",
+ pEventData, pGetARPStatsReqParams, wdiGetARPStatsRspCb);
+ WDI_ASSERT(0);
+ return WDI_STATUS_E_FAILURE;
+ }
+
+ statsReqParams.statsGetArpReqParams.pkt_type =
+ pGetARPStatsReqParams->pkt_type;
+
+ wpalMemoryCopy( pSendBuffer+usDataOffset,
+ &statsReqParams.statsGetArpReqParams,
+ sizeof(statsReqParams.statsGetArpReqParams));
+
+ wdi_status = WDI_SendMsg(pWDICtx, pSendBuffer, usSendSize,
+ wdiGetARPStatsRspCb, pEventData->pUserData,
+ WDI_FW_GET_ARP_STATS_RSP);
+
+ VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+ "%s: %d Exit",__func__, __LINE__);
+ return wdi_status;
+}
+
+/**
+ * WDI_GetARPStatsReq() - WDI api to process get arp stats request
+ * @pwdiGetStatsReqParams: pointer to get stats params
+ * @wdiGetStatsRspCb: pointer to get response callback
+ * @pUserData: user data
+ *
+ * Return: WDI_Status
+ */
+WDI_Status
+WDI_GetARPStatsReq
+(
+ WDI_GetARPStatsParamsInfoType* pwdiGetStatsReqParams,
+ WDI_GetARPStatsRspCb wdiGetStatsRspCb,
+ void* pUserData
+)
+{
+ WDI_EventInfoType wdiEventData;
+
+ if (eWLAN_PAL_FALSE == gWDIInitialized )
+ {
+ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+ "WDI API call before module is initialized - Fail request");
+
+ return WDI_STATUS_E_NOT_ALLOWED;
+ }
+
+ wdiEventData.wdiRequest = WDI_FW_GET_ARP_STATS_REQ;
+ wdiEventData.pEventData = pwdiGetStatsReqParams;
+ wdiEventData.uEventDataSize = sizeof(*pwdiGetStatsReqParams);
+ wdiEventData.pCBfnc = wdiGetStatsRspCb;
+ wdiEventData.pUserData = pUserData;
+
+ return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+
+}/*WDI_GetARPStatsReq*/
diff --git a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c
index 48bf139ff16..25d627f2388 100644
--- a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c
+++ b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -386,6 +386,7 @@ WDI_FillTxBd
wpt_uint8 ucProtMgmtFrame,
wpt_uint32 uTimeStamp,
wpt_uint8 isEapol,
+ wpt_uint8 isArp,
wpt_uint8* staIndex,
wpt_uint32 txBdToken
)
@@ -409,6 +410,9 @@ WDI_FillTxBd
Get type and subtype of the frame first
------------------------------------------------------------------------*/
pBd->txBdToken = txBdToken;
+
+ pBd->isArp = isArp;
+
ucType = (ucTypeSubtype & WDI_FRAME_TYPE_MASK) >> WDI_FRAME_TYPE_OFFSET;
ucSubType = (ucTypeSubtype & WDI_FRAME_SUBTYPE_MASK);
diff --git a/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h b/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
index 483ad65980b..2acb5cec4cd 100644
--- a/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
+++ b/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -53,11 +53,12 @@ typedef struct
wpt_uint32 txFlags;
wpt_uint8 ac;
wpt_uint8 isEapol:1; //0 - not eapol 1 - eapol
- wpt_uint8 isWai:1; //WAPI 0 - not WAI 1 WAI
+ wpt_uint8 isWai:1; //WAPI 0 - not WAI 1 WAI
+ wpt_uint8 isArp:1; //0 - not ARP 1 - ARP
wpt_uint8 fdisableFrmXlt:1; //0 - Let ADU do FT. 1 - bypass ADU FT
wpt_uint8 qosEnabled:1; //0 - non-Qos 1 - Qos
wpt_uint8 fenableWDS:1; //0 - not WDS 1 WDS
- wpt_uint8 reserved1:3;
+ wpt_uint8 reserved1:2;
wpt_uint8 typeSubtype;
wpt_uint8 fUP;
wpt_uint8 fSTAMACAddress[6];
diff --git a/drivers/staging/prima/CORE/WDI/DP/src/wlan_qct_wdi_ds.c b/drivers/staging/prima/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
index 902c0de1f59..ac4512a83cd 100644
--- a/drivers/staging/prima/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
+++ b/drivers/staging/prima/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -129,6 +129,7 @@ WDI_Status WDI_DS_TxPacket(void *pContext,
wpt_uint8 ucUP;
wpt_uint8 ucTypeSubtype;
wpt_uint8 isEapol;
+ wpt_uint8 isArp;
wpt_uint8 alignment;
wpt_uint32 ucTxFlag;
wpt_uint8 ucProtMgmtFrame;
@@ -160,6 +161,7 @@ WDI_Status WDI_DS_TxPacket(void *pContext,
ucTypeSubtype = pTxMetadata->typeSubtype;
ucUP = pTxMetadata->fUP;
isEapol = pTxMetadata->isEapol;
+ isArp = pTxMetadata->isArp;
ucTxFlag = pTxMetadata->txFlags;
ucProtMgmtFrame = pTxMetadata->fProtMgmtFrame;
pSTAMACAddress = &(pTxMetadata->fSTAMACAddress[0]);
@@ -211,9 +213,16 @@ WDI_Status WDI_DS_TxPacket(void *pContext,
WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
"Packet Length is %d\n", pTxMetadata->fPktlen);
}
+
+ if (pTxMetadata->isArp)
+ {
+ WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+ "%s :Transmitting ARP packet",__func__);
+ }
+
wdiStatus = WDI_FillTxBd(pContext, ucTypeSubtype, pSTAMACAddress, pAddr2MACAddress,
- &ucUP, 1, pvBDHeader, ucTxFlag /* No ACK */, ucProtMgmtFrame, 0, isEapol, &staId,
- pTxMetadata->txBdToken);
+ &ucUP, 1, pvBDHeader, ucTxFlag /* No ACK */, ucProtMgmtFrame, 0, isEapol, isArp,
+ &staId, pTxMetadata->txBdToken);
if(WDI_STATUS_SUCCESS != wdiStatus)
{
diff --git a/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
index 018b8be4f5e..a43656a1b41 100644
--- a/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
+++ b/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1259,6 +1259,13 @@ wpt_status WDTS_TxPacket(void *pContext, wpt_packet *pFrame)
#else
((pTxMetadata->isEapol) ? WDTS_CHANNEL_TX_HIGH_PRI : WDTS_CHANNEL_TX_LOW_PRI) : WDTS_CHANNEL_TX_HIGH_PRI;
#endif
+
+ if (pTxMetadata->isArp)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :Transmitting ARP packet", __func__);
+ }
+
// Send packet to Transport Driver.
status = gTransportDriver.xmit(pDTDriverContext, pFrame, channel);
if ((WLAN_LOG_LEVEL_ACTIVE ==
diff --git a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h
index c1a8d181233..aeacf6f58a0 100644
--- a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h
+++ b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015,2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -389,4 +389,6 @@ int wpalIsDxeSSREnable(void);
wpt_uint8 wpalIsFwLoggingEnabled(void);
wpt_uint8 wpalIsFwLoggingSupported(void);
wpt_uint8 wpalIsFwEvLoggingEnabled(void);
+bool wpalIsArpPkt(void *pPacket);
+void wpalUpdateTXArpFWdeliveredStats(void);
#endif // __WLAN_QCT_PAL_API_H
diff --git a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c
index 9e0f047fea4..ee70505da23 100644
--- a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c
+++ b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012,2014-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012,2014-2015,2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -542,3 +542,20 @@ int wpalIsDxeSSREnable(void)
return vos_get_dxeSSREnable();
}
+bool wpalIsArpPkt(void *pPacket)
+{
+ vos_pkt_t *pkt = (vos_pkt_t*)pPacket;
+
+ if (vos_is_arp_pkt(pkt->pSkb, true))
+ {
+ if (vos_check_arp_req_target_ip(pkt->pSkb, true))
+ return true;
+ }
+
+ return false;
+}
+
+void wpalUpdateTXArpFWdeliveredStats(void)
+{
+ vos_update_arp_fw_tx_delivered();
+}
diff --git a/drivers/staging/prima/riva/inc/wlan_hal_msg.h b/drivers/staging/prima/riva/inc/wlan_hal_msg.h
index 581862c9307..a74f2e4e746 100644
--- a/drivers/staging/prima/riva/inc/wlan_hal_msg.h
+++ b/drivers/staging/prima/riva/inc/wlan_hal_msg.h
@@ -605,6 +605,11 @@ typedef enum
WLAN_HAL_PER_ROAM_SCAN_TRIGGER_REQ = 336,
WLAN_HAL_PER_ROAM_SCAN_TRIGGER_RSP = 337,
+ WLAN_HAL_FW_SET_CLEAR_ARP_STATS_REQ = 354,
+ WLAN_HAL_FW_SET_CLEAR_ARP_STATS_RSP = 355,
+ WLAN_HAL_FW_GET_ARP_STATS_REQ = 356,
+ WLAN_HAL_FW_GET_ARP_STATS_RSP = 357,
+
WLAN_HAL_MSG_MAX = WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE
}tHalHostMsgType;
@@ -6876,6 +6881,7 @@ typedef enum {
WIFI_CONFIG = 61,
ANTENNA_DIVERSITY_SELECTION = 62,
PER_BASED_ROAMING = 63,
+ NUD_DEBUG = 68,
MAX_FEATURE_SUPPORTED = 128,
} placeHolderInCapBitmap;
@@ -9302,6 +9308,69 @@ typedef PACKED_PRE struct PACKED_POST
tHalModifyRoamParamsIndParams modifyRoamParamsReqParams;
} tHalModifyRoamParamsInd, *tpHalModifyRoamParamsInd;
+/*---------------------------------------------------------------------------
+ * WLAN_HAL_FW_SET_CLEAR_ARP_STATS_REQ
+ *--------------------------------------------------------------------------*/
+typedef PACKED_PRE struct PACKED_POST
+{
+ tANI_U8 set_clr; /*1 set and 0 reset*/
+ tANI_U8 pkt_type; /* Default 1: ARP */
+ tANI_U32 ip_addr; /*GW ipv4 address */
+} tHalStatsArpReqParams, *tpHalStatsArpReqParams;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+ tHalMsgHeader header;
+ tHalStatsArpReqParams statsArpReqParams;
+} tHalStatsArpReqMsg, *tpHalStatsArpReqMsg;
+
+/*---------------------------------------------------------------------------
+ * WLAN_HAL_FW_SET_CLEAR_ARP_STATS_RSP
+ *--------------------------------------------------------------------------*/
+typedef PACKED_PRE struct PACKED_POST
+{
+ tANI_U32 status; //success or failure
+} tHalStatsArpRspParams, *tpHalStatsArpRspParams;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+ tHalMsgHeader header;
+ tHalStatsArpRspParams statsArpRspParams;
+} tHalStatsArpRspMsg, *tpHalStatsArpRspMsg;
+
+/*---------------------------------------------------------------------------
+ * WLAN_HAL_FW_GET_ARP_STATS_REQ
+ *--------------------------------------------------------------------------*/
+typedef PACKED_PRE struct PACKED_POST
+{
+ tANI_U8 pkt_type; /* Furture purpose */
+} tHalStatsGetArpReqParams, *tpHalStatsGetArpReqParams;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+ tHalMsgHeader header;
+ tHalStatsGetArpReqParams statsGetArpReqParams;
+} tHalStatsGetArpReqMsg, *tpHalStatsGetArpReqMsg;
+
+/*---------------------------------------------------------------------------
+ * WLAN_HAL_FW_GET_ARP_STATS_RSP
+ *--------------------------------------------------------------------------*/
+typedef PACKED_PRE struct PACKED_POST
+{
+ tANI_U32 status;
+ tANI_U16 dad;
+ tANI_U16 arpReqRcvdInFW;
+ tANI_U16 ackedArpReqCnt;
+ tANI_U16 arpRspCnt;
+ tANI_U8 data[1];
+} tdbugArpStatsgetRspParams, *tpdbugArpStatsgetRspParams;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+ tHalMsgHeader header;
+ tdbugArpStatsgetRspParams fwArpstatsRspParams;
+} tHalARPfwStatsRspMsg, *tpHalARPfwStatsRspMsg;
+
#if defined(__ANI_COMPILER_PRAGMA_PACK_STACK)
#pragma pack(pop)
#elif defined(__ANI_COMPILER_PRAGMA_PACK)
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index e5eb1b5a04e..2f261fba980 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -774,8 +774,6 @@ static int ab8500_usb_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ab);
- ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
-
/* all: Disable phy when called from set_host and set_peripheral */
INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 8443335c2ea..f7451fa2778 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -314,8 +314,6 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
goto err_irq;
}
- ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier);
-
INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work);
gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index bd601c537c8..f2a77e236d0 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -157,8 +157,6 @@ static int mxs_phy_probe(struct platform_device *pdev)
mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect;
mxs_phy->phy.type = USB_PHY_TYPE_USB2;
- ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier);
-
mxs_phy->clk = clk;
platform_set_drvdata(pdev, &mxs_phy->phy);
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index a9984c700d2..a3684f7908e 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -329,6 +329,8 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
return -EINVAL;
}
+ ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
+
spin_lock_irqsave(&phy_lock, flags);
list_for_each_entry(phy, &phy_list, head) {
@@ -367,6 +369,8 @@ int usb_add_phy_dev(struct usb_phy *x)
return -EINVAL;
}
+ ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
+
spin_lock_irqsave(&phy_lock, flags);
list_for_each_entry(phy_bind, &phy_bind_list, list)
if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev))))
diff --git a/include/linux/compiler-gcc6.h b/include/linux/compiler-gcc6.h
new file mode 100644
index 00000000000..622117be664
--- /dev/null
+++ b/include/linux/compiler-gcc6.h
@@ -0,0 +1,65 @@
+#ifndef __LINUX_COMPILER_H
+#error "Please don't include <linux/compiler-gcc6.h> directly, include <linux/compiler.h> instead."
+#endif
+
+#define __used __attribute__((__used__))
+#define __must_check __attribute__((warn_unused_result))
+#define __compiler_offsetof(a, b) __builtin_offsetof(a, b)
+
+/* Mark functions as cold. gcc will assume any path leading to a call
+ to them will be unlikely. This means a lot of manual unlikely()s
+ are unnecessary now for any paths leading to the usual suspects
+ like BUG(), printk(), panic() etc. [but let's keep them for now for
+ older compilers]
+
+ Early snapshots of gcc 4.3 don't support this and we can't detect this
+ in the preprocessor, but we can live with this because they're unreleased.
+ Maketime probing would be overkill here.
+
+ gcc also has a __attribute__((__hot__)) to move hot functions into
+ a special section, but I don't see any sense in this right now in
+ the kernel context */
+#define __cold __attribute__((__cold__))
+
+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+
+#ifndef __CHECKER__
+# define __compiletime_warning(message) __attribute__((warning(message)))
+# define __compiletime_error(message) __attribute__((error(message)))
+#endif /* __CHECKER__ */
+
+/*
+ * Mark a position in code as unreachable. This can be used to
+ * suppress control flow warnings after asm blocks that transfer
+ * control elsewhere.
+ *
+ * Early snapshots of gcc 4.5 don't support this and we can't detect
+ * this in the preprocessor, but we can live with this because they're
+ * unreleased. Really, we need to have autoconf for the kernel.
+ */
+#define unreachable() __builtin_unreachable()
+
+/* Mark a function definition as prohibited from being cloned. */
+#define __noclone __attribute__((__noclone__))
+
+/*
+ * Tell the optimizer that something else uses this function or variable.
+ */
+#define __visible __attribute__((externally_visible))
+
+/*
+ * GCC 'asm goto' miscompiles certain code sequences:
+ *
+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
+ *
+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
+ *
+ * (asm goto is automatically volatile - the naming reflects this.)
+ */
+#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
+
+#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
+#define __HAVE_BUILTIN_BSWAP32__
+#define __HAVE_BUILTIN_BSWAP64__
+#define __HAVE_BUILTIN_BSWAP16__
+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
diff --git a/include/linux/device.h b/include/linux/device.h
index 074d4503731..5ba4a30611e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -72,6 +72,10 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
* the specific driver's probe to initial the matched device.
* @remove: Called when a device removed from this bus.
* @shutdown: Called at shut-down time to quiesce the device.
+ *
+ * @online: Called to put the device back online (after offlining it).
+ * @offline: Called to put the device offline for hot-removal. May fail.
+ *
* @suspend: Called when a device on this bus wants to go to sleep mode.
* @resume: Called to bring a device on this bus out of sleep mode.
* @pm: Power management operations of this bus, callback the specific
@@ -105,6 +109,9 @@ struct bus_type {
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
+ int (*online)(struct device *dev);
+ int (*offline)(struct device *dev);
+
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
@@ -672,6 +679,8 @@ struct acpi_dev_node {
* @release: Callback to free the device after all references have
* gone away. This should be set by the allocator of the
* device (i.e. the bus driver that discovered the device).
+ * @offline_disabled: If set, the device is permanently online.
+ * @offline: Set after successful invocation of bus type's .offline().
*
* At the lowest level, every device in a Linux system is represented by an
* instance of struct device. The device structure contains the information
@@ -744,6 +753,9 @@ struct device {
void (*release)(struct device *dev);
struct iommu_group *iommu_group;
+
+ bool offline_disabled:1;
+ bool offline:1;
};
static inline struct device *kobj_to_dev(struct kobject *kobj)
@@ -880,6 +892,15 @@ extern const char *device_get_devnode(struct device *dev,
extern void *dev_get_drvdata(const struct device *dev);
extern int dev_set_drvdata(struct device *dev, void *data);
+static inline bool device_supports_offline(struct device *dev)
+{
+ return dev->bus && dev->bus->offline && dev->bus->online;
+}
+
+extern void lock_device_hotplug(void);
+extern void unlock_device_hotplug(void);
+extern int device_offline(struct device *dev);
+extern int device_online(struct device *dev);
/*
* Root device objects for grouping under /sys/devices
*/
diff --git a/init/Kconfig b/init/Kconfig
index 6573f2c654d..f67913aea4f 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1039,6 +1039,16 @@ config SCHED_HMP
in their instructions per-cycle capability or the maximum
frequency they can attain.
+config SCHED_CORE_CTL
+ bool "QTI Core Control"
+ depends on SMP
+ help
+ This options enables the core control functionality in
+ the scheduler. Core control automatically offline and
+ online cores based on cpu load and utilization.
+
+ If unsure, say N here.
+
config CHECKPOINT_RESTORE
bool "Checkpoint/restore support" if EXPERT
default n
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 1c7bde63c5e..53ccd2f5d41 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
obj-$(CONFIG_SCHEDSTATS) += stats.o
obj-$(CONFIG_SCHED_DEBUG) += debug.o
obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o
+obj-$(CONFIG_SCHED_CORE_CTL) += core_ctl.o
diff --git a/drivers/soc/qcom/core_ctl.c b/kernel/sched/core_ctl.c
index 0148630a7e0..a1134c86d27 100644
--- a/drivers/soc/qcom/core_ctl.c
+++ b/kernel/sched/core_ctl.c
@@ -1,45 +1,24 @@
-/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
*
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/init.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
-#include <linux/moduleparam.h>
#include <linux/cpumask.h>
#include <linux/cpufreq.h>
#include <linux/timer.h>
#include <linux/kthread.h>
-#include <linux/module.h>
#include <linux/sched.h>
-#include <soc/qcom/core_ctl.h>
+#include <linux/sched/rt.h>
#include <linux/mutex.h>
#include <trace/events/power.h>
@@ -81,6 +60,7 @@ struct cpu_data {
struct task_struct *hotplug_thread;
struct kobject kobj;
struct list_head pending_lru;
+ bool disabled;
};
static DEFINE_PER_CPU(struct cpu_data, cpu_state);
@@ -200,6 +180,7 @@ static ssize_t store_busy_up_thres(struct cpu_data *state,
static ssize_t show_busy_up_thres(struct cpu_data *state, char *buf)
{
int i, count = 0;
+
for (i = 0; i < state->num_cpus; i++)
count += snprintf(buf + count, PAGE_SIZE - count, "%u ",
state->busy_up_thres[i]);
@@ -231,6 +212,7 @@ static ssize_t store_busy_down_thres(struct cpu_data *state,
static ssize_t show_busy_down_thres(struct cpu_data *state, char *buf)
{
int i, count = 0;
+
for (i = 0; i < state->num_cpus; i++)
count += snprintf(buf + count, PAGE_SIZE - count, "%u ",
state->busy_down_thres[i]);
@@ -307,19 +289,22 @@ static ssize_t show_global_state(struct cpu_data *state, char *buf)
"\tIs busy: %u\n", c->is_busy);
if (c->cpu != c->first_cpu)
continue;
- count += snprintf(buf + count, PAGE_SIZE- count,
+ count += snprintf(buf + count, PAGE_SIZE - count,
"\tNr running: %u\n", c->nrrun);
count += snprintf(buf + count, PAGE_SIZE - count,
"\tAvail CPUs: %u\n", c->avail_cpus);
count += snprintf(buf + count, PAGE_SIZE - count,
"\tNeed CPUs: %u\n", c->need_cpus);
+ count += snprintf(buf + count, PAGE_SIZE - count,
+ "\tStatus: %s\n",
+ c->disabled ? "disabled" : "enabled");
}
return count;
}
static ssize_t store_not_preferred(struct cpu_data *state,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
struct cpu_data *c;
unsigned int i, first_cpu;
@@ -359,6 +344,33 @@ static ssize_t show_not_preferred(struct cpu_data *state, char *buf)
return count;
}
+static ssize_t store_disable(struct cpu_data *state,
+ const char *buf, size_t count)
+{
+ unsigned int val;
+
+ if (sscanf(buf, "%u\n", &val) != 1)
+ return -EINVAL;
+
+ val = !!val;
+
+ if (state->disabled == val)
+ return count;
+
+ state->disabled = val;
+
+ if (!state->disabled)
+ wake_up_hotplug_thread(state);
+
+
+ return count;
+}
+
+static ssize_t show_disable(struct cpu_data *state, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", state->disabled);
+}
+
struct core_ctl_attr {
struct attribute attr;
ssize_t (*show)(struct cpu_data *, char *);
@@ -385,6 +397,7 @@ core_ctl_attr_ro(need_cpus);
core_ctl_attr_ro(online_cpus);
core_ctl_attr_ro(global_state);
core_ctl_attr_rw(not_preferred);
+core_ctl_attr_rw(disable);
static struct attribute *default_attrs[] = {
&min_cpus.attr,
@@ -399,6 +412,7 @@ static struct attribute *default_attrs[] = {
&online_cpus.attr,
&global_state.attr,
&not_preferred.attr,
+ &disable.attr,
NULL
};
@@ -445,7 +459,6 @@ static struct kobj_type ktype_core_ctl = {
#define RQ_AVG_DEFAULT_MS 20
#define NR_RUNNING_TOLERANCE 5
static unsigned int rq_avg_period_ms = RQ_AVG_DEFAULT_MS;
-module_param(rq_avg_period_ms, uint, 0644);
static s64 rq_avg_timestamp_ms;
static struct timer_list rq_avg_timer;
@@ -460,7 +473,7 @@ static void update_running_avg(bool trigger_update)
spin_lock_irqsave(&state_lock, flags);
- now = core_ctl_get_time();
+ now = ktime_to_ms(ktime_get());
if (now - rq_avg_timestamp_ms < rq_avg_period_ms - RQ_AVG_TOLERANCE) {
spin_unlock_irqrestore(&state_lock, flags);
return;
@@ -570,7 +583,7 @@ static bool eval_need(struct cpu_data *f)
need_flag = apply_limits(f, need_cpus) != apply_limits(f, f->need_cpus);
last_need = f->need_cpus;
- now = core_ctl_get_time();
+ now = ktime_to_ms(ktime_get());
if (need_cpus == last_need) {
f->need_ts = now;
@@ -582,6 +595,7 @@ static bool eval_need(struct cpu_data *f)
ret = 1;
} else if (need_cpus < last_need) {
s64 elapsed = now - f->need_ts;
+
if (elapsed >= f->offline_delay_ms) {
ret = 1;
} else {
@@ -595,7 +609,8 @@ static bool eval_need(struct cpu_data *f)
f->need_cpus = need_cpus;
}
- trace_core_ctl_eval_need(f->cpu, last_need, need_cpus, ret && need_flag);
+ trace_core_ctl_eval_need(f->cpu, last_need, need_cpus,
+ ret && need_flag);
spin_unlock_irqrestore(&state_lock, flags);
return ret && need_flag;
@@ -642,6 +657,9 @@ static void wake_up_hotplug_thread(struct cpu_data *state)
struct cpu_data *pcpu;
bool no_wakeup = false;
+ if (unlikely(state->disabled))
+ return;
+
for_each_possible_cpu(cpu) {
pcpu = &per_cpu(cpu_state, cpu);
if (cpu != pcpu->first_cpu)
@@ -670,7 +688,7 @@ static void core_ctl_timer_func(unsigned long cpu)
struct cpu_data *state = &per_cpu(cpu_state, cpu);
unsigned long flags;
- if (eval_need(state)) {
+ if (eval_need(state) && !state->disabled) {
spin_lock_irqsave(&state->pending_lock, flags);
state->pending = true;
spin_unlock_irqrestore(&state->pending_lock, flags);
@@ -679,6 +697,40 @@ static void core_ctl_timer_func(unsigned long cpu)
}
+static int core_ctl_online_core(unsigned int cpu)
+{
+ int ret;
+ struct device *dev;
+
+ lock_device_hotplug();
+ dev = get_cpu_device(cpu);
+ if (!dev) {
+ pr_err("%s: failed to get cpu%d device\n", __func__, cpu);
+ ret = -ENODEV;
+ } else {
+ ret = device_online(dev);
+ }
+ unlock_device_hotplug();
+ return ret;
+}
+
+static int core_ctl_offline_core(unsigned int cpu)
+{
+ int ret;
+ struct device *dev;
+
+ lock_device_hotplug();
+ dev = get_cpu_device(cpu);
+ if (!dev) {
+ pr_err("%s: failed to get cpu%d device\n", __func__, cpu);
+ ret = -ENODEV;
+ } else {
+ ret = device_offline(dev);
+ }
+ unlock_device_hotplug();
+ return ret;
+}
+
static void update_lru(struct cpu_data *f)
{
struct cpu_data *c, *tmp;
@@ -719,7 +771,7 @@ static void __ref do_hotplug(struct cpu_data *f)
continue;
pr_debug("Trying to Offline CPU%u\n", c->cpu);
- if (cpu_down(c->cpu))
+ if (core_ctl_offline_core(c->cpu))
pr_debug("Unable to Offline CPU%u\n", c->cpu);
}
@@ -738,7 +790,7 @@ static void __ref do_hotplug(struct cpu_data *f)
break;
pr_debug("Trying to Offline CPU%u\n", c->cpu);
- if (cpu_down(c->cpu))
+ if (core_ctl_offline_core(c->cpu))
pr_debug("Unable to Offline CPU%u\n", c->cpu);
}
} else if (f->online_cpus < need) {
@@ -850,7 +902,8 @@ static int __ref cpu_callback(struct notifier_block *nfb,
* so that there's no race with hotplug thread bringing up more
* CPUs than necessary.
*/
- if (apply_limits(f, f->need_cpus) <= f->online_cpus) {
+ if (!f->disabled &&
+ apply_limits(f, f->need_cpus) <= f->online_cpus) {
pr_debug("Prevent CPU%d onlining\n", cpu);
ret = NOTIFY_BAD;
} else {
@@ -931,7 +984,6 @@ static struct notifier_block __refdata cpu_notifier = {
/* ============================ init code ============================== */
-#define HOTPLUG_THREAD_NICE_VAL -7
static int group_init(struct cpumask *mask)
{
struct device *dev;
@@ -939,11 +991,12 @@ static int group_init(struct cpumask *mask)
struct cpu_data *f = &per_cpu(cpu_state, first_cpu);
struct cpu_data *state;
unsigned int cpu;
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
if (likely(f->inited))
return 0;
- dev = core_ctl_find_cpu_device(first_cpu);
+ dev = get_cpu_device(first_cpu);
if (!dev)
return -ENODEV;
@@ -986,7 +1039,9 @@ static int group_init(struct cpumask *mask)
f->hotplug_thread = kthread_run(try_hotplug, (void *) f,
"core_ctl/%d", first_cpu);
- set_user_nice(f->hotplug_thread, HOTPLUG_THREAD_NICE_VAL);
+ if (IS_ERR(f->hotplug_thread))
+ return PTR_ERR(f->hotplug_thread);
+ sched_setscheduler_nocheck(f->hotplug_thread, SCHED_FIFO, &param);
for_each_cpu(cpu, mask) {
state = &per_cpu(cpu_state, cpu);
@@ -1044,43 +1099,17 @@ static int __init core_ctl_init(void)
init_timer_deferrable(&rq_avg_timer);
rq_avg_timer.function = rq_avg_timer_func;
- core_ctl_block_hotplug();
+ get_online_cpus();
for_each_online_cpu(cpu) {
- policy = core_ctl_get_policy(cpu);
+ policy = cpufreq_cpu_get(cpu);
if (policy) {
group_init(policy->related_cpus);
- core_ctl_put_policy(policy);
+ cpufreq_cpu_put(policy);
}
}
- core_ctl_unblock_hotplug();
+ put_online_cpus();
mod_timer(&rq_avg_timer, round_to_nw_start());
return 0;
}
-static void __exit core_ctl_exit(void)
-{
- int cpu;
- struct cpu_data *pcpu;
-
- unregister_cpu_notifier(&cpu_notifier);
- cpufreq_unregister_notifier(&cpufreq_pol_nb, CPUFREQ_POLICY_NOTIFIER);
- cpufreq_unregister_notifier(&cpufreq_gov_nb, CPUFREQ_GOVINFO_NOTIFIER);
- del_timer_sync(&rq_avg_timer);
-
- for_each_possible_cpu(cpu) {
- pcpu = &per_cpu(cpu_state, cpu);
- if (pcpu->inited && cpu == pcpu->first_cpu) {
- pcpu->inited = false;
- del_timer_sync(&pcpu->timer);
- kthread_stop(pcpu->hotplug_thread);
- kobject_put(&pcpu->kobj);
- }
- pcpu->inited = false;
- }
-}
-
-module_init(core_ctl_init);
-module_exit(core_ctl_exit);
-
-MODULE_DESCRIPTION("MSM Core Control Driver");
-MODULE_LICENSE("GPL v2");
+late_initcall(core_ctl_init);
diff --git a/sound/soc/codecs/msm8x16-wcd.h b/sound/soc/codecs/msm8x16-wcd.h
index 394bd8ec4f2..55c4f8353fc 100644
--- a/sound/soc/codecs/msm8x16-wcd.h
+++ b/sound/soc/codecs/msm8x16-wcd.h
@@ -36,6 +36,9 @@
#define MSM8X16_TOMBAK_LPASS_DIGCODEC_CBCR 0x0181C0B0
#define MSM8X16_TOMBAK_LPASS_DIGCODEC_AHB_CBCR 0x0181C0B4
+#define EXT_SPK_AMP_GPIO (902+121)
+#define EXT_SPK_AMP_HEADSET_GPIO (902+8)
+
#define MSM8X16_CODEC_NAME "msm8x16_wcd_codec"
#define MSM8X16_WCD_IS_DIGITAL_REG(reg) \
@@ -314,6 +317,8 @@ extern int msm8x16_wcd_hs_detect(struct snd_soc_codec *codec,
extern void msm8x16_wcd_hs_detect_exit(struct snd_soc_codec *codec);
+extern int msm8x16_wcd_restart_mbhc(struct snd_soc_codec *codec);
+
extern void msm8x16_wcd_spk_ext_pa_cb(
int (*codec_spk_ext_pa)(struct snd_soc_codec *codec,
int enable), struct snd_soc_codec *codec);
diff --git a/sound/soc/codecs/wcd-mbhc-v2.h b/sound/soc/codecs/wcd-mbhc-v2.h
index 500e474d2c9..e2cb79c0693 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.h
+++ b/sound/soc/codecs/wcd-mbhc-v2.h
@@ -508,4 +508,6 @@ static inline int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc,
}
#endif
void wcd_mbhc_deinit(struct wcd_mbhc *mbhc);
+extern void msm8x16_wcd_codec_set_headset_state(u32 state);
+extern int msm8x16_wcd_codec_get_headset_state(void);
#endif /* __WCD_MBHC_V2_H__ */