Skip to content

Commit

Permalink
ath6kl: fixup WOW
Browse files Browse the repository at this point in the history
This also introduces a minimal ioctl in order to more easily
implement a Broadcom like interface in the future

Change-Id: I70d4c8b0834b5f995d36b9558e340e614fb6baba
  • Loading branch information
Bassem Mohsen authored and ohanar committed Jan 6, 2013
1 parent 81ac559 commit 5dce80d
Show file tree
Hide file tree
Showing 10 changed files with 495 additions and 31 deletions.
21 changes: 12 additions & 9 deletions arch/arm/mach-exynos/mach-px.c
Expand Up @@ -358,8 +358,7 @@ static int register_wlan_pdev(struct platform_device *pdev)
return 0;
}

#define WLAN_HOST_WAKE
#ifdef WLAN_HOST_WAKE
#ifdef CONFIG_HAS_WAKELOCK
struct wlansleep_info {
unsigned host_wake;
unsigned host_wake_irq;
Expand All @@ -371,9 +370,13 @@ static struct tasklet_struct hostwake_task;

static void wlan_hostwake_task(unsigned long data)
{
#if defined(CONFIG_MACH_P8LTE)
printk(KERN_INFO "WLAN: wake lock timeout 1 sec...\n");
wake_lock_timeout(&wsi->wake_lock, HZ);
#else
printk(KERN_INFO "WLAN: wake lock timeout 0.5 sec...\n");

wake_lock_timeout(&wsi->wake_lock, HZ / 2);
#endif
}

static irqreturn_t wlan_hostwake_isr(int irq, void *dev_id)
Expand Down Expand Up @@ -423,7 +426,7 @@ static void wlan_host_wake_exit(void)
wake_lock_destroy(&wsi->wake_lock);
kfree(wsi);
}
#endif /* WLAN_HOST_WAKE */
#endif /* CONFIG_HAS_WAKELOCK */

static void config_wlan_gpio(void)
{
Expand Down Expand Up @@ -492,14 +495,14 @@ wlan_setup_power(int on)
mdelay(30);
gpio_direction_output(GPIO_WLAN_nRST, 1);

#ifdef WLAN_HOST_WAKE
#ifdef CONFIG_HAS_WAKELOCK
wlan_host_wake_init();
#endif /* WLAN_HOST_WAKE */
#endif /* CONFIG_HAS_WAKELOCK */

} else {
#ifdef WLAN_HOST_WAKE
#ifdef CONFIG_HAS_WAKELOCK
wlan_host_wake_exit();
#endif /* WLAN_HOST_WAKE */
#endif /* CONFIG_HAS_WAKELOCK */

gpio_direction_output(GPIO_WLAN_nRST, 0);
if (system_rev >= 4)
Expand Down Expand Up @@ -6023,7 +6026,7 @@ static void __init smdkc210_usbgadget_init(void)
/* P2 EUR OPEN */
/*squelch threshold tune [13:11] (000 : +15%) */
pdata->phy_tune_mask |= 0x7 << 11;
pdata->phy_tune |= 0x0 << 11;
pdata->phy_tune |= 0x4 << 11;
#endif
printk(KERN_DEBUG "usb: %s tune_mask=0x%x, tune=0x%x\n",
__func__, pdata->phy_tune_mask, pdata->phy_tune);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath6kl/Makefile
Expand Up @@ -34,6 +34,7 @@ ath6kl-y += main.o
ath6kl-y += txrx.o
ath6kl-y += wmi.o
ath6kl-y += core.o
ath6kl-y += pm.o
ath6kl-$(CONFIG_MACH_PX) += softmac.o
ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath6kl-$(CONFIG_ATH6KL_SDIO) += sdio.o
Expand Down
33 changes: 30 additions & 3 deletions drivers/net/wireless/ath/ath6kl/cfg80211.c
Expand Up @@ -26,6 +26,7 @@
#include "debug.h"
#include "hif-ops.h"
#include "testmode.h"
#include "pm.h"

#define RATETAB_ENT(_rate, _rateid, _flags) { \
.bitrate = (_rate), \
Expand Down Expand Up @@ -1039,6 +1040,13 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
* supported rates to advertise and xmit rates for
* probe requests
*/

#ifdef CONFIG_HAS_WAKELOCK
if (request->no_cck) {
ath6kl_p2p_release_wakelock(ar);
ath6kl_p2p_acquire_wakelock(ar , n_channels * 200);
}
#endif
ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
WMI_LONG_SCAN, force_fg_scan,
false, 0,
Expand Down Expand Up @@ -2244,6 +2252,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar)

