summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/cmd.c37
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c30
-rw-r--r--drivers/net/wireless/libertas/decl.h2
-rw-r--r--drivers/net/wireless/libertas/dev.h6
-rw-r--r--drivers/net/wireless/libertas/ethtool.c24
-rw-r--r--drivers/net/wireless/libertas/host.h120
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c58
-rw-r--r--drivers/net/wireless/libertas/if_usb.c12
-rw-r--r--drivers/net/wireless/libertas/main.c79
-rw-r--r--drivers/net/wireless/libertas/radiotap.h4
-rw-r--r--drivers/net/wireless/libertas/rx.c8
-rw-r--r--drivers/net/wireless/libertas/scan.c2
-rw-r--r--drivers/net/wireless/libertas/types.h66
13 files changed, 276 insertions, 172 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index cdb9b96..0fa6b0e 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -70,6 +70,8 @@ static u8 is_command_allowed_in_ps(u16 cmd)
switch (cmd) {
case CMD_802_11_RSSI:
return 1;
+ case CMD_802_11_HOST_SLEEP_CFG:
+ return 1;
default:
break;
}
@@ -185,6 +187,23 @@ out:
return ret;
}
+static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
+ struct cmd_header *resp)
+{
+ lbs_deb_enter(LBS_DEB_CMD);
+ if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
+ priv->is_host_sleep_configured = 0;
+ if (priv->psstate == PS_STATE_FULL_POWER) {
+ priv->is_host_sleep_activated = 0;
+ wake_up_interruptible(&priv->host_sleep_q);
+ }
+ } else {
+ priv->is_host_sleep_configured = 1;
+ }
+ lbs_deb_leave(LBS_DEB_CMD);
+ return 0;
+}
+
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
struct wol_config *p_wol_config)
{
@@ -202,12 +221,11 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
else
cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;
- ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config);
+ ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr,
+ le16_to_cpu(cmd_config.hdr.size),
+ lbs_ret_host_sleep_cfg, 0);
if (!ret) {
- if (criteria) {
- lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
- priv->wol_criteria = criteria;
- } else
+ if (p_wol_config)
memcpy((uint8_t *) p_wol_config,
(uint8_t *)&cmd_config.wol_conf,
sizeof(struct wol_config));
@@ -712,6 +730,10 @@ static void lbs_queue_cmd(struct lbs_private *priv,
}
}
+ if (le16_to_cpu(cmdnode->cmdbuf->command) ==
+ CMD_802_11_WAKEUP_CONFIRM)
+ addtail = 0;
+
spin_lock_irqsave(&priv->driver_lock, flags);
if (addtail)
@@ -1353,6 +1375,11 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
/* We don't get a response on the sleep-confirmation */
priv->dnld_sent = DNLD_RES_RECEIVED;
+ if (priv->is_host_sleep_configured) {
+ priv->is_host_sleep_activated = 1;
+ wake_up_interruptible(&priv->host_sleep_q);
+ }
+
/* If nothing to do, go back to sleep (?) */
if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx])
priv->psstate = PS_STATE_SLEEP;
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 88f7131..d6c3063 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -17,6 +17,7 @@
#include "dev.h"
#include "assoc.h"
#include "wext.h"
+#include "cmd.h"
/**
* @brief This function handles disconnect event. it
@@ -341,32 +342,10 @@ done:
return ret;
}
-static int lbs_send_confirmwake(struct lbs_private *priv)
-{
- struct cmd_header cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
- cmd.size = cpu_to_le16(sizeof(cmd));
- cmd.seqnum = cpu_to_le16(++priv->seqnum);
- cmd.result = 0;
-
- lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
- sizeof(cmd));
-
- ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
- if (ret)
- lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
-
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
- return ret;
-}
-
int lbs_process_event(struct lbs_private *priv, u32 event)
{
int ret = 0;
+ struct cmd_header cmd;
lbs_deb_enter(LBS_DEB_CMD);
@@ -410,7 +389,10 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
if (priv->reset_deep_sleep_wakeup)
priv->reset_deep_sleep_wakeup(priv);
priv->is_deep_sleep = 0;
- lbs_send_confirmwake(priv);
+ lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd,
+ sizeof(cmd));
+ priv->is_host_sleep_activated = 0;
+ wake_up_interruptible(&priv->host_sleep_q);
break;
case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 709ffca..61db8bc 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -38,7 +38,7 @@ int lbs_set_mac_address(struct net_device *dev, void *addr);
void lbs_set_multicast_list(struct net_device *dev);
int lbs_suspend(struct lbs_private *priv);
-void lbs_resume(struct lbs_private *priv);
+int lbs_resume(struct lbs_private *priv);
void lbs_queue_event(struct lbs_private *priv, u32 event);
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index a54880e..71c5ad4 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -75,6 +75,7 @@ struct lbs_private {
/* Deep sleep */
int is_deep_sleep;
+ int deep_sleep_required;
int is_auto_deep_sleep_enabled;
int wakeup_dev_required;
int is_activity_detected;
@@ -82,6 +83,11 @@ struct lbs_private {
wait_queue_head_t ds_awake_q;
struct timer_list auto_deepsleep_timer;
+ /* Host sleep*/
+ int is_host_sleep_configured;
+ int is_host_sleep_activated;
+ wait_queue_head_t host_sleep_q;
+
/* Hardware access */
void *card;
u8 fw_ready;
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 3804a58..0cf31bb 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -69,14 +69,11 @@ static void lbs_ethtool_get_wol(struct net_device *dev,
{
struct lbs_private *priv = dev->ml_priv;
- if (priv->wol_criteria == 0xffffffff) {
- /* Interface driver didn't configure wake */
- wol->supported = wol->wolopts = 0;
- return;
- }
-
wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
+ if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
+ return;
+
if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
wol->wolopts |= WAKE_UCAST;
if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
@@ -91,23 +88,22 @@ static int lbs_ethtool_set_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
struct lbs_private *priv = dev->ml_priv;
- uint32_t criteria = 0;
if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
return -EOPNOTSUPP;
+ priv->wol_criteria = 0;
if (wol->wolopts & WAKE_UCAST)
- criteria |= EHS_WAKE_ON_UNICAST_DATA;
+ priv->wol_criteria |= EHS_WAKE_ON_UNICAST_DATA;
if (wol->wolopts & WAKE_MCAST)
- criteria |= EHS_WAKE_ON_MULTICAST_DATA;
+ priv->wol_criteria |= EHS_WAKE_ON_MULTICAST_DATA;
if (wol->wolopts & WAKE_BCAST)
- criteria |= EHS_WAKE_ON_BROADCAST_DATA;
+ priv->wol_criteria |= EHS_WAKE_ON_BROADCAST_DATA;
if (wol->wolopts & WAKE_PHY)
- criteria |= EHS_WAKE_ON_MAC_EVENT;
+ priv->wol_criteria |= EHS_WAKE_ON_MAC_EVENT;
if (wol->wolopts == 0)
- criteria |= EHS_REMOVE_WAKEUP;
-
- return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
+ priv->wol_criteria |= EHS_REMOVE_WAKEUP;
+ return 0;
}
const struct ethtool_ops lbs_ethtool_ops = {
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 3809c0b..3bd5d3b 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -326,7 +326,7 @@ struct txpd {
u8 pktdelay_2ms;
/* reserved */
u8 reserved1;
-} __attribute__ ((packed));
+} __packed;
/* RxPD Descriptor */
struct rxpd {
@@ -339,8 +339,8 @@ struct rxpd {
u8 bss_type;
/* BSS number */
u8 bss_num;
- } __attribute__ ((packed)) bss;
- } __attribute__ ((packed)) u;
+ } __packed bss;
+ } __packed u;
/* SNR */
u8 snr;
@@ -366,14 +366,14 @@ struct rxpd {
/* Pkt Priority */
u8 priority;
u8 reserved[3];
-} __attribute__ ((packed));
+} __packed;
struct cmd_header {
__le16 command;
__le16 size;
__le16 seqnum;
__le16 result;
-} __attribute__ ((packed));
+} __packed;
/* Generic structure to hold all key types. */
struct enc_key {
@@ -387,7 +387,7 @@ struct enc_key {
struct lbs_offset_value {
u32 offset;
u32 value;
-} __attribute__ ((packed));
+} __packed;
/*
* Define data structure for CMD_GET_HW_SPEC
@@ -426,7 +426,7 @@ struct cmd_ds_get_hw_spec {
/*FW/HW capability */
__le32 fwcapinfo;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_subscribe_event {
struct cmd_header hdr;
@@ -440,7 +440,7 @@ struct cmd_ds_802_11_subscribe_event {
* bump this up a bit.
*/
uint8_t tlv[128];
-} __attribute__ ((packed));
+} __packed;
/*
* This scan handle Country Information IE(802.11d compliant)
@@ -452,7 +452,7 @@ struct cmd_ds_802_11_scan {
uint8_t bsstype;
uint8_t bssid[ETH_ALEN];
uint8_t tlvbuffer[0];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_scan_rsp {
struct cmd_header hdr;
@@ -460,7 +460,7 @@ struct cmd_ds_802_11_scan_rsp {
__le16 bssdescriptsize;
uint8_t nr_sets;
uint8_t bssdesc_and_tlvbuffer[0];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_get_log {
struct cmd_header hdr;
@@ -478,20 +478,20 @@ struct cmd_ds_802_11_get_log {
__le32 fcserror;
__le32 txframe;
__le32 wepundecryptable;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_mac_control {
struct cmd_header hdr;
__le16 action;
u16 reserved;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_mac_multicast_adr {
struct cmd_header hdr;
__le16 action;
__le16 nr_of_adrs;
u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_authenticate {
struct cmd_header hdr;
@@ -499,14 +499,14 @@ struct cmd_ds_802_11_authenticate {
u8 bssid[ETH_ALEN];
u8 authtype;
u8 reserved[10];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_deauthenticate {
struct cmd_header hdr;
u8 macaddr[ETH_ALEN];
__le16 reasoncode;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_associate {
struct cmd_header hdr;
@@ -517,7 +517,7 @@ struct cmd_ds_802_11_associate {
__le16 bcnperiod;
u8 dtimperiod;
u8 iebuf[512]; /* Enough for required and most optional IEs */
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_associate_response {
struct cmd_header hdr;
@@ -526,7 +526,7 @@ struct cmd_ds_802_11_associate_response {
__le16 statuscode;
__le16 aid;
u8 iebuf[512];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_set_wep {
struct cmd_header hdr;
@@ -540,7 +540,7 @@ struct cmd_ds_802_11_set_wep {
/* 40, 128bit or TXWEP */
uint8_t keytype[4];
uint8_t keymaterial[4][16];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_snmp_mib {
struct cmd_header hdr;
@@ -549,40 +549,40 @@ struct cmd_ds_802_11_snmp_mib {
__le16 oid;
__le16 bufsize;
u8 value[128];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_mac_reg_access {
__le16 action;
__le16 offset;
__le32 value;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_bbp_reg_access {
__le16 action;
__le16 offset;
u8 value;
u8 reserved[3];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_rf_reg_access {
__le16 action;
__le16 offset;
u8 value;
u8 reserved[3];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_radio_control {
struct cmd_header hdr;
__le16 action;
__le16 control;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_beacon_control {
__le16 action;
__le16 beacon_enable;
__le16 beacon_period;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_sleep_params {
struct cmd_header hdr;
@@ -607,7 +607,7 @@ struct cmd_ds_802_11_sleep_params {
/* reserved field, should be set to zero */
__le16 reserved;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_rf_channel {
struct cmd_header hdr;
@@ -617,7 +617,7 @@ struct cmd_ds_802_11_rf_channel {
__le16 rftype; /* unused */
__le16 reserved; /* unused */
u8 channellist[32]; /* unused */
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_rssi {
/* weighting factor */
@@ -626,21 +626,21 @@ struct cmd_ds_802_11_rssi {
__le16 reserved_0;
__le16 reserved_1;
__le16 reserved_2;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_rssi_rsp {
__le16 SNR;
__le16 noisefloor;
__le16 avgSNR;
__le16 avgnoisefloor;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_mac_address {
struct cmd_header hdr;
__le16 action;
u8 macadd[ETH_ALEN];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_rf_tx_power {
struct cmd_header hdr;
@@ -649,26 +649,26 @@ struct cmd_ds_802_11_rf_tx_power {
__le16 curlevel;
s8 maxlevel;
s8 minlevel;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_monitor_mode {
__le16 action;
__le16 mode;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_set_boot2_ver {
struct cmd_header hdr;
__le16 action;
__le16 version;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_fw_wake_method {
struct cmd_header hdr;
__le16 action;
__le16 method;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_ps_mode {
__le16 action;
@@ -676,7 +676,7 @@ struct cmd_ds_802_11_ps_mode {
__le16 multipledtim;
__le16 reserved;
__le16 locallisteninterval;
-} __attribute__ ((packed));
+} __packed;
struct cmd_confirm_sleep {
struct cmd_header hdr;
@@ -686,7 +686,7 @@ struct cmd_confirm_sleep {
__le16 multipledtim;
__le16 reserved;
__le16 locallisteninterval;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_data_rate {
struct cmd_header hdr;
@@ -694,14 +694,14 @@ struct cmd_ds_802_11_data_rate {
__le16 action;
__le16 reserved;
u8 rates[MAX_RATES];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_rate_adapt_rateset {
struct cmd_header hdr;
__le16 action;
__le16 enablehwauto;
__le16 bitmap;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_ad_hoc_start {
struct cmd_header hdr;
@@ -718,14 +718,14 @@ struct cmd_ds_802_11_ad_hoc_start {
__le16 capability;
u8 rates[MAX_RATES];
u8 tlv_memory_size_pad[100];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_ad_hoc_result {
struct cmd_header hdr;
u8 pad[3];
u8 bssid[ETH_ALEN];
-} __attribute__ ((packed));
+} __packed;
struct adhoc_bssdesc {
u8 bssid[ETH_ALEN];
@@ -746,7 +746,7 @@ struct adhoc_bssdesc {
* Adhoc join command and will cause a binary layout mismatch with
* the firmware
*/
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_ad_hoc_join {
struct cmd_header hdr;
@@ -754,18 +754,18 @@ struct cmd_ds_802_11_ad_hoc_join {
struct adhoc_bssdesc bss;
__le16 failtimeout; /* Reserved on v9 and later */
__le16 probedelay; /* Reserved on v9 and later */
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_ad_hoc_stop {
struct cmd_header hdr;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_enable_rsn {
struct cmd_header hdr;
__le16 action;
__le16 enable;
-} __attribute__ ((packed));
+} __packed;
struct MrvlIEtype_keyParamSet {
/* type ID */
@@ -785,7 +785,7 @@ struct MrvlIEtype_keyParamSet {
/* key material of size keylen */
u8 key[32];
-} __attribute__ ((packed));
+} __packed;
#define MAX_WOL_RULES 16
@@ -797,7 +797,7 @@ struct host_wol_rule {
__le16 reserve;
__be32 sig_mask;
__be32 signature;
-} __attribute__ ((packed));
+} __packed;
struct wol_config {
uint8_t action;
@@ -805,7 +805,7 @@ struct wol_config {
uint8_t no_rules_in_cmd;
uint8_t result;
struct host_wol_rule rule[MAX_WOL_RULES];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_host_sleep {
struct cmd_header hdr;
@@ -813,7 +813,7 @@ struct cmd_ds_host_sleep {
uint8_t gpio;
uint16_t gap;
struct wol_config wol_conf;
-} __attribute__ ((packed));
+} __packed;
@@ -822,7 +822,7 @@ struct cmd_ds_802_11_key_material {
__le16 action;
struct MrvlIEtype_keyParamSet keyParamSet[2];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_eeprom_access {
struct cmd_header hdr;
@@ -832,7 +832,7 @@ struct cmd_ds_802_11_eeprom_access {
/* firmware says it returns a maximum of 20 bytes */
#define LBS_EEPROM_READ_LEN 20
u8 value[LBS_EEPROM_READ_LEN];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_tpc_cfg {
struct cmd_header hdr;
@@ -843,7 +843,7 @@ struct cmd_ds_802_11_tpc_cfg {
int8_t P1;
int8_t P2;
uint8_t usesnr;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_pa_cfg {
@@ -854,14 +854,14 @@ struct cmd_ds_802_11_pa_cfg {
int8_t P0;
int8_t P1;
int8_t P2;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_led_ctrl {
__le16 action;
__le16 numled;
u8 data[256];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_802_11_afc {
__le16 afc_auto;
@@ -875,22 +875,22 @@ struct cmd_ds_802_11_afc {
__le16 carrier_offset; /* signed */
};
};
-} __attribute__ ((packed));
+} __packed;
struct cmd_tx_rate_query {
__le16 txrate;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_get_tsf {
__le64 tsfvalue;
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_bt_access {
__le16 action;
__le32 id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_fwt_access {
__le16 action;
@@ -910,7 +910,7 @@ struct cmd_ds_fwt_access {
__le32 snr;
__le32 references;
u8 prec[ETH_ALEN];
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_mesh_config {
struct cmd_header hdr;
@@ -920,14 +920,14 @@ struct cmd_ds_mesh_config {
__le16 type;
__le16 length;
u8 data[128]; /* last position reserved */
-} __attribute__ ((packed));
+} __packed;
struct cmd_ds_mesh_access {
struct cmd_header hdr;
__le16 action;
__le32 data[32]; /* last position reserved */
-} __attribute__ ((packed));
+} __packed;
/* Number of stats counters returned by the firmware */
#define MESH_STATS_NUM 8
@@ -957,6 +957,6 @@ struct cmd_ds_command {
struct cmd_ds_fwt_access fwt;
struct cmd_ds_802_11_beacon_control bcn_ctrl;
} params;
-} __attribute__ ((packed));
+} __packed;
#endif
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 64dd345..6e71346 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -1182,11 +1182,69 @@ static void if_sdio_remove(struct sdio_func *func)
lbs_deb_leave(LBS_DEB_SDIO);
}
+static int if_sdio_suspend(struct device *dev)
+{
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ int ret;
+ struct if_sdio_card *card = sdio_get_drvdata(func);
+
+ mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
+
+ lbs_pr_info("%s: suspend: PM flags = 0x%x\n",
+ sdio_func_id(func), flags);
+
+ /* If we aren't being asked to wake on anything, we should bail out
+ * and let the SD stack power down the card.
+ */
+ if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) {
+ lbs_pr_info("Suspend without wake params -- "
+ "powering down card.");
+ return -ENOSYS;
+ }
+
+ if (!(flags & MMC_PM_KEEP_POWER)) {
+ lbs_pr_err("%s: cannot remain alive while host is suspended\n",
+ sdio_func_id(func));
+ return -ENOSYS;
+ }
+
+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+ if (ret)
+ return ret;
+
+ ret = lbs_suspend(card->priv);
+ if (ret)
+ return ret;
+
+ return sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
+}
+
+static int if_sdio_resume(struct device *dev)
+{
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ struct if_sdio_card *card = sdio_get_drvdata(func);
+ int ret;
+
+ lbs_pr_info("%s: resume: we're back\n", sdio_func_id(func));
+
+ ret = lbs_resume(card->priv);
+
+ return ret;
+}
+
+static const struct dev_pm_ops if_sdio_pm_ops = {
+ .suspend = if_sdio_suspend,
+ .resume = if_sdio_resume,
+};
+
static struct sdio_driver if_sdio_driver = {
.name = "libertas_sdio",
.id_table = if_sdio_ids,
.probe = if_sdio_probe,
.remove = if_sdio_remove,
+ .drv = {
+ .pm = &if_sdio_pm_ops,
+ },
};
/*******************************************************************/
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index f41594c..3678e53 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -613,16 +613,14 @@ static void if_usb_receive_fwload(struct urb *urb)
return;
}
- syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
+ syncfwheader = kmemdup(skb->data + IPFIELD_ALIGN_OFFSET,
+ sizeof(struct fwsyncheader), GFP_ATOMIC);
if (!syncfwheader) {
lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
kfree_skb(skb);
return;
}
- memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
- sizeof(struct fwsyncheader));
-
if (!syncfwheader->cmd) {
lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
@@ -1043,6 +1041,12 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
if (priv->psstate != PS_STATE_FULL_POWER)
return -1;
+ if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
+ lbs_pr_info("Suspend attempt without "
+ "configuring wake params!\n");
+ return -ENOSYS;
+ }
+
ret = lbs_suspend(priv);
if (ret)
goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index d9b8ee1..abfecc4 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -625,16 +625,13 @@ static int lbs_thread(void *data)
return 0;
}
-static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy,
- struct cmd_header *cmd)
+static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
+ unsigned long dummy,
+ struct cmd_header *cmd)
{
lbs_deb_enter(LBS_DEB_FW);
-
- netif_device_detach(priv->dev);
- if (priv->mesh_dev)
- netif_device_detach(priv->mesh_dev);
-
- priv->fw_ready = 0;
+ priv->is_host_sleep_activated = 1;
+ wake_up_interruptible(&priv->host_sleep_q);
lbs_deb_leave(LBS_DEB_FW);
return 0;
}
@@ -646,39 +643,65 @@ int lbs_suspend(struct lbs_private *priv)
lbs_deb_enter(LBS_DEB_FW);
- if (priv->wol_criteria == 0xffffffff) {
- lbs_pr_info("Suspend attempt without configuring wake params!\n");
- return -EINVAL;
+ if (priv->is_deep_sleep) {
+ ret = lbs_set_deep_sleep(priv, 0);
+ if (ret) {
+ lbs_pr_err("deep sleep cancellation failed: %d\n", ret);
+ return ret;
+ }
+ priv->deep_sleep_required = 1;
}
memset(&cmd, 0, sizeof(cmd));
+ ret = lbs_host_sleep_cfg(priv, priv->wol_criteria,
+ (struct wol_config *)NULL);
+ if (ret) {
+ lbs_pr_info("Host sleep configuration failed: %d\n", ret);
+ return ret;
+ }
+ if (priv->psstate == PS_STATE_FULL_POWER) {
+ ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
+ sizeof(cmd), lbs_ret_host_sleep_activate, 0);
+ if (ret)
+ lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
+ }
- ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
- sizeof(cmd), lbs_suspend_callback, 0);
- if (ret)
- lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
+ if (!wait_event_interruptible_timeout(priv->host_sleep_q,
+ priv->is_host_sleep_activated, (10 * HZ))) {
+ lbs_pr_err("host_sleep_q: timer expired\n");
+ ret = -1;
+ }
+ netif_device_detach(priv->dev);
+ if (priv->mesh_dev)
+ netif_device_detach(priv->mesh_dev);
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
return ret;
}
EXPORT_SYMBOL_GPL(lbs_suspend);
-void lbs_resume(struct lbs_private *priv)
+int lbs_resume(struct lbs_private *priv)
{
- lbs_deb_enter(LBS_DEB_FW);
+ int ret;
+ uint32_t criteria = EHS_REMOVE_WAKEUP;
- priv->fw_ready = 1;
+ lbs_deb_enter(LBS_DEB_FW);
- /* Firmware doesn't seem to give us RX packets any more
- until we send it some command. Might as well update */
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- 0, 0, NULL);
+ ret = lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
netif_device_attach(priv->dev);
if (priv->mesh_dev)
netif_device_attach(priv->mesh_dev);
- lbs_deb_leave(LBS_DEB_FW);
+ if (priv->deep_sleep_required) {
+ priv->deep_sleep_required = 0;
+ ret = lbs_set_deep_sleep(priv, 1);
+ if (ret)
+ lbs_pr_err("deep sleep activation failed: %d\n", ret);
+ }
+
+ lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+ return ret;
}
EXPORT_SYMBOL_GPL(lbs_resume);
@@ -834,10 +857,13 @@ static int lbs_init_adapter(struct lbs_private *priv)
priv->psstate = PS_STATE_FULL_POWER;
priv->is_deep_sleep = 0;
priv->is_auto_deep_sleep_enabled = 0;
+ priv->deep_sleep_required = 0;
priv->wakeup_dev_required = 0;
init_waitqueue_head(&priv->ds_awake_q);
priv->authtype_auto = 1;
-
+ priv->is_host_sleep_configured = 0;
+ priv->is_host_sleep_activated = 0;
+ init_waitqueue_head(&priv->host_sleep_q);
mutex_init(&priv->lock);
setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
@@ -976,6 +1002,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
priv->wol_criteria = 0xffffffff;
priv->wol_gpio = 0xff;
+ priv->wol_gap = 20;
goto done;
@@ -1031,6 +1058,10 @@ void lbs_remove_card(struct lbs_private *priv)
wake_up_interruptible(&priv->ds_awake_q);
}
+ priv->is_host_sleep_configured = 0;
+ priv->is_host_sleep_activated = 0;
+ wake_up_interruptible(&priv->host_sleep_q);
+
/* Stop the thread servicing the interrupts */
priv->surpriseremoved = 1;
kthread_stop(priv->main_thread);
diff --git a/drivers/net/wireless/libertas/radiotap.h b/drivers/net/wireless/libertas/radiotap.h
index d16b264..b3c8ea6 100644
--- a/drivers/net/wireless/libertas/radiotap.h
+++ b/drivers/net/wireless/libertas/radiotap.h
@@ -6,7 +6,7 @@ struct tx_radiotap_hdr {
u8 txpower;
u8 rts_retries;
u8 data_retries;
-} __attribute__ ((packed));
+} __packed;
#define TX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_RATE) | \
@@ -34,7 +34,7 @@ struct rx_radiotap_hdr {
u8 flags;
u8 rate;
u8 antsignal;
-} __attribute__ ((packed));
+} __packed;
#define RX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 7a377f5..1c63f8c 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -15,7 +15,7 @@ struct eth803hdr {
u8 dest_addr[6];
u8 src_addr[6];
u16 h803_len;
-} __attribute__ ((packed));
+} __packed;
struct rfc1042hdr {
u8 llc_dsap;
@@ -23,17 +23,17 @@ struct rfc1042hdr {
u8 llc_ctrl;
u8 snap_oui[3];
u16 snap_type;
-} __attribute__ ((packed));
+} __packed;
struct rxpackethdr {
struct eth803hdr eth803_hdr;
struct rfc1042hdr rfc1042_hdr;
-} __attribute__ ((packed));
+} __packed;
struct rx80211packethdr {
struct rxpd rx_pd;
void *eth80211_hdr;
-} __attribute__ ((packed));
+} __packed;
static int process_rxed_802_11_packet(struct lbs_private *priv,
struct sk_buff *skb);
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 24cd54b..7d82f13b 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -666,7 +666,7 @@ void lbs_scan_worker(struct work_struct *work)
/**
* @brief Interpret a BSS scan response returned from the firmware
*
- * Parse the various fixed fields and IEs passed back for a a BSS probe
+ * Parse the various fixed fields and IEs passed back for a BSS probe
* response or beacon from the scan command. Record information as needed
* in the scan table struct bss_descriptor for that entry.
*
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index 3e72c86..462fbb4 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -11,7 +11,7 @@
struct ieee_ie_header {
u8 id;
u8 len;
-} __attribute__ ((packed));
+} __packed;
struct ieee_ie_cf_param_set {
struct ieee_ie_header header;
@@ -20,19 +20,19 @@ struct ieee_ie_cf_param_set {
u8 cfpperiod;
__le16 cfpmaxduration;
__le16 cfpdurationremaining;
-} __attribute__ ((packed));
+} __packed;
struct ieee_ie_ibss_param_set {
struct ieee_ie_header header;
__le16 atimwindow;
-} __attribute__ ((packed));
+} __packed;
union ieee_ss_param_set {
struct ieee_ie_cf_param_set cf;
struct ieee_ie_ibss_param_set ibss;
-} __attribute__ ((packed));
+} __packed;
struct ieee_ie_fh_param_set {
struct ieee_ie_header header;
@@ -41,18 +41,18 @@ struct ieee_ie_fh_param_set {
u8 hopset;
u8 hoppattern;
u8 hopindex;
-} __attribute__ ((packed));
+} __packed;
struct ieee_ie_ds_param_set {
struct ieee_ie_header header;
u8 channel;
-} __attribute__ ((packed));
+} __packed;
union ieee_phy_param_set {
struct ieee_ie_fh_param_set fh;
struct ieee_ie_ds_param_set ds;
-} __attribute__ ((packed));
+} __packed;
/** TLV type ID definition */
#define PROPRIETARY_TLV_BASE_ID 0x0100
@@ -100,28 +100,28 @@ union ieee_phy_param_set {
struct mrvl_ie_header {
__le16 type;
__le16 len;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_data {
struct mrvl_ie_header header;
u8 Data[1];
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_rates_param_set {
struct mrvl_ie_header header;
u8 rates[1];
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_ssid_param_set {
struct mrvl_ie_header header;
u8 ssid[1];
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_wildcard_ssid_param_set {
struct mrvl_ie_header header;
u8 MaxSsidlength;
u8 ssid[1];
-} __attribute__ ((packed));
+} __packed;
struct chanscanmode {
#ifdef __BIG_ENDIAN_BITFIELD
@@ -133,7 +133,7 @@ struct chanscanmode {
u8 disablechanfilt:1;
u8 reserved_2_7:6;
#endif
-} __attribute__ ((packed));
+} __packed;
struct chanscanparamset {
u8 radiotype;
@@ -141,12 +141,12 @@ struct chanscanparamset {
struct chanscanmode chanscanmode;
__le16 minscantime;
__le16 maxscantime;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_chanlist_param_set {
struct mrvl_ie_header header;
struct chanscanparamset chanscanparam[1];
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_cf_param_set {
struct mrvl_ie_header header;
@@ -154,86 +154,86 @@ struct mrvl_ie_cf_param_set {
u8 cfpperiod;
__le16 cfpmaxduration;
__le16 cfpdurationremaining;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_ds_param_set {
struct mrvl_ie_header header;
u8 channel;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_rsn_param_set {
struct mrvl_ie_header header;
u8 rsnie[1];
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_tsf_timestamp {
struct mrvl_ie_header header;
__le64 tsftable[1];
-} __attribute__ ((packed));
+} __packed;
/* v9 and later firmware only */
struct mrvl_ie_auth_type {
struct mrvl_ie_header header;
__le16 auth;
-} __attribute__ ((packed));
+} __packed;
/** Local Power capability */
struct mrvl_ie_power_capability {
struct mrvl_ie_header header;
s8 minpower;
s8 maxpower;
-} __attribute__ ((packed));
+} __packed;
/* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */
struct mrvl_ie_thresholds {
struct mrvl_ie_header header;
u8 value;
u8 freq;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_beacons_missed {
struct mrvl_ie_header header;
u8 beaconmissed;
u8 reserved;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_num_probes {
struct mrvl_ie_header header;
__le16 numprobes;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_bcast_probe {
struct mrvl_ie_header header;
__le16 bcastprobe;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_num_ssid_probe {
struct mrvl_ie_header header;
__le16 numssidprobe;
-} __attribute__ ((packed));
+} __packed;
struct led_pin {
u8 led;
u8 pin;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_ledgpio {
struct mrvl_ie_header header;
struct led_pin ledpin[1];
-} __attribute__ ((packed));
+} __packed;
struct led_bhv {
uint8_t firmwarestate;
uint8_t led;
uint8_t ledstate;
uint8_t ledarg;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_ie_ledbhv {
struct mrvl_ie_header header;
struct led_bhv ledbhv[1];
-} __attribute__ ((packed));
+} __packed;
/* Meant to be packed as the value member of a struct ieee80211_info_element.
* Note that the len member of the ieee80211_info_element varies depending on
@@ -248,12 +248,12 @@ struct mrvl_meshie_val {
uint8_t mesh_capability;
uint8_t mesh_id_len;
uint8_t mesh_id[IEEE80211_MAX_SSID_LEN];
-} __attribute__ ((packed));
+} __packed;
struct mrvl_meshie {
u8 id, len;
struct mrvl_meshie_val val;
-} __attribute__ ((packed));
+} __packed;
struct mrvl_mesh_defaults {
__le32 bootflag;
@@ -261,6 +261,6 @@ struct mrvl_mesh_defaults {
uint8_t reserved;
__le16 channel;
struct mrvl_meshie meshie;
-} __attribute__ ((packed));
+} __packed;
#endif