Skip to content

Commit

Permalink
libertas: convert PS_MODE to a direct command
Browse files Browse the repository at this point in the history
Powersave looks like it got broken at some point but we'll fix that up
when the command submission stuff is more understandable, which this
series helps to do.  That said, this patch should not further break
powersave.

Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Dan Williams authored and John W. Linville committed Jul 27, 2010
1 parent 8196112 commit 0bb6408
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 126 deletions.
139 changes: 55 additions & 84 deletions drivers/net/wireless/libertas/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,42 +230,49 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
}
EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);

static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
u16 cmd_action)
/**
* @brief Sets the Power Save mode
*
* @param priv A pointer to struct lbs_private structure
* @param cmd_action The Power Save operation (PS_MODE_ACTION_ENTER_PS or
* PS_MODE_ACTION_EXIT_PS)
* @param block Whether to block on a response or not
*
* @return 0 on success, error on failure
*/
int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
{
struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
struct cmd_ds_802_11_ps_mode cmd;
int ret = 0;

lbs_deb_enter(LBS_DEB_CMD);

cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
sizeof(struct cmd_header));
psm->action = cpu_to_le16(cmd_action);
psm->multipledtim = 0;
switch (cmd_action) {
case CMD_SUBCMD_ENTER_PS:
lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");

psm->locallisteninterval = 0;
psm->nullpktinterval = 0;
psm->multipledtim =
cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
break;

case CMD_SUBCMD_EXIT_PS:
lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
break;

case CMD_SUBCMD_SLEEP_CONFIRMED:
lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
break;
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(cmd_action);

default:
break;
if (cmd_action == PS_MODE_ACTION_ENTER_PS) {
lbs_deb_cmd("PS_MODE: action ENTER_PS\n");
cmd.multipledtim = cpu_to_le16(1); /* Default DTIM multiple */
} else if (cmd_action == PS_MODE_ACTION_EXIT_PS) {
lbs_deb_cmd("PS_MODE: action EXIT_PS\n");
} else {
/* We don't handle CONFIRM_SLEEP here because it needs to
* be fastpathed to the firmware.
*/
lbs_deb_cmd("PS_MODE: unknown action 0x%X\n", cmd_action);
ret = -EOPNOTSUPP;
goto out;
}

lbs_deb_leave(LBS_DEB_CMD);
return 0;
if (block)
ret = lbs_cmd_with_response(priv, CMD_802_11_PS_MODE, &cmd);
else
lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd));

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

int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
Expand Down Expand Up @@ -950,16 +957,15 @@ static void lbs_queue_cmd(struct lbs_private *priv,

/* Exit_PS command needs to be queued in the header always. */
if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1];
struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf;

if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
if (priv->psstate != PS_STATE_FULL_POWER)
addtail = 0;
}
}

if (le16_to_cpu(cmdnode->cmdbuf->command) ==
CMD_802_11_WAKEUP_CONFIRM)
if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_WAKEUP_CONFIRM)
addtail = 0;

spin_lock_irqsave(&priv->driver_lock, flags);
Expand Down Expand Up @@ -1154,7 +1160,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
{
int ret = 0;
struct cmd_ctrl_node *cmdnode;
struct cmd_ds_command *cmdptr;
struct cmd_header *cmdptr;
unsigned long flags;

lbs_deb_enter(LBS_DEB_HOST);
Expand Down Expand Up @@ -1190,7 +1196,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
cmdnode->callback = NULL;
cmdnode->callback_arg = (unsigned long)pdata_buf;

cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
cmdptr = (struct cmd_header *)cmdnode->cmdbuf;

lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);

Expand All @@ -1202,10 +1208,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
cmdptr->result = 0;