ar->state = ATH6KL_STATE_RESUMING;

#ifdef CONFIG_HAS_WAKELOCK
wake_lock_timeout(&ar->wake_lock, 5 * HZ);
#endif
ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
ATH6KL_HOST_MODE_AWAKE);
if (ret) {
Expand Down Expand Up @@ -2477,6 +2488,9 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
break;

case ATH6KL_STATE_SCHED_SCAN:
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_timeout(&ar->wake_lock, 30 * HZ);
#endif
break;

default:
Expand Down Expand Up @@ -2521,18 +2535,22 @@ static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
*
* ath6kl_check_wow_status() is called from ath6kl_rx().
*/
void ath6kl_check_wow_status(struct ath6kl *ar)
void ath6kl_check_wow_status(struct ath6kl *ar, struct sk_buff *skb,
bool is_event_pkt)
{
if (ar->state == ATH6KL_STATE_SUSPENDING)
return;

if (ar->state == ATH6KL_STATE_WOW)
if (ar->state == ATH6KL_STATE_WOW || ar->state == ATH6KL_STATE_SCHED_SCAN)
ath6kl_cfg80211_resume(ar);
else
ath6kl_config_suspend_wake_lock(ar, skb, is_event_pkt);
}

#else

void ath6kl_check_wow_status(struct ath6kl *ar)
void ath6kl_check_wow_status(struct ath6kl *ar, struct sk_buff *skb,
bool is_event_pkt)
{
}
#endif
Expand Down Expand Up @@ -2985,6 +3003,11 @@ static int ath6kl_remain_on_channel(struct wiphy *wiphy,
struct ath6kl *ar = ath6kl_priv(vif->ndev);
u32 id;

#ifdef CONFIG_HAS_WAKELOCK
ath6kl_p2p_release_wakelock(ar);
ath6kl_p2p_acquire_wakelock(ar , duration + 100);
#endif

/* TODO: if already pending or ongoing remain-on-channel,
* return -EBUSY */
id = ++vif->last_roc_id;
Expand Down Expand Up @@ -3641,6 +3664,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)

wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS;

ath6kl_setup_android_resource(ar);

ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
WIPHY_FLAG_HAVE_AP_SME |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
Expand Down Expand Up @@ -3700,6 +3725,8 @@ void ath6kl_cfg80211_destroy(struct ath6kl *ar)
{
int i;

ath6kl_cleanup_android_resource(ar);

for (i = 0; i < AP_MAX_NUM_STA; i++)
kfree(ar->sta_list[i].aggr_conn);

Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/ath/ath6kl/core.c
Expand Up @@ -28,8 +28,13 @@
#include "cfg80211.h"

unsigned int debug_mask;
#ifdef CONFIG_MACH_PX
static unsigned int suspend_mode = WLAN_POWER_STATE_WOW;
static unsigned int wow_mode = WLAN_POWER_STATE_DEEP_SLEEP;
#else
static unsigned int suspend_mode;
static unsigned int wow_mode;
#endif
static unsigned int uart_debug;
static unsigned int ath6kl_p2p;
static unsigned int testmode;
Expand Down
18 changes: 17 additions & 1 deletion drivers/net/wireless/ath/ath6kl/core.h
Expand Up @@ -24,6 +24,12 @@
#include <linux/sched.h>
#include <linux/circ_buf.h>
#include <net/cfg80211.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#ifdef CONFIG_HAS_WAKELOCK
#include <linux/wakelock.h>
#endif
#include "htc.h"
#include "wmi.h"
#include "bmi.h"
Expand Down Expand Up @@ -787,6 +793,16 @@ struct ath6kl {
u8 disc_timeout;
} debug;
#endif /* CONFIG_ATH6KL_DEBUG */

#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
bool screen_off;
#endif /* CONFIG_HAS_EARLYSUSPEND */

#ifdef CONFIG_HAS_WAKELOCK
struct wake_lock wake_lock;
struct wake_lock p2p_wake_lock;
#endif /* CONFIG_HAS_WAKELOCK */
};

static inline struct ath6kl *ath6kl_priv(struct net_device *dev)
Expand Down Expand Up @@ -889,7 +905,7 @@ int ath6kl_init_hw_stop(struct ath6kl *ar);
int ath6kl_init_fetch_firmwares(struct ath6kl *ar);
int ath6kl_init_hw_params(struct ath6kl *ar);

void ath6kl_check_wow_status(struct ath6kl *ar);
void ath6kl_check_wow_status(struct ath6kl *ar, struct sk_buff *skb, bool is_event_pkt);

void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb);
void ath6kl_core_rx_complete(struct ath6kl *ar, struct sk_buff *skb, u8 pipe);
Expand Down
101 changes: 101 additions & 0 deletions drivers/net/wireless/ath/ath6kl/main.c
Expand Up @@ -23,6 +23,14 @@
#include "target.h"
#include "debug.h"

