aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile2
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c131
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c26
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c39
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.h5
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.h2
6 files changed, 142 insertions, 63 deletions
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index a8b135d..ead28f5 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -8,7 +8,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \
-DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \
-DKEEP_ALIVE -DCSCAN -DGET_CUSTOM_MAC_ENABLE -DPKT_FILTER_SUPPORT \
-DEMBEDDED_PLATFORM -DENABLE_INSMOD_NO_FW_LOAD -DPNO_SUPPORT \
- -DSET_RANDOM_MAC_SOFTAP -DENABLE_P2P_INTERFACE \
+ -DSET_RANDOM_MAC_SOFTAP -DENABLE_P2P_INTERFACE -DDHD_USE_EARLYSUSPEND \
-Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include
DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 6418e38..9654719 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -154,11 +154,10 @@ print_tainted()
extern wl_iw_extra_params_t g_wl_iw_params;
#endif /* defined(WL_WIRELESS_EXT) */
-#if defined(CONFIG_HAS_EARLYSUSPEND)
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
#include <linux/earlysuspend.h>
-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
-extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
#ifdef PKT_FILTER_SUPPORT
extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg);
@@ -259,6 +258,7 @@ typedef struct dhd_info {
* calls and wifi_on or wifi_off
*/
struct mutex dhd_net_if_mutex;
+ struct mutex dhd_suspend_mutex;
#endif
spinlock_t wakelock_spinlock;
int wakelock_counter;
@@ -271,7 +271,7 @@ typedef struct dhd_info {
atomic_t pend_8021x_cnt;
dhd_attach_states_t dhd_state;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif /* CONFIG_HAS_EARLYSUSPEND */
@@ -424,6 +424,8 @@ static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR
;
static void dhd_net_if_lock_local(dhd_info_t *dhd);
static void dhd_net_if_unlock_local(dhd_info_t *dhd);
+static void dhd_suspend_lock(dhd_pub_t *dhdp);
+static void dhd_suspend_unlock(dhd_pub_t *dhdp);
#if !defined(AP) && defined(WLP2P)
static u32 dhd_concurrent_fw(dhd_pub_t *dhd);
#endif
@@ -513,7 +515,6 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
#endif
}
-#if defined(CONFIG_HAS_EARLYSUSPEND)
static int dhd_set_suspend(int value, dhd_pub_t *dhd)
{
int power_mode = PM_MAX;
@@ -525,70 +526,75 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n",
__FUNCTION__, value, dhd->in_suspend));
+ dhd_suspend_lock(dhd);
if (dhd && dhd->up) {
if (value && dhd->in_suspend) {
- /* Kernel suspended */
- DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__));
+ /* Kernel suspended */
+ DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
- sizeof(power_mode), TRUE, 0);
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
+ sizeof(power_mode), TRUE, 0);
- /* Enable packet filter, only allow unicast packet to send up */
- dhd_set_packet_filter(1, dhd);
+ /* Enable packet filter, only allow unicast packet to send up */
+ dhd_set_packet_filter(1, dhd);
- /* If DTIM skip is set up as default, force it to wake
- * each third DTIM for better power savings. Note that
- * one side effect is a chance to miss BC/MC packet.
- */
- bcn_li_dtim = dhd_get_dtim_skip(dhd);
- bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
- 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-
- /* Disable firmware roaming during suspend */
- bcm_mkiovar("roam_off", (char *)&roamvar, 4,
- iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- } else {
+ /* If DTIM skip is set up as default, force it to wake
+ * each third DTIM for better power savings. Note that
+ * one side effect is a chance to miss BC/MC packet.
+ */
+ bcn_li_dtim = dhd_get_dtim_skip(dhd);
+ bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+ 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
+ /* Disable firmware roaming during suspend */
+ bcm_mkiovar("roam_off", (char *)&roamvar, 4,
+ iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ } else {
- /* Kernel resumed */
- DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__));
+ /* Kernel resumed */
+ DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__));
- power_mode = PM_FAST;
- dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
- sizeof(power_mode), TRUE, 0);
+ power_mode = PM_FAST;
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
+ sizeof(power_mode), TRUE, 0);
- /* disable pkt filter */
- dhd_set_packet_filter(0, dhd);
+ /* disable pkt filter */
+ dhd_set_packet_filter(0, dhd);
- /* restore pre-suspend setting for dtim_skip */
- bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
- 4, iovbuf, sizeof(iovbuf));
+ /* restore pre-suspend setting for dtim_skip */
+ bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
+ 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- roamvar = dhd_roam_disable;
- bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf,
- sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- }
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ roamvar = dhd_roam_disable;
+ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf,
+ sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ }
}
-
+ dhd_suspend_unlock(dhd);
return 0;
}
-static void dhd_suspend_resume_helper(struct dhd_info *dhd, int val)
+static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force)
{
dhd_pub_t *dhdp = &dhd->pub;
+ int ret = 0;
DHD_OS_WAKE_LOCK(dhdp);
/* Set flag when early suspend was called */
dhdp->in_suspend = val;
- if ((!dhdp->suspend_disable_flag) && (dhd_check_ap_wfd_mode_set(dhdp) == FALSE))
- dhd_set_suspend(val, dhdp);
+ if ((force || !dhdp->suspend_disable_flag) &&
+ (dhd_check_ap_wfd_mode_set(dhdp) == FALSE))
+ ret = dhd_set_suspend(val, dhdp);
DHD_OS_WAKE_UNLOCK(dhdp);
+ return ret;
}
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
static void dhd_early_suspend(struct early_suspend *h)
{
struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
@@ -596,7 +602,7 @@ static void dhd_early_suspend(struct early_suspend *h)
DHD_TRACE(("%s: enter\n", __FUNCTION__));
if (dhd)
- dhd_suspend_resume_helper(dhd, 1);
+ dhd_suspend_resume_helper(dhd, 1, 0);
}
static void dhd_late_resume(struct early_suspend *h)
@@ -606,7 +612,7 @@ static void dhd_late_resume(struct early_suspend *h)
DHD_TRACE(("%s: enter\n", __FUNCTION__));
if (dhd)
- dhd_suspend_resume_helper(dhd, 0);
+ dhd_suspend_resume_helper(dhd, 0, 0);
}
#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
@@ -2645,6 +2651,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
mutex_init(&dhd->dhd_net_if_mutex);
+ mutex_init(&dhd->dhd_suspend_mutex);
#endif
dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT;
@@ -2730,7 +2737,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
register_pm_notifier(&dhd_sleep_pm_notifier);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
dhd->early_suspend.suspend = dhd_early_suspend;
dhd->early_suspend.resume = dhd_late_resume;
@@ -3563,7 +3570,7 @@ void dhd_detach(dhd_pub_t *dhdp)
unregister_inetaddr_notifier(&dhd_notifier);
#endif /* ARP_OFFLOAD_SUPPORT */
-#if defined(CONFIG_HAS_EARLYSUSPEND)
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
if (dhd->dhd_state & DHD_ATTACH_STATE_EARLYSUSPEND_DONE) {
if (dhd->early_suspend.suspend)
unregister_early_suspend(&dhd->early_suspend);
@@ -4255,16 +4262,18 @@ int net_os_set_suspend_disable(struct net_device *dev, int val)
return ret;
}
-int net_os_set_suspend(struct net_device *dev, int val)
+int net_os_set_suspend(struct net_device *dev, int val, int force)
{
int ret = 0;
-#if defined(CONFIG_HAS_EARLYSUSPEND)
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
if (dhd) {
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
ret = dhd_set_suspend(val, &dhd->pub);
+#else
+ ret = dhd_suspend_resume_helper(dhd, val, force);
+#endif
}
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
return ret;
}
@@ -4440,6 +4449,24 @@ static void dhd_net_if_unlock_local(dhd_info_t *dhd)
#endif
}
+static void dhd_suspend_lock(dhd_pub_t *pub)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ if (dhd)
+ mutex_lock(&dhd->dhd_suspend_mutex);
+#endif
+}
+
+static void dhd_suspend_unlock(dhd_pub_t *pub)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ if (dhd)
+ mutex_unlock(&dhd->dhd_suspend_mutex);
+#endif
+}
+
unsigned long dhd_os_spin_lock(dhd_pub_t *pub)
{
dhd_info_t *dhd = (dhd_info_t *)(pub->info);
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 8f6b198..3b75448 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -67,6 +67,7 @@
#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP"
#define CMD_BTCOEXMODE "BTCOEXMODE"
#define CMD_SETSUSPENDOPT "SETSUSPENDOPT"
+#define CMD_SETSUSPENDMODE "SETSUSPENDMODE"
#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR"
#define CMD_SETFWPATH "SETFWPATH"
#define CMD_SETBAND "SETBAND"
@@ -201,7 +202,7 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int
ret_now = net_os_set_suspend_disable(dev, suspend_flag);
if (ret_now != suspend_flag) {
- if (!(ret = net_os_set_suspend(dev, ret_now)))
+ if (!(ret = net_os_set_suspend(dev, ret_now, 1)))
DHD_INFO(("%s: Suspend Flag %d -> %d\n",
__FUNCTION__, ret_now, suspend_flag));
else
@@ -210,6 +211,26 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int
return ret;
}
+static int wl_android_set_suspendmode(struct net_device *dev, char *command, int total_len)
+{
+ int ret = 0;
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND)
+ int suspend_flag;
+
+ suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0';
+
+ if (suspend_flag != 0)
+ suspend_flag = 1;
+
+ if (!(ret = net_os_set_suspend(dev, suspend_flag, 0)))
+ DHD_INFO(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag));
+ else
+ DHD_ERROR(("%s: failed %d\n",__FUNCTION__,ret));
+#endif
+ return ret;
+}
+
static int wl_android_get_band(struct net_device *dev, char *command, int total_len)
{
uint band;
@@ -505,6 +526,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) {
bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
}
+ else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) {
+ bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len);
+ }
else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
bytes_written = wldev_set_band(net, band);
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index e724aa3..f5494f3 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -1119,7 +1119,7 @@ wl_iw_set_btcoex_dhcp(
}
static int
-wl_iw_set_suspend(
+wl_iw_set_suspend_opt(
struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
@@ -1130,16 +1130,15 @@ char *extra
int ret_now;
int ret = 0;
- suspend_flag = *(extra + strlen(SETSUSPEND_CMD) + 1) - '0';
+ suspend_flag = *(extra + strlen(SETSUSPENDOPT_CMD) + 1) - '0';
if (suspend_flag != 0)
suspend_flag = 1;
ret_now = net_os_set_suspend_disable(dev, suspend_flag);
-
if (ret_now != suspend_flag) {
- if (!(ret = net_os_set_suspend(dev, ret_now)))
+ if (!(ret = net_os_set_suspend(dev, ret_now, 1)))
WL_ERROR(("%s: Suspend Flag %d -> %d\n",
__FUNCTION__, ret_now, suspend_flag));
else
@@ -1150,6 +1149,32 @@ char *extra
}
static int
+wl_iw_set_suspend_mode(
+struct net_device *dev,
+struct iw_request_info *info,
+union iwreq_data *wrqu,
+char *extra
+)
+{
+ int ret = 0;
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND)
+ int suspend_flag;
+
+ suspend_flag = *(extra + strlen(SETSUSPENDMODE_CMD) + 1) - '0';
+
+ if (suspend_flag != 0)
+ suspend_flag = 1;
+
+ if (!(ret = net_os_set_suspend(dev, suspend_flag, 0)))
+ WL_ERROR(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag));
+ else
+ WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
+#endif
+ return ret;
+}
+
+static int
wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
{
int i, c;
@@ -7601,8 +7626,10 @@ wl_iw_set_priv(
ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0)
ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
- ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, SETSUSPENDOPT_CMD, strlen(SETSUSPENDOPT_CMD)) == 0)
+ ret = wl_iw_set_suspend_opt(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, SETSUSPENDMODE_CMD, strlen(SETSUSPENDMODE_CMD)) == 0)
+ ret = wl_iw_set_suspend_mode(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, TXPOWER_SET_CMD, strlen(TXPOWER_SET_CMD)) == 0)
ret = wl_iw_set_txpower(dev, info, (union iwreq_data *)dwrq, extra);
#if defined(PNO_SUPPORT)
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h
index faca5f7..273dcf1 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.h
+++ b/drivers/net/wireless/bcmdhd/wl_iw.h
@@ -47,7 +47,8 @@
#define BAND_SET_CMD "SETBAND"
#define DTIM_SKIP_GET_CMD "DTIMSKIPGET"
#define DTIM_SKIP_SET_CMD "DTIMSKIPSET"
-#define SETSUSPEND_CMD "SETSUSPENDOPT"
+#define SETSUSPENDOPT_CMD "SETSUSPENDOPT"
+#define SETSUSPENDMODE_CMD "SETSUSPENDMODE"
#define PNOSSIDCLR_SET_CMD "PNOSSIDCLR"
#define PNOSETUP_SET_CMD "PNOSETUP "
@@ -206,7 +207,7 @@ extern int net_os_wake_unlock(struct net_device *dev);
extern int net_os_wake_lock_timeout(struct net_device *dev);
extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val);
extern int net_os_set_suspend_disable(struct net_device *dev, int val);
-extern int net_os_set_suspend(struct net_device *dev, int val);
+extern int net_os_set_suspend(struct net_device *dev, int val, int force);
extern int net_os_set_dtim_skip(struct net_device *dev, int val);
extern int net_os_send_hang_message(struct net_device *dev);
extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec);
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h
index 6a1ba15..773235e 100644
--- a/drivers/net/wireless/bcmdhd/wldev_common.h
+++ b/drivers/net/wireless/bcmdhd/wldev_common.h
@@ -92,7 +92,7 @@ extern int net_os_wake_lock_timeout(struct net_device *dev);
extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val);
extern int net_os_set_dtim_skip(struct net_device *dev, int val);
extern int net_os_set_suspend_disable(struct net_device *dev, int val);
-extern int net_os_set_suspend(struct net_device *dev, int val);
+extern int net_os_set_suspend(struct net_device *dev, int val, int force);
extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid,
int max, int *bytes_left);