switch (cmd_no) {
case CMD_802_11_PS_MODE:
ret = lbs_cmd_802_11_ps_mode(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(sizeof(struct cmd_header));
Expand Down Expand Up @@ -1426,10 +1428,10 @@ int lbs_execute_next_command(struct lbs_private *priv)
/*
* 1. Non-PS command:
* Queue it. set needtowakeup to TRUE if current state
* is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
* 2. PS command but not Exit_PS:
* is SLEEP, otherwise call send EXIT_PS.
* 2. PS command but not EXIT_PS:
* Ignore it.
* 3. PS command Exit_PS:
* 3. PS command EXIT_PS:
* Set needtowakeup to TRUE if current state is SLEEP,
* otherwise send this command down to firmware
* immediately.
Expand All @@ -1443,8 +1445,11 @@ int lbs_execute_next_command(struct lbs_private *priv)
/* w/ new scheme, it will not reach here.
since it is blocked in main_thread. */
priv->needtowakeup = 1;
} else
lbs_ps_wakeup(priv, 0);
} else {
lbs_set_ps_mode(priv,
PS_MODE_ACTION_EXIT_PS,
false);
}

ret = 0;
goto done;
Expand All @@ -1459,7 +1464,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
"EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
psm->action);
if (psm->action !=
cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
lbs_deb_host(
"EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
list_del(&cmdnode->list);
Expand Down Expand Up @@ -1519,13 +1524,16 @@ int lbs_execute_next_command(struct lbs_private *priv)
lbs_deb_host(
"EXEC_NEXT_CMD: WPA enabled and GTK_SET"
" go back to PS_SLEEP");
lbs_ps_sleep(priv, 0);
lbs_set_ps_mode(priv,
PS_MODE_ACTION_ENTER_PS,
false);
}
} else {
lbs_deb_host(
"EXEC_NEXT_CMD: cmdpendingq empty, "
"go back to PS_SLEEP");
lbs_ps_sleep(priv, 0);
lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS,
false);
}
}
#endif
Expand Down Expand Up @@ -1573,43 +1581,6 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
lbs_deb_leave(LBS_DEB_HOST);
}

void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
{
lbs_deb_enter(LBS_DEB_HOST);

/*
* PS is currently supported only in Infrastructure mode
* Remove this check if it is to be supported in IBSS mode also
*/

lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);

lbs_deb_leave(LBS_DEB_HOST);
}

/**
* @brief This function sends Exit_PS command to firmware.
*
* @param priv A pointer to struct lbs_private structure
* @param wait_option wait response or not
* @return n/a
*/
void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
{
__le32 Localpsmode;

lbs_deb_enter(LBS_DEB_HOST);

Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);

lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
CMD_SUBCMD_EXIT_PS,
wait_option, 0, &Localpsmode);

lbs_deb_leave(LBS_DEB_HOST);
}

/**
* @brief This function checks condition and prepares to
* send sleep confirm command to firmware if ok.
Expand Down
6 changes: 2 additions & 4 deletions drivers/net/wireless/libertas/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,6 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
struct sleep_params *sp);

void lbs_ps_sleep(struct lbs_private *priv, int wait_option);

void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);

void lbs_ps_confirm_sleep(struct lbs_private *priv);

int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
Expand Down Expand Up @@ -143,4 +139,6 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value);

int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value);

int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block);

#endif /* _LBS_CMD_H */
13 changes: 7 additions & 6 deletions drivers/net/wireless/libertas/cmdresp.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
if (priv->psstate != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
lbs_deb_cmd("disconnected, so exit PS mode\n");
lbs_ps_wakeup(priv, 0);
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
}
lbs_deb_leave(LBS_DEB_ASSOC);
}
Expand Down Expand Up @@ -132,9 +132,9 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
* lbs_execute_next_command().
*/
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
action == CMD_SUBCMD_ENTER_PS)
action == PS_MODE_ACTION_ENTER_PS)
priv->psmode = LBS802_11POWERMODECAM;
} else if (action == CMD_SUBCMD_ENTER_PS) {
} else if (action == PS_MODE_ACTION_ENTER_PS) {
priv->needtowakeup = 0;
priv->psstate = PS_STATE_AWAKE;

Expand All @@ -149,11 +149,12 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)

