Add enable and disable Wi-Fi Power management through syfs.
nagaraj [Wed, 30 Nov 2016 22:54:18 +0000 (14:54 -0800)]
Bug 1828585

Change-Id: I713de1dddbec21d0e3c0105d9f2630a45cecd2ff
Signed-off-by: Nagaraj Annaiah <nannaiah@nvidia.com>
(cherry picked from commit 63fa1393ea127c753002cc7fce893590b7931b34)
Reviewed-on: http://git-master/r/1263671
Tested-by: David Dastous St Hilaire <ddastoussthi@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terry Wang <terwang@nvidia.com>
Reviewed-by: Ramaiyer Ramesh <ramaiyerr@nvidia.com>

drivers/net/wireless/bcmdhd/dhd_common.c
drivers/net/wireless/bcmdhd/dhd_custom_sysfs_tegra.c
drivers/net/wireless/bcmdhd/dhd_custom_sysfs_tegra_rf_test.c

index f6bae38..d146d5a 100644 (file)
@@ -361,6 +361,7 @@ dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, int
 extern atomic_t rf_test;
 extern atomic_t cur_power_mode;
 extern rf_test_params_t rf_test_params[NUM_RF_TEST_PARAMS];
+extern atomic_t pm_disable;
 #endif /* CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA */
 
 int
@@ -420,7 +421,7 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
        if (ioc->cmd == WLC_SET_PM && ioc->buf) {
                uint pm_mode = *(uint *)ioc->buf;
                if (ioc->set) {
-                       if (atomic_read(&rf_test)) {
+                       if (atomic_read(&rf_test) || atomic_read(&pm_disable)) {
                                atomic_set(&cur_power_mode, pm_mode);
                                DHD_ERROR(("%s: WLC_SET_PM: %d not allowed\n", __FUNCTION__, pm_mode));
                                return BCME_OK;
index f55b72a..8197312 100644 (file)
@@ -33,6 +33,19 @@ atomic_t tegra_downgrade_ac = ATOMIC_INIT(0);
 
 extern int bcmdhd_resume_trigger;
 
+extern atomic_t pm_disable;
+extern void tegra_sysfs_pm_enable(void);
+extern void tegra_sysfs_pm_disable(void);
+extern ssize_t
+tegra_sysfs_pm_state_store(struct device *dev,
+       struct device_attribute *attr,
+       const char *buf, size_t count);
+extern ssize_t
+tegra_sysfs_pm_state_show(struct device *dev,
+       struct device_attribute *attr,
+       char *buf);
+
+
 static DEVICE_ATTR(ping, S_IRUGO | S_IWUGO,
        tegra_sysfs_histogram_ping_show,
        tegra_sysfs_histogram_ping_store);
@@ -72,8 +85,14 @@ static DEVICE_ATTR(state, S_IRUGO | S_IWUGO,
        tegra_sysfs_rf_test_state_show,
        tegra_sysfs_rf_test_state_store);
 
+/* PM test attributes */
+static DEVICE_ATTR(pm, S_IRUGO | S_IWUGO,
+       tegra_sysfs_pm_state_show,
+       tegra_sysfs_pm_state_store);
+
 static struct attribute *tegra_sysfs_entries_rf_test[] = {
        &dev_attr_state.attr,
+       &dev_attr_pm.attr,
        NULL,
 };
 
@@ -212,6 +231,10 @@ tegra_sysfs_on(void)
        tegra_sysfs_histogram_scan_work_start();
        tegra_sysfs_histogram_stat_work_start();
        tegra_sysfs_histogram_tcpdump_work_start();
+       if (atomic_read(&pm_disable)) {
+               pr_info("%s disable pm\n", __func__);
+               tegra_sysfs_pm_disable();
+       }
 
 }
 
index f642cba..13dbb71 100644 (file)
@@ -22,6 +22,7 @@
 #include "wldev_common.h"
 
 atomic_t rf_test = ATOMIC_INIT(0);
+atomic_t pm_disable = ATOMIC_INIT(0);
 atomic_t cur_power_mode = ATOMIC_INIT(0);
 extern int tegra_sysfs_wifi_on;
 
@@ -98,6 +99,46 @@ tegra_sysfs_rf_test_disable()
        }
 }
 
+void
+tegra_sysfs_pm_disable(void)
+{
+       extern struct net_device *dhd_custom_sysfs_tegra_histogram_stat_netdev;
+       struct net_device *net = dhd_custom_sysfs_tegra_histogram_stat_netdev;
+       int power_mode_off = 0;
+
+       pr_info("%s\n", __func__);
+
+       if(wldev_ioctl(net, WLC_GET_PM, &cur_power_mode, sizeof(cur_power_mode), false)) {
+               pr_err("%s: Failed to get current power mode state\n", __func__);
+       }
+
+       if(wldev_ioctl(net, WLC_SET_PM, &power_mode_off, sizeof(power_mode_off), true)) {
+               pr_err("%s: Failed to set power mode off state\n", __func__);
+       }
+       atomic_set(&pm_disable, 1);
+}
+
+
+void
+tegra_sysfs_pm_enable(void)
+{
+       extern struct net_device *dhd_custom_sysfs_tegra_histogram_stat_netdev;
+       struct net_device *net = dhd_custom_sysfs_tegra_histogram_stat_netdev;
+
+       pr_info("%s\n", __func__);
+
+       if (atomic_read(&pm_disable)) {
+               atomic_set(&pm_disable, 0);
+
+               if (wldev_ioctl(net, WLC_SET_PM,
+                       (void *)&atomic_read(&cur_power_mode),
+                       sizeof(cur_power_mode), true)) {
+                       pr_err("%s: Failed to restore power mode state\n", __func__);
+               }
+       }
+}
+
+
 ssize_t
 tegra_sysfs_rf_test_state_show(struct device *dev,
        struct device_attribute *attr,
@@ -135,3 +176,41 @@ tegra_sysfs_rf_test_state_store(struct device *dev,
 
        return count;
 }
+
+ssize_t
+tegra_sysfs_pm_state_show(struct device *dev,
+       struct device_attribute *attr,
+       char *buf)
+{
+       if (atomic_read(&pm_disable)) {
+               strcpy(buf, "pm disabled\n");
+               return strlen(buf);
+       } else {
+               strcpy(buf, "pm enabled\n");
+               return strlen(buf);
+       }
+}
+
+ssize_t
+tegra_sysfs_pm_state_store(struct device *dev,
+       struct device_attribute *attr,
+       const char *buf, size_t count)
+{
+       if (strncmp(buf, "pm_disable", 10) == 0) {
+               if (!atomic_read(&pm_disable) && tegra_sysfs_wifi_on) {
+                       tegra_sysfs_pm_disable();
+               } else {
+                       pr_info("%s: operation not allowed\n", __func__);
+               }
+       } else if (strncmp(buf, "pm_enable", 9) == 0) {
+               if (atomic_read(&pm_disable) && tegra_sysfs_wifi_on) {
+                       tegra_sysfs_pm_enable();
+               } else {
+                       pr_info("%s: operation not allowed\n", __func__);
+               }
+       } else {
+               pr_err("%s: unknown command\n", __func__);
+       }
+
+       return count;
+}