[net-config] Suspend/Resume WLAN driver 07/188607/1
authorMayank Haarit <mayank.h@samsung.com>
Thu, 6 Sep 2018 11:49:53 +0000 (17:19 +0530)
committerMayank Haarit <mayank.h@samsung.com>
Thu, 6 Sep 2018 11:49:53 +0000 (17:19 +0530)
This patch suspend and resume wlan driver as
per below action :
1) On LCD ON/OFF state change callback
2) On the basis of current service state

Change-Id: I90d2b67c5d6fa6be80421c5bf817aefccdc3fe88
Signed-off-by: Mayank Haarit <mayank.h@samsung.com>
include/wifi-power.h
src/wifi-power.c
src/wifi-state.c

index 598d290..49f25aa 100755 (executable)
@@ -31,6 +31,7 @@ void wifi_power_deinitialize(void);
 
 int wifi_power_on(void);
 int wifi_power_off(void);
+void wifi_set_early_suspend(gboolean);
 #if defined TIZEN_WEARABLE
 int wifi_power_on_wearable(gboolean device_picker_test);
 #endif
index e052147..c900012 100755 (executable)
@@ -24,6 +24,8 @@
 #include <stdlib.h>
 #include <glib.h>
 #include <tzplatform_config.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
 
 #include "log.h"
 #include "util.h"
 
 #define NETCONFIG_TECH_WAITING_INTERVAL 500
 #define NETCONFIG_TECH_WAITING_COUNT 6
+#define MAX_DRV_CMD_SIZE 248
+#define WLAN_IOCTL_SUSPEND (SIOCDEVPRIVATE + 1)
 
 static gboolean connman_wifi_technology_state = FALSE;
 static gboolean wifi_firmware_recovery_mode = FALSE;
 static int airplane_mode = 0;
 
+typedef struct {
+       char *buf;
+       int used_len;
+       int total_len;
+} netconfig_wifi_priv_cmd;
+
 static gboolean __is_wifi_restricted(void)
 {
 #if defined TIZEN_WEARABLE
@@ -497,6 +507,66 @@ static void __emergency_mode_changed_cb(keynode_t *node, void *user_data)
 
 }
 
+void wifi_set_early_suspend(gboolean value)
+{
+       static gboolean old_state = FALSE;
+       struct ifreq ifr;
+       char buf[MAX_DRV_CMD_SIZE];
+       netconfig_wifi_priv_cmd priv_cmd;
+       int ret = 0;
+       int ioctl_sock = 0;
+       int pm_state = 0;
+       wifi_service_state_e wifi_state;
+
+       if (old_state == value) {
+               DBG("Old and new states are same");
+               return;
+       }
+
+       if (netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state) < 0)
+               ERR("Fail to get VCONFKEY_PM_STATE");
+
+       wifi_state = wifi_state_get_service_state();
+
+       if (value == TRUE &&
+                       (pm_state < VCONFKEY_PM_STATE_LCDOFF ||
+                        wifi_state == NETCONFIG_WIFI_ASSOCIATION ||
+                        wifi_state == NETCONFIG_WIFI_CONFIGURATION)){
+               DBG("");
+               return;
+       }
+
+       memset(buf, 0, sizeof(buf));
+       snprintf(buf, sizeof(buf), "SETSUSPENDMODE %d", value);
+
+       memset(&ifr, 0, sizeof(struct ifreq));
+       g_strlcpy((char *)ifr.ifr_name, WIFI_IFNAME, IFNAMSIZ);
+
+       DBG("Early suspend command: [%s]", buf);
+
+       memset(&priv_cmd, 0, sizeof(priv_cmd));
+       priv_cmd.buf = buf;
+       priv_cmd.used_len = sizeof(buf);
+       priv_cmd.total_len = sizeof(buf);
+       ifr.ifr_data = (char *)&priv_cmd;
+
+       ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
+       if (ioctl_sock < 0) {
+               DBG("socket(PF_INET,SOCK_DGRAM) failed");
+               return;
+       }
+
+       ret = ioctl(ioctl_sock, WLAN_IOCTL_SUSPEND, &ifr);
+
+       if (ret < 0)
+               ERR("Fail to issue private commands: %d. %s", ret, strerror(errno));
+       else {
+               old_state = value;
+       }
+
+       close(ioctl_sock);
+}
+
 static void __pm_state_changed_cb(keynode_t* node, void* user_data)
 {
        int new_state = -1;
@@ -523,9 +593,18 @@ static void __pm_state_changed_cb(keynode_t* node, void* user_data)
        DBG("Old PM state: %d, current: %d (1 normal / 2 lcddim / 3 lcdoff / 4 sleep)", prev_state, new_state);
 
        if ((new_state == VCONFKEY_PM_STATE_NORMAL) && (prev_state >= VCONFKEY_PM_STATE_LCDOFF)) {
+               /* Send early suspend mode based on LCD state and disallow early suspend count */
+               if (wifi_state != VCONFKEY_WIFI_OFF) {
+                       wifi_set_early_suspend(FALSE);
+                       DBG("Unset early suspend");
+               }
+
                netconfig_wifi_bgscan_stop();
                netconfig_wifi_bgscan_set_interval(SCAN_EXPONENTIAL_MIN);
                netconfig_wifi_bgscan_start(TRUE);
+       } else if ((new_state == VCONFKEY_PM_STATE_LCDOFF) && (prev_state < VCONFKEY_PM_STATE_LCDOFF) && (wifi_state != VCONFKEY_WIFI_OFF)) {
+               wifi_set_early_suspend(TRUE);
+               DBG("Set early suspend");
        }
 
        prev_state = new_state;
index 27c64f1..237e2e0 100755 (executable)
@@ -541,12 +541,14 @@ void wifi_state_set_service_state(wifi_service_state_e new_state)
        DBG("Wi-Fi service state, old state[%s] ==> new state[%s]",
                _convert_wifi_service_state_to_string(old_state), _convert_wifi_service_state_to_string(new_state));
 
-       /* During DHCP, temporarily disable Wi-Fi power saving */
-       if ((old_state < NETCONFIG_WIFI_ASSOCIATION || old_state == NETCONFIG_WIFI_FAILURE) && new_state == NETCONFIG_WIFI_CONFIGURATION) {
+       /* From association, temporarily disable Wi-Fi power saving */
+       if ((old_state < NETCONFIG_WIFI_ASSOCIATION || old_state == NETCONFIG_WIFI_FAILURE) && new_state == NETCONFIG_WIFI_ASSOCIATION) {
                _set_power_lock(TRUE);
+               wifi_set_early_suspend(FALSE);
                dhcp_stage = TRUE;
-       } else if (dhcp_stage == TRUE) {
+       } else if (dhcp_stage == TRUE && new_state != NETCONFIG_WIFI_CONFIGURATION) {
                _set_power_lock(FALSE);
+               wifi_set_early_suspend(TRUE);
                dhcp_stage = FALSE;
        }