spin_unlock_irqrestore(&priv->driver_lock, flags);
mutex_unlock(&priv->lock);
lbs_ps_wakeup(priv, 0);
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS,
false);
mutex_lock(&priv->lock);
spin_lock_irqsave(&priv->driver_lock, flags);
}
} else if (action == CMD_SUBCMD_EXIT_PS) {
} else if (action == PS_MODE_ACTION_EXIT_PS) {
priv->needtowakeup = 0;
priv->psstate = PS_STATE_FULL_POWER;
lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
Expand Down Expand Up @@ -291,7 +292,7 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
* in lbs_ps_wakeup()
*/
lbs_deb_cmd("waking up ...\n");
lbs_ps_wakeup(priv, 0);
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
}
break;

Expand Down
5 changes: 0 additions & 5 deletions drivers/net/wireless/libertas/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define MRVDRV_MAX_BSS_DESCRIPTS 16
#define MRVDRV_MAX_REGION_CODE 6

#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe
#define MRVDRV_MIN_MULTIPLE_DTIM 1
#define MRVDRV_MAX_MULTIPLE_DTIM 5
#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1

#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10

#define MRVDRV_CHANNELS_PER_SCAN 4
Expand Down
50 changes: 27 additions & 23 deletions drivers/net/wireless/libertas/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,9 @@
#define CMD_802_11_BEACON_CTRL 0x00b0

/* For the IEEE Power Save */
#define CMD_SUBCMD_ENTER_PS 0x0030
#define CMD_SUBCMD_EXIT_PS 0x0031
#define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034
#define CMD_SUBCMD_FULL_POWERDOWN 0x0035
#define CMD_SUBCMD_FULL_POWERUP 0x0036
#define PS_MODE_ACTION_ENTER_PS 0x0030
#define PS_MODE_ACTION_EXIT_PS 0x0031
#define PS_MODE_ACTION_SLEEP_CONFIRMED 0x0034

#define CMD_ENABLE_RSN 0x0001
#define CMD_DISABLE_RSN 0x0000
Expand Down Expand Up @@ -163,11 +161,6 @@
#define CMD_ACT_SET_TX_FIX_RATE 0x0001
#define CMD_ACT_GET_TX_RATE 0x0002

/* Define action or option for CMD_802_11_PS_MODE */
#define CMD_TYPE_CAM 0x0000
#define CMD_TYPE_MAX_PSP 0x0001
#define CMD_TYPE_FAST_PSP 0x0002

/* Options for CMD_802_11_FW_WAKE_METHOD */
#define CMD_WAKE_METHOD_UNCHANGED 0x0000
#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
Expand Down Expand Up @@ -683,11 +676,35 @@ struct cmd_ds_802_11_fw_wake_method {
} __packed;

struct cmd_ds_802_11_ps_mode {
struct cmd_header hdr;

__le16 action;

/* Interval for keepalive in PS mode:
* 0x0000 = don't change
* 0x001E = firmware default
* 0xFFFF = disable
*/
__le16 nullpktinterval;

/* Number of DTIM intervals to wake up for:
* 0 = don't change
* 1 = firmware default
* 5 = max
*/
__le16 multipledtim;

__le16 reserved;
__le16 locallisteninterval;

/* AdHoc awake period (FW v9+ only):
* 0 = don't change
* 1 = always awake (IEEE standard behavior)
* 2 - 31 = sleep for (n - 1) periods and awake for 1 period
* 32 - 254 = invalid
* 255 = sleep at each ATIM
*/
__le16 adhoc_awake_period;
} __packed;

struct cmd_confirm_sleep {
Expand Down Expand Up @@ -952,17 +969,4 @@ struct cmd_ds_mesh_access {

/* Number of stats counters returned by the firmware */
#define MESH_STATS_NUM 8

struct cmd_ds_command {
/* command header */
__le16 command;
__le16 size;
__le16 seqnum;
__le16 result;

/* command Body */
union {
struct cmd_ds_802_11_ps_mode psmode;
} params;
} __packed;
#endif
Loading

0 comments on commit 0bb6408

Please sign in to comment.