Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 170591
b: refs/heads/master
c: 4912545
h: refs/heads/master
i:
  170589: 942b9a9
  170587: e9a0e3e
  170583: 294d4c7
  170575: c2034df
  170559: bba7384
v: v3
  • Loading branch information
Amitkumar Karwar authored and John W. Linville committed Oct 7, 2009
1 parent aa536e8 commit 7f9726d
Show file tree
Hide file tree
Showing 16 changed files with 534 additions and 22 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 125b181aec7a67c71234284ecf6d9c729d05deda
refs/heads/master: 4912545472d71e3dd546b18b397aec4c89fd7403
26 changes: 25 additions & 1 deletion trunk/drivers/net/wireless/libertas/README
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
================================================================================
README for USB8388
README for Libertas

(c) Copyright © 2003-2006, Marvell International Ltd.
All Rights Reserved
Expand Down Expand Up @@ -226,4 +226,28 @@ setuserscan
All entries in the scan table (not just the new scan data when keep=1)
will be displayed upon completion by use of the getscantable ioctl.

========================
IWCONFIG COMMANDS
========================
power period

This command is used to configure the station in deep sleep mode /
auto deep sleep mode.

The timer is implemented to monitor the activities (command, event,
etc.). When an activity is detected station will exit from deep
sleep mode automatically and restart the timer. At timer expiry
(no activity for defined time period) the deep sleep mode is entered
automatically.

Note: this command is for SDIO interface only.

Usage:
To enable deep sleep mode do:
iwconfig wlan0 power period 0
To enable auto deep sleep mode with idle time period 5 seconds do:
iwconfig wlan0 power period 5
To disable deep sleep/auto deep sleep mode do:
iwconfig wlan0 power period -1

==============================================================================
72 changes: 69 additions & 3 deletions trunk/drivers/net/wireless/libertas/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);


/**
* @brief Simple callback that copies response back into command
*
Expand Down Expand Up @@ -319,6 +318,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
return 0;
}

static int lbs_wait_for_ds_awake(struct lbs_private *priv)
{
int ret = 0;

lbs_deb_enter(LBS_DEB_CMD);

if (priv->is_deep_sleep) {
if (!wait_event_interruptible_timeout(priv->ds_awake_q,
!priv->is_deep_sleep, (10 * HZ))) {
lbs_pr_err("ds_awake_q: timer expired\n");
ret = -1;
}
}

lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}

int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
{
int ret = 0;

lbs_deb_enter(LBS_DEB_CMD);

if (deep_sleep) {
if (priv->is_deep_sleep != 1) {
lbs_deb_cmd("deep sleep: sleep\n");
BUG_ON(!priv->enter_deep_sleep);
ret = priv->enter_deep_sleep(priv);
if (!ret) {
netif_stop_queue(priv->dev);
netif_carrier_off(priv->dev);
}
} else {
lbs_pr_err("deep sleep: already enabled\n");
}
} else {
if (priv->is_deep_sleep) {
lbs_deb_cmd("deep sleep: wakeup\n");
BUG_ON(!priv->exit_deep_sleep);
ret = priv->exit_deep_sleep(priv);
if (!ret) {
ret = lbs_wait_for_ds_awake(priv);
if (ret)
lbs_pr_err("deep sleep: wakeup"
"failed\n");
}
}
}

lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}

int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc)
{
Expand Down Expand Up @@ -1242,8 +1295,17 @@ static void lbs_submit_command(struct lbs_private *priv,
timeo = HZ/4;
}

/* Setup the timer after transmit command */
mod_timer(&priv->command_timer, jiffies + timeo);
if (command == CMD_802_11_DEEP_SLEEP) {
if (priv->is_auto_deep_sleep_enabled) {
priv->wakeup_dev_required = 1;
priv->dnld_sent = 0;
}
priv->is_deep_sleep = 1;
lbs_complete_command(priv, cmdnode, 0);
} else {
/* Setup the timer after transmit command */
mod_timer(&priv->command_timer, jiffies + timeo);
}

lbs_deb_leave(LBS_DEB_HOST);
}
Expand Down Expand Up @@ -1505,6 +1567,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
case CMD_802_11_BEACON_CTRL:
ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
break;
case CMD_802_11_DEEP_SLEEP:
cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
cmdptr->size = cpu_to_le16(S_DS_GEN);
break;
default:
lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
ret = -1;
Expand Down
12 changes: 12 additions & 0 deletions trunk/drivers/net/wireless/libertas/cmdresp.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,9 +504,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event)

case MACREG_INT_CODE_HOST_AWAKE:
lbs_deb_cmd("EVENT: host awake\n");
if (priv->reset_deep_sleep_wakeup)
priv->reset_deep_sleep_wakeup(priv);
priv->is_deep_sleep = 0;
lbs_send_confirmwake(priv);
break;

case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
if (priv->reset_deep_sleep_wakeup)
priv->reset_deep_sleep_wakeup(priv);
lbs_deb_cmd("EVENT: ds awake\n");
priv->is_deep_sleep = 0;
priv->wakeup_dev_required = 0;
wake_up_interruptible(&priv->ds_awake_q);
break;