#define CMD_SETSUSPENDMODE "SETSUSPENDMODE"

typedef struct android_wifi_priv_cmd {
char *buf;
int used_len;
int total_len;
} android_wifi_priv_cmd;

struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr)
{
struct ath6kl *ar = vif->ar;
Expand Down Expand Up @@ -1274,13 +1282,106 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
list_splice_tail(&mc_filter_new, &vif->mc_filter);
}

static int ath6kl_set_suspendmode(struct net_device *dev,
char *command, int total_len)
{
struct ath6kl *ar;

ar = ath6kl_priv(dev);

if (*(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0')
ath6kl_hif_suspend(ar, NULL);
else
ath6kl_hif_resume(ar);

return 0;
}

static int ath6kl_priv_cmd(struct net_device *net,
struct ifreq *ifr, int cmd)
{
#define PRIVATE_COMMAND_MAX_LEN 8192
int ret = 0;
char *command = NULL;
int bytes_written = 0;
android_wifi_priv_cmd priv_cmd;

if (!ifr->ifr_data) {
ret = -EINVAL;
goto exit;
}
if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
ret = -EFAULT;
goto exit;
}
if (priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN)
{
ath6kl_err("%s: too long priavte command\n", __func__);
ret = -EINVAL;
}
command = kmalloc(priv_cmd.total_len, GFP_KERNEL);
if (!command)
{
ath6kl_err("%s: failed to allocate memory\n", __func__);
ret = -ENOMEM;
goto exit;
}
if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
ret = -EFAULT;
goto exit;
}

ath6kl_info("%s: Android private cmd \"%s\" on %s\n", __func__, command, ifr->ifr_name);

if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) {
ath6kl_set_suspendmode(net, command, priv_cmd.total_len);
} else {
ath6kl_err("Unknown PRIVATE command %s - ignored\n", command);
snprintf(command, 3, "OK");
bytes_written = strlen("OK");
}

if (bytes_written >= 0) {
if ((bytes_written == 0) && (priv_cmd.total_len > 0))
command[0] = '\0';
if (bytes_written >= priv_cmd.total_len) {
ath6kl_err("%s: bytes_written = %d\n", __func__, bytes_written);
bytes_written = priv_cmd.total_len;
} else {
bytes_written++;
}
priv_cmd.used_len = bytes_written;
if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
ath6kl_err("%s: failed to copy data to user buffer\n", __func__);
ret = -EFAULT;
}
} else
ret = bytes_written;

exit:
if (command) {
kfree(command);
}

return ret;
}

static int ath6kl_do_ioctl(struct net_device *dev,
struct ifreq *ifr, int cmd)
{
if (cmd == SIOCDEVPRIVATE+1)
return ath6kl_priv_cmd(dev, ifr, cmd);
return -EOPNOTSUPP;
}

static const struct net_device_ops ath6kl_netdev_ops = {
.ndo_open = ath6kl_open,
.ndo_stop = ath6kl_close,
.ndo_start_xmit = ath6kl_data_tx,
.ndo_get_stats = ath6kl_get_stats,
.ndo_set_features = ath6kl_set_features,
.ndo_set_rx_mode = ath6kl_set_multicast_list,
.ndo_do_ioctl = ath6kl_do_ioctl,
};

void init_netdev(struct net_device *dev)
Expand Down

0 comments on commit 5dce80d

Please sign in to comment.