case MACREG_INT_CODE_PS_AWAKE:
lbs_deb_cmd("EVENT: ps awake\n");
/* handle unexpected PS AWAKE event */
Expand Down
46 changes: 46 additions & 0 deletions trunk/drivers/net/wireless/libertas/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ static ssize_t lbs_sleepparams_write(struct file *file,
if (!buf)
return -ENOMEM;

if (!lbs_is_cmd_allowed(priv)) {
ret = -EBUSY;
goto out_unlock;
}

buf_size = min(count, len - 1);
if (copy_from_user(buf, user_buf, buf_size)) {
ret = -EFAULT;
Expand Down Expand Up @@ -157,6 +162,11 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
if (!buf)
return -ENOMEM;

if (!lbs_is_cmd_allowed(priv)) {
ret = -EBUSY;
goto out_unlock;
}

ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
if (ret)
goto out_unlock;
Expand Down Expand Up @@ -223,6 +233,9 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
u8 freq;
int events = 0;

if (!lbs_is_cmd_allowed(priv))
return -EBUSY;

buf = (char *)get_zeroed_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
Expand Down Expand Up @@ -275,6 +288,9 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
char *buf;
int ret;

if (!lbs_is_cmd_allowed(priv))
return -EBUSY;

buf = (char *)get_zeroed_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
Expand Down Expand Up @@ -444,6 +460,11 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
if (!buf)
return -ENOMEM;

if (!lbs_is_cmd_allowed(priv)) {
free_page(addr);
return -EBUSY;
}

offval.offset = priv->mac_offset;
offval.value = 0;

Expand Down Expand Up @@ -496,6 +517,11 @@ static ssize_t lbs_wrmac_write(struct file *file,
if (!buf)
return -ENOMEM;

if (!lbs_is_cmd_allowed(priv)) {
res = -EBUSY;
goto out_unlock;
}

buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
Expand Down Expand Up @@ -532,6 +558,11 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
if (!buf)
return -ENOMEM;

if (!lbs_is_cmd_allowed(priv)) {
free_page(addr);
return -EBUSY;
}

offval.offset = priv->bbp_offset;
offval.value = 0;

Expand Down Expand Up @@ -585,6 +616,11 @@ static ssize_t lbs_wrbbp_write(struct file *file,
if (!buf)
return -ENOMEM;

if (!lbs_is_cmd_allowed(priv)) {
res = -EBUSY;
goto out_unlock;
}

buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
Expand Down Expand Up @@ -621,6 +657,11 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
if (!buf)
return -ENOMEM;

if (!lbs_is_cmd_allowed(priv)) {
free_page(addr);
return -EBUSY;
}

offval.offset = priv->rf_offset;
offval.value = 0;

Expand Down Expand Up @@ -674,6 +715,11 @@ static ssize_t lbs_wrrf_write(struct file *file,
if (!buf)
return -ENOMEM;

if (!lbs_is_cmd_allowed(priv)) {
res = -EBUSY;
goto out_unlock;
}

buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/net/wireless/libertas/decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ int lbs_execute_next_command(struct lbs_private *priv);
int lbs_process_event(struct lbs_private *priv, u32 event);
void lbs_queue_event(struct lbs_private *priv, u32 event);
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
int lbs_is_cmd_allowed(struct lbs_private *priv);
int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
int lbs_exit_auto_deep_sleep(struct lbs_private *priv);

u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
Expand Down
18 changes: 18 additions & 0 deletions trunk/drivers/net/wireless/libertas/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ struct lbs_private {
u32 bbp_offset;
u32 rf_offset;

/** Deep sleep flag */
int is_deep_sleep;
/** Auto deep sleep enabled flag */
int is_auto_deep_sleep_enabled;
/** Device wakeup required flag */
int wakeup_dev_required;
/** Auto deep sleep flag*/
int is_activity_detected;
/** Auto deep sleep timeout (in miliseconds) */
int auto_deep_sleep_timeout;

/** Deep sleep wait queue */
wait_queue_head_t ds_awake_q;

/* Download sent:
bit0 1/0=data_sent/data_tx_done,
bit1 1/0=cmd_sent/cmd_tx_done,
Expand All @@ -154,6 +168,9 @@ struct lbs_private {
/** Hardware access */
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
void (*reset_card) (struct lbs_private *priv);
int (*enter_deep_sleep) (struct lbs_private *priv);
int (*exit_deep_sleep) (struct lbs_private *priv);
int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);

/* Wake On LAN */
uint32_t wol_criteria;
Expand Down Expand Up @@ -204,6 +221,7 @@ struct lbs_private {

/** Timers */
struct timer_list command_timer;
struct timer_list auto_deepsleep_timer;
int nr_retries;
int cmd_timed_out;

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/libertas/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#define CMD_802_11_ENABLE_RSN 0x002f
#define CMD_802_11_SET_AFC 0x003c
#define CMD_802_11_GET_AFC 0x003d
#define CMD_802_11_DEEP_SLEEP 0x003e
#define CMD_802_11_AD_HOC_STOP 0x0040
#define CMD_802_11_HOST_SLEEP_CFG 0x0043
#define CMD_802_11_WAKEUP_CONFIRM 0x0044
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/wireless/libertas/if_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
card->priv = priv;
priv->card = card;
priv->hw_host_to_card = if_cs_host_to_card;
priv->enter_deep_sleep = NULL;
priv->exit_deep_sleep = NULL;
priv->reset_deep_sleep_wakeup = NULL;
priv->fw_ready = 1;

/* Now actually get the IRQ */
Expand Down
Loading

0 comments on commit 7f9726d

Please sign in to comment.