aboutsummaryrefslogtreecommitdiffstats
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/Kconfig39
-rw-r--r--drivers/net/wireless/libertas/Makefile15
-rw-r--r--drivers/net/wireless/libertas/README26
-rw-r--r--drivers/net/wireless/libertas/cfg.c198
-rw-r--r--drivers/net/wireless/libertas/cfg.h16
-rw-r--r--drivers/net/wireless/libertas/cmd.c106
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c12
-rw-r--r--drivers/net/wireless/libertas/decl.h3
-rw-r--r--drivers/net/wireless/libertas/defs.h2
-rw-r--r--drivers/net/wireless/libertas/dev.h19
-rw-r--r--drivers/net/wireless/libertas/host.h1
-rw-r--r--drivers/net/wireless/libertas/if_cs.c3
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c56
-rw-r--r--drivers/net/wireless/libertas/if_sdio.h3
-rw-r--r--drivers/net/wireless/libertas/if_spi.c3
-rw-r--r--drivers/net/wireless/libertas/if_usb.c3
-rw-r--r--drivers/net/wireless/libertas/main.c171
-rw-r--r--drivers/net/wireless/libertas/wext.c54
18 files changed, 689 insertions, 41 deletions
diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig
new file mode 100644
index 000000000000..8f8d75b61ea9
--- /dev/null
+++ b/drivers/net/wireless/libertas/Kconfig
@@ -0,0 +1,39 @@
1config LIBERTAS
2 tristate "Marvell 8xxx Libertas WLAN driver support"
3 depends on WLAN_80211 && CFG80211
4 select WIRELESS_EXT
5 select WEXT_SPY
6 select LIB80211
7 select FW_LOADER
8 ---help---
9 A library for Marvell Libertas 8xxx devices.
10
11config LIBERTAS_USB
12 tristate "Marvell Libertas 8388 USB 802.11b/g cards"
13 depends on LIBERTAS && USB
14 ---help---
15 A driver for Marvell Libertas 8388 USB devices.
16
17config LIBERTAS_CS
18 tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
19 depends on LIBERTAS && PCMCIA
20 ---help---
21 A driver for Marvell Libertas 8385 CompactFlash devices.
22
23config LIBERTAS_SDIO
24 tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
25 depends on LIBERTAS && MMC
26 ---help---
27 A driver for Marvell Libertas 8385/8686/8688 SDIO devices.
28
29config LIBERTAS_SPI
30 tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
31 depends on LIBERTAS && SPI
32 ---help---
33 A driver for Marvell Libertas 8686 SPI devices.
34
35config LIBERTAS_DEBUG
36 bool "Enable full debugging output in the Libertas module."
37 depends on LIBERTAS
38 ---help---
39 Debugging support.
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 0b6918584503..e5584dd1c79a 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -1,5 +1,16 @@
1libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \ 1libertas-y += 11d.o
2 debugfs.o persistcfg.o ethtool.o assoc.o 2libertas-y += assoc.o
3libertas-y += cfg.o
4libertas-y += cmd.o
5libertas-y += cmdresp.o
6libertas-y += debugfs.o
7libertas-y += ethtool.o
8libertas-y += main.o
9libertas-y += persistcfg.o
10libertas-y += rx.o
11libertas-y += scan.o
12libertas-y += tx.o
13libertas-y += wext.o
3 14
4usb8xxx-objs += if_usb.o 15usb8xxx-objs += if_usb.o
5libertas_cs-objs += if_cs.o 16libertas_cs-objs += if_cs.o
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
index ab6a2d518af0..2726c044430f 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -1,5 +1,5 @@
1================================================================================ 1================================================================================
2 README for USB8388 2 README for Libertas
3 3
4 (c) Copyright © 2003-2006, Marvell International Ltd. 4 (c) Copyright © 2003-2006, Marvell International Ltd.
5 All Rights Reserved 5 All Rights Reserved
@@ -226,4 +226,28 @@ setuserscan
226 All entries in the scan table (not just the new scan data when keep=1) 226 All entries in the scan table (not just the new scan data when keep=1)
227 will be displayed upon completion by use of the getscantable ioctl. 227 will be displayed upon completion by use of the getscantable ioctl.
228 228
229========================
230IWCONFIG COMMANDS
231========================
232power period
233
234 This command is used to configure the station in deep sleep mode /
235 auto deep sleep mode.
236
237 The timer is implemented to monitor the activities (command, event,
238 etc.). When an activity is detected station will exit from deep
239 sleep mode automatically and restart the timer. At timer expiry
240 (no activity for defined time period) the deep sleep mode is entered
241 automatically.
242
243 Note: this command is for SDIO interface only.
244
245 Usage:
246 To enable deep sleep mode do:
247 iwconfig wlan0 power period 0
248 To enable auto deep sleep mode with idle time period 5 seconds do:
249 iwconfig wlan0 power period 5
250 To disable deep sleep/auto deep sleep mode do:
251 iwconfig wlan0 power period -1
252
229============================================================================== 253==============================================================================
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
new file mode 100644
index 000000000000..4396dccd12ac
--- /dev/null
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -0,0 +1,198 @@
1/*
2 * Implement cfg80211 ("iw") support.
3 *
4 * Copyright (C) 2009 M&N Solutions GmbH, 61191 Rosbach, Germany
5 * Holger Schurig <hs4233@mail.mn-solutions.de>
6 *
7 */
8
9#include <net/cfg80211.h>
10
11#include "cfg.h"
12#include "cmd.h"
13
14
15#define CHAN2G(_channel, _freq, _flags) { \
16 .band = IEEE80211_BAND_2GHZ, \
17 .center_freq = (_freq), \
18 .hw_value = (_channel), \
19 .flags = (_flags), \
20 .max_antenna_gain = 0, \
21 .max_power = 30, \
22}
23
24static struct ieee80211_channel lbs_2ghz_channels[] = {
25 CHAN2G(1, 2412, 0),
26 CHAN2G(2, 2417, 0),
27 CHAN2G(3, 2422, 0),
28 CHAN2G(4, 2427, 0),
29 CHAN2G(5, 2432, 0),
30 CHAN2G(6, 2437, 0),
31 CHAN2G(7, 2442, 0),
32 CHAN2G(8, 2447, 0),
33 CHAN2G(9, 2452, 0),
34 CHAN2G(10, 2457, 0),
35 CHAN2G(11, 2462, 0),
36 CHAN2G(12, 2467, 0),
37 CHAN2G(13, 2472, 0),
38 CHAN2G(14, 2484, 0),
39};
40
41#define RATETAB_ENT(_rate, _rateid, _flags) { \
42 .bitrate = (_rate), \
43 .hw_value = (_rateid), \
44 .flags = (_flags), \
45}
46
47
48static struct ieee80211_rate lbs_rates[] = {
49 RATETAB_ENT(10, 0x1, 0),
50 RATETAB_ENT(20, 0x2, 0),
51 RATETAB_ENT(55, 0x4, 0),
52 RATETAB_ENT(110, 0x8, 0),
53 RATETAB_ENT(60, 0x10, 0),
54 RATETAB_ENT(90, 0x20, 0),
55 RATETAB_ENT(120, 0x40, 0),
56 RATETAB_ENT(180, 0x80, 0),
57 RATETAB_ENT(240, 0x100, 0),
58 RATETAB_ENT(360, 0x200, 0),
59 RATETAB_ENT(480, 0x400, 0),
60 RATETAB_ENT(540, 0x800, 0),
61};
62
63static struct ieee80211_supported_band lbs_band_2ghz = {
64 .channels = lbs_2ghz_channels,
65 .n_channels = ARRAY_SIZE(lbs_2ghz_channels),
66 .bitrates = lbs_rates,
67 .n_bitrates = ARRAY_SIZE(lbs_rates),
68};
69
70
71static const u32 cipher_suites[] = {
72 WLAN_CIPHER_SUITE_WEP40,
73 WLAN_CIPHER_SUITE_WEP104,
74 WLAN_CIPHER_SUITE_TKIP,
75 WLAN_CIPHER_SUITE_CCMP,
76};
77
78
79
80static int lbs_cfg_set_channel(struct wiphy *wiphy,
81 struct ieee80211_channel *chan,
82 enum nl80211_channel_type channel_type)
83{
84 struct lbs_private *priv = wiphy_priv(wiphy);
85 int ret = -ENOTSUPP;
86
87 lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type);
88
89 if (channel_type != NL80211_CHAN_NO_HT)
90 goto out;
91
92 ret = lbs_set_channel(priv, chan->hw_value);
93
94 out:
95 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
96 return ret;
97}
98
99
100
101
102static struct cfg80211_ops lbs_cfg80211_ops = {
103 .set_channel = lbs_cfg_set_channel,
104};
105
106
107/*
108 * At this time lbs_private *priv doesn't even exist, so we just allocate
109 * memory and don't initialize the wiphy further. This is postponed until we
110 * can talk to the firmware and happens at registration time in
111 * lbs_cfg_wiphy_register().
112 */
113struct wireless_dev *lbs_cfg_alloc(struct device *dev)
114{
115 int ret = 0;
116 struct wireless_dev *wdev;
117
118 lbs_deb_enter(LBS_DEB_CFG80211);
119
120 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
121 if (!wdev) {
122 dev_err(dev, "cannot allocate wireless device\n");
123 return ERR_PTR(-ENOMEM);
124 }
125
126 wdev->wiphy = wiphy_new(&lbs_cfg80211_ops, sizeof(struct lbs_private));
127 if (!wdev->wiphy) {
128 dev_err(dev, "cannot allocate wiphy\n");
129 ret = -ENOMEM;
130 goto err_wiphy_new;
131 }
132
133 lbs_deb_leave(LBS_DEB_CFG80211);
134 return wdev;
135
136 err_wiphy_new:
137 kfree(wdev);
138 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
139 return ERR_PTR(ret);
140}
141
142
143/*
144 * This function get's called after lbs_setup_firmware() determined the
145 * firmware capabities. So we can setup the wiphy according to our
146 * hardware/firmware.
147 */
148int lbs_cfg_register(struct lbs_private *priv)
149{
150 struct wireless_dev *wdev = priv->wdev;
151 int ret;
152
153 lbs_deb_enter(LBS_DEB_CFG80211);
154
155 wdev->wiphy->max_scan_ssids = 1;
156 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
157
158 /* TODO: BIT(NL80211_IFTYPE_ADHOC); */
159 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
160
161 /* TODO: honor priv->regioncode */
162 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
163
164 /*
165 * We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have
166 * never seen a firmware without WPA
167 */
168 wdev->wiphy->cipher_suites = cipher_suites;
169 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
170
171 ret = wiphy_register(wdev->wiphy);
172 if (ret < 0)
173 lbs_pr_err("cannot register wiphy device\n");
174
175 ret = register_netdev(priv->dev);
176 if (ret)
177 lbs_pr_err("cannot register network device\n");
178
179 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
180 return ret;
181}
182
183
184void lbs_cfg_free(struct lbs_private *priv)
185{
186 struct wireless_dev *wdev = priv->wdev;
187
188 lbs_deb_enter(LBS_DEB_CFG80211);
189
190 if (!wdev)
191 return;
192
193 if (wdev->wiphy) {
194 wiphy_unregister(wdev->wiphy);
195 wiphy_free(wdev->wiphy);
196 }
197 kfree(wdev);
198}
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
new file mode 100644
index 000000000000..e09a193a34d6
--- /dev/null
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -0,0 +1,16 @@
1#ifndef __LBS_CFG80211_H__
2#define __LBS_CFG80211_H__
3
4#include "dev.h"
5
6struct wireless_dev *lbs_cfg_alloc(struct device *dev);
7int lbs_cfg_register(struct lbs_private *priv);
8void lbs_cfg_free(struct lbs_private *priv);
9
10int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
11 u8 ssid_len);
12int lbs_scan_networks(struct lbs_private *priv, int full_scan);
13void lbs_cfg_scan_worker(struct work_struct *work);
14
15
16#endif
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 685098148e10..0fb312576b8d 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -17,7 +17,6 @@
17 17
18static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); 18static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
19 19
20
21/** 20/**
22 * @brief Simple callback that copies response back into command 21 * @brief Simple callback that copies response back into command
23 * 22 *
@@ -76,6 +75,30 @@ static u8 is_command_allowed_in_ps(u16 cmd)
76} 75}
77 76
78/** 77/**
78 * @brief This function checks if the command is allowed.
79 *
80 * @param priv A pointer to lbs_private structure
81 * @return allowed or not allowed.
82 */
83
84static int lbs_is_cmd_allowed(struct lbs_private *priv)
85{
86 int ret = 1;
87
88 lbs_deb_enter(LBS_DEB_CMD);
89
90 if (!priv->is_auto_deep_sleep_enabled) {
91 if (priv->is_deep_sleep) {
92 lbs_deb_cmd("command not allowed in deep sleep\n");
93 ret = 0;
94 }
95 }
96
97 lbs_deb_leave(LBS_DEB_CMD);
98 return ret;
99}
100
101/**
79 * @brief Updates the hardware details like MAC address and regulatory region 102 * @brief Updates the hardware details like MAC address and regulatory region
80 * 103 *
81 * @param priv A pointer to struct lbs_private structure 104 * @param priv A pointer to struct lbs_private structure
@@ -319,6 +342,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
319 return 0; 342 return 0;
320} 343}
321 344
345static int lbs_wait_for_ds_awake(struct lbs_private *priv)
346{
347 int ret = 0;
348
349 lbs_deb_enter(LBS_DEB_CMD);
350
351 if (priv->is_deep_sleep) {
352 if (!wait_event_interruptible_timeout(priv->ds_awake_q,
353 !priv->is_deep_sleep, (10 * HZ))) {
354 lbs_pr_err("ds_awake_q: timer expired\n");
355 ret = -1;
356 }
357 }
358
359 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
360 return ret;
361}
362
363int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
364{
365 int ret = 0;
366
367 lbs_deb_enter(LBS_DEB_CMD);
368
369 if (deep_sleep) {
370 if (priv->is_deep_sleep != 1) {
371 lbs_deb_cmd("deep sleep: sleep\n");
372 BUG_ON(!priv->enter_deep_sleep);
373 ret = priv->enter_deep_sleep(priv);
374 if (!ret) {
375 netif_stop_queue(priv->dev);
376 netif_carrier_off(priv->dev);
377 }
378 } else {
379 lbs_pr_err("deep sleep: already enabled\n");
380 }
381 } else {
382 if (priv->is_deep_sleep) {
383 lbs_deb_cmd("deep sleep: wakeup\n");
384 BUG_ON(!priv->exit_deep_sleep);
385 ret = priv->exit_deep_sleep(priv);
386 if (!ret) {
387 ret = lbs_wait_for_ds_awake(priv);
388 if (ret)
389 lbs_pr_err("deep sleep: wakeup"
390 "failed\n");
391 }
392 }
393 }
394
395 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
396 return ret;
397}
398
322int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, 399int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
323 struct assoc_request *assoc) 400 struct assoc_request *assoc)
324{ 401{
@@ -1242,8 +1319,17 @@ static void lbs_submit_command(struct lbs_private *priv,
1242 timeo = HZ/4; 1319 timeo = HZ/4;
1243 } 1320 }
1244 1321
1245 /* Setup the timer after transmit command */ 1322 if (command == CMD_802_11_DEEP_SLEEP) {
1246 mod_timer(&priv->command_timer, jiffies + timeo); 1323 if (priv->is_auto_deep_sleep_enabled) {
1324 priv->wakeup_dev_required = 1;
1325 priv->dnld_sent = 0;
1326 }
1327 priv->is_deep_sleep = 1;
1328 lbs_complete_command(priv, cmdnode, 0);
1329 } else {
1330 /* Setup the timer after transmit command */
1331 mod_timer(&priv->command_timer, jiffies + timeo);
1332 }
1247 1333
1248 lbs_deb_leave(LBS_DEB_HOST); 1334 lbs_deb_leave(LBS_DEB_HOST);
1249} 1335}
@@ -1390,6 +1476,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1390 goto done; 1476 goto done;
1391 } 1477 }
1392 1478
1479 if (!lbs_is_cmd_allowed(priv)) {
1480 ret = -EBUSY;
1481 goto done;
1482 }
1483
1393 cmdnode = lbs_get_cmd_ctrl_node(priv); 1484 cmdnode = lbs_get_cmd_ctrl_node(priv);
1394 1485
1395 if (cmdnode == NULL) { 1486 if (cmdnode == NULL) {
@@ -1505,6 +1596,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1505 case CMD_802_11_BEACON_CTRL: 1596 case CMD_802_11_BEACON_CTRL:
1506 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); 1597 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
1507 break; 1598 break;
1599 case CMD_802_11_DEEP_SLEEP:
1600 cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
1601 cmdptr->size = cpu_to_le16(S_DS_GEN);
1602 break;
1508 default: 1603 default:
1509 lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); 1604 lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1510 ret = -1; 1605 ret = -1;
@@ -2038,6 +2133,11 @@ static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
2038 goto done; 2133 goto done;
2039 } 2134 }
2040 2135
2136 if (!lbs_is_cmd_allowed(priv)) {
2137 cmdnode = ERR_PTR(-EBUSY);
2138 goto done;
2139 }
2140
2041 cmdnode = lbs_get_cmd_ctrl_node(priv); 2141 cmdnode = lbs_get_cmd_ctrl_node(priv);
2042 if (cmdnode == NULL) { 2142 if (cmdnode == NULL) {
2043 lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); 2143 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index c42d3faa2660..47d2b1909d69 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -504,9 +504,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
504 504
505 case MACREG_INT_CODE_HOST_AWAKE: 505 case MACREG_INT_CODE_HOST_AWAKE:
506 lbs_deb_cmd("EVENT: host awake\n"); 506 lbs_deb_cmd("EVENT: host awake\n");
507 if (priv->reset_deep_sleep_wakeup)
508 priv->reset_deep_sleep_wakeup(priv);
509 priv->is_deep_sleep = 0;
507 lbs_send_confirmwake(priv); 510 lbs_send_confirmwake(priv);
508 break; 511 break;
509 512
513 case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
514 if (priv->reset_deep_sleep_wakeup)
515 priv->reset_deep_sleep_wakeup(priv);
516 lbs_deb_cmd("EVENT: ds awake\n");
517 priv->is_deep_sleep = 0;
518 priv->wakeup_dev_required = 0;
519 wake_up_interruptible(&priv->ds_awake_q);
520 break;
521
510 case MACREG_INT_CODE_PS_AWAKE: 522 case MACREG_INT_CODE_PS_AWAKE:
511 lbs_deb_cmd("EVENT: ps awake\n"); 523 lbs_deb_cmd("EVENT: ps awake\n");
512 /* handle unexpected PS AWAKE event */ 524 /* handle unexpected PS AWAKE event */
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 8b15380ae6e1..fb91c3639fc1 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -33,6 +33,9 @@ int lbs_execute_next_command(struct lbs_private *priv);
33int lbs_process_event(struct lbs_private *priv, u32 event); 33int lbs_process_event(struct lbs_private *priv, u32 event);
34void lbs_queue_event(struct lbs_private *priv, u32 event); 34void lbs_queue_event(struct lbs_private *priv, u32 event);
35void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); 35void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
36int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
37int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
38int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
36 39
37u32 lbs_fw_index_to_data_rate(u8 index); 40u32 lbs_fw_index_to_data_rate(u8 index);
38u8 lbs_data_rate_to_fw_index(u32 rate); 41u8 lbs_data_rate_to_fw_index(u32 rate);
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 72f3479a4d70..1cf5d5985dac 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -42,6 +42,7 @@
42#define LBS_DEB_SDIO 0x00400000 42#define LBS_DEB_SDIO 0x00400000
43#define LBS_DEB_SYSFS 0x00800000 43#define LBS_DEB_SYSFS 0x00800000
44#define LBS_DEB_SPI 0x01000000 44#define LBS_DEB_SPI 0x01000000
45#define LBS_DEB_CFG80211 0x02000000
45 46
46extern unsigned int lbs_debug; 47extern unsigned int lbs_debug;
47 48
@@ -86,6 +87,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
86#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) 87#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
87#define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) 88#define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
88#define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) 89#define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
90#define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)
89 91
90#define lbs_pr_info(format, args...) \ 92#define lbs_pr_info(format, args...) \
91 printk(KERN_INFO DRV_NAME": " format, ## args) 93 printk(KERN_INFO DRV_NAME": " format, ## args)
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index d3b69a4b4b5e..8abb28af5afa 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -100,6 +100,7 @@ struct lbs_mesh_stats {
100 100
101/** Private structure for the MV device */ 101/** Private structure for the MV device */
102struct lbs_private { 102struct lbs_private {
103 struct wireless_dev *wdev;
103 int mesh_open; 104 int mesh_open;
104 int mesh_fw_ver; 105 int mesh_fw_ver;
105 int infra_open; 106 int infra_open;
@@ -129,6 +130,20 @@ struct lbs_private {
129 u32 bbp_offset; 130 u32 bbp_offset;
130 u32 rf_offset; 131 u32 rf_offset;
131 132
133 /** Deep sleep flag */
134 int is_deep_sleep;
135 /** Auto deep sleep enabled flag */
136 int is_auto_deep_sleep_enabled;
137 /** Device wakeup required flag */
138 int wakeup_dev_required;
139 /** Auto deep sleep flag*/
140 int is_activity_detected;
141 /** Auto deep sleep timeout (in miliseconds) */
142 int auto_deep_sleep_timeout;
143
144 /** Deep sleep wait queue */
145 wait_queue_head_t ds_awake_q;
146
132 /* Download sent: 147 /* Download sent:
133 bit0 1/0=data_sent/data_tx_done, 148 bit0 1/0=data_sent/data_tx_done,
134 bit1 1/0=cmd_sent/cmd_tx_done, 149 bit1 1/0=cmd_sent/cmd_tx_done,
@@ -154,6 +169,9 @@ struct lbs_private {
154 /** Hardware access */ 169 /** Hardware access */
155 int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); 170 int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
156 void (*reset_card) (struct lbs_private *priv); 171 void (*reset_card) (struct lbs_private *priv);
172 int (*enter_deep_sleep) (struct lbs_private *priv);
173 int (*exit_deep_sleep) (struct lbs_private *priv);
174 int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
157 175
158 /* Wake On LAN */ 176 /* Wake On LAN */
159 uint32_t wol_criteria; 177 uint32_t wol_criteria;
@@ -204,6 +222,7 @@ struct lbs_private {
204 222
205 /** Timers */ 223 /** Timers */
206 struct timer_list command_timer; 224 struct timer_list command_timer;
225 struct timer_list auto_deepsleep_timer;
207 int nr_retries; 226 int nr_retries;
208 int cmd_timed_out; 227 int cmd_timed_out;
209 228
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index fe8f0cb737bc..c055daabea13 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -57,6 +57,7 @@
57#define CMD_802_11_ENABLE_RSN 0x002f 57#define CMD_802_11_ENABLE_RSN 0x002f
58#define CMD_802_11_SET_AFC 0x003c 58#define CMD_802_11_SET_AFC 0x003c
59#define CMD_802_11_GET_AFC 0x003d 59#define CMD_802_11_GET_AFC 0x003d
60#define CMD_802_11_DEEP_SLEEP 0x003e
60#define CMD_802_11_AD_HOC_STOP 0x0040 61#define CMD_802_11_AD_HOC_STOP 0x0040
61#define CMD_802_11_HOST_SLEEP_CFG 0x0043 62#define CMD_802_11_HOST_SLEEP_CFG 0x0043
62#define CMD_802_11_WAKEUP_CONFIRM 0x0044 63#define CMD_802_11_WAKEUP_CONFIRM 0x0044
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 62381768f2d5..465742f19ecb 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -946,6 +946,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
946 card->priv = priv; 946 card->priv = priv;
947 priv->card = card; 947 priv->card = card;
948 priv->hw_host_to_card = if_cs_host_to_card; 948 priv->hw_host_to_card = if_cs_host_to_card;
949 priv->enter_deep_sleep = NULL;
950 priv->exit_deep_sleep = NULL;
951 priv->reset_deep_sleep_wakeup = NULL;
949 priv->fw_ready = 1; 952 priv->fw_ready = 1;
950 953
951 /* Now actually get the IRQ */ 954 /* Now actually get the IRQ */
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 485a8d406525..9716728a33cb 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -831,6 +831,58 @@ out:
831 return ret; 831 return ret;
832} 832}
833 833
834static int if_sdio_enter_deep_sleep(struct lbs_private *priv)
835{
836 int ret = -1;
837 struct cmd_header cmd;
838
839 memset(&cmd, 0, sizeof(cmd));
840
841 lbs_deb_sdio("send DEEP_SLEEP command\n");
842 ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd),
843 lbs_cmd_copyback, (unsigned long) &cmd);
844 if (ret)
845 lbs_pr_err("DEEP_SLEEP cmd failed\n");
846
847 mdelay(200);
848 return ret;
849}
850
851static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
852{
853 struct if_sdio_card *card = priv->card;
854 int ret = -1;
855
856 lbs_deb_enter(LBS_DEB_SDIO);
857 sdio_claim_host(card->func);
858
859 sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
860 if (ret)
861 lbs_pr_err("sdio_writeb failed!\n");
862
863 sdio_release_host(card->func);
864 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
865 return ret;
866}
867
868static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
869{
870 struct if_sdio_card *card = priv->card;
871 int ret = -1;
872
873 lbs_deb_enter(LBS_DEB_SDIO);
874 sdio_claim_host(card->func);
875
876 sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret);
877 if (ret)
878 lbs_pr_err("sdio_writeb failed!\n");
879
880 sdio_release_host(card->func);
881 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
882 return ret;
883
884}
885
834/*******************************************************************/ 886/*******************************************************************/
835/* SDIO callbacks */ 887/* SDIO callbacks */
836/*******************************************************************/ 888/*******************************************************************/
@@ -859,6 +911,7 @@ static void if_sdio_interrupt(struct sdio_func *func)
859 * Ignore the define name, this really means the card has 911 * Ignore the define name, this really means the card has
860 * successfully received the command. 912 * successfully received the command.
861 */ 913 */
914 card->priv->is_activity_detected = 1;
862 if (cause & IF_SDIO_H_INT_DNLD) 915 if (cause & IF_SDIO_H_INT_DNLD)
863 lbs_host_to_card_done(card->priv); 916 lbs_host_to_card_done(card->priv);
864 917
@@ -998,6 +1051,9 @@ static int if_sdio_probe(struct sdio_func *func,
998 1051
999 priv->card = card; 1052 priv->card = card;
1000 priv->hw_host_to_card = if_sdio_host_to_card; 1053 priv->hw_host_to_card = if_sdio_host_to_card;
1054 priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
1055 priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
1056 priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
1001 1057
1002 priv->fw_ready = 1; 1058 priv->fw_ready = 1;
1003 1059
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
index 60c9b2fcef03..12179c1dc9c9 100644
--- a/drivers/net/wireless/libertas/if_sdio.h
+++ b/drivers/net/wireless/libertas/if_sdio.h
@@ -51,5 +51,6 @@
51#define IF_SDIO_EVENT 0x80fc 51#define IF_SDIO_EVENT 0x80fc
52 52
53#define IF_SDIO_BLOCK_SIZE 256 53#define IF_SDIO_BLOCK_SIZE 256
54 54#define CONFIGURATION_REG 0x03
55#define HOST_POWER_UP (0x1U << 1)
55#endif 56#endif
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index cb8be8d7abc1..06df2e174b50 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -1117,6 +1117,9 @@ static int __devinit if_spi_probe(struct spi_device *spi)
1117 card->priv = priv; 1117 card->priv = priv;
1118 priv->card = card; 1118 priv->card = card;
1119 priv->hw_host_to_card = if_spi_host_to_card; 1119 priv->hw_host_to_card = if_spi_host_to_card;
1120 priv->enter_deep_sleep = NULL;
1121 priv->exit_deep_sleep = NULL;
1122 priv->reset_deep_sleep_wakeup = NULL;
1120 priv->fw_ready = 1; 1123 priv->fw_ready = 1;
1121 1124
1122 /* Initialize interrupt handling stuff. */ 1125 /* Initialize interrupt handling stuff. */
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 92bc8c5f1ca2..a8262dea9b1f 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -300,6 +300,9 @@ static int if_usb_probe(struct usb_interface *intf,
300 cardp->priv->fw_ready = 1; 300 cardp->priv->fw_ready = 1;
301 301
302 priv->hw_host_to_card = if_usb_host_to_card; 302 priv->hw_host_to_card = if_usb_host_to_card;
303 priv->enter_deep_sleep = NULL;
304 priv->exit_deep_sleep = NULL;
305 priv->reset_deep_sleep_wakeup = NULL;
303#ifdef CONFIG_OLPC 306#ifdef CONFIG_OLPC
304 if (machine_is_olpc()) 307 if (machine_is_olpc())
305 priv->reset_card = if_usb_reset_olpc_card; 308 priv->reset_card = if_usb_reset_olpc_card;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 87b4e497faa2..87bfd17b9c8c 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -14,11 +14,13 @@
14#include <linux/stddef.h> 14#include <linux/stddef.h>
15#include <linux/ieee80211.h> 15#include <linux/ieee80211.h>
16#include <net/iw_handler.h> 16#include <net/iw_handler.h>
17#include <net/cfg80211.h>
17 18
18#include "host.h" 19#include "host.h"
19#include "decl.h" 20#include "decl.h"
20#include "dev.h" 21#include "dev.h"
21#include "wext.h" 22#include "wext.h"
23#include "cfg.h"
22#include "debugfs.h" 24#include "debugfs.h"
23#include "scan.h" 25#include "scan.h"
24#include "assoc.h" 26#include "assoc.h"
@@ -574,8 +576,10 @@ void lbs_host_to_card_done(struct lbs_private *priv)
574 priv->dnld_sent = DNLD_RES_RECEIVED; 576 priv->dnld_sent = DNLD_RES_RECEIVED;
575 577
576 /* Wake main thread if commands are pending */ 578 /* Wake main thread if commands are pending */
577 if (!priv->cur_cmd || priv->tx_pending_len > 0) 579 if (!priv->cur_cmd || priv->tx_pending_len > 0) {
578 wake_up_interruptible(&priv->waitq); 580 if (!priv->wakeup_dev_required)
581 wake_up_interruptible(&priv->waitq);
582 }
579 583
580 spin_unlock_irqrestore(&priv->driver_lock, flags); 584 spin_unlock_irqrestore(&priv->driver_lock, flags);
581 lbs_deb_leave(LBS_DEB_THREAD); 585 lbs_deb_leave(LBS_DEB_THREAD);
@@ -770,7 +774,8 @@ static int lbs_thread(void *data)
770 shouldsleep = 0; /* We have a command response */ 774 shouldsleep = 0; /* We have a command response */
771 else if (priv->cur_cmd) 775 else if (priv->cur_cmd)
772 shouldsleep = 1; /* Can't send a command; one already running */ 776 shouldsleep = 1; /* Can't send a command; one already running */
773 else if (!list_empty(&priv->cmdpendingq)) 777 else if (!list_empty(&priv->cmdpendingq) &&
778 !(priv->wakeup_dev_required))
774 shouldsleep = 0; /* We have a command to send */ 779 shouldsleep = 0; /* We have a command to send */
775 else if (__kfifo_len(priv->event_fifo)) 780 else if (__kfifo_len(priv->event_fifo))
776 shouldsleep = 0; /* We have an event to process */ 781 shouldsleep = 0; /* We have an event to process */
@@ -822,6 +827,26 @@ static int lbs_thread(void *data)
822 } 827 }
823 spin_unlock_irq(&priv->driver_lock); 828 spin_unlock_irq(&priv->driver_lock);
824 829
830 /* Process hardware events, e.g. card removed, link lost */
831 spin_lock_irq(&priv->driver_lock);
832 while (__kfifo_len(priv->event_fifo)) {
833 u32 event;
834 __kfifo_get(priv->event_fifo, (unsigned char *) &event,
835 sizeof(event));
836 spin_unlock_irq(&priv->driver_lock);
837 lbs_process_event(priv, event);
838 spin_lock_irq(&priv->driver_lock);
839 }
840 spin_unlock_irq(&priv->driver_lock);
841
842 if (priv->wakeup_dev_required) {
843 lbs_deb_thread("Waking up device...\n");
844 /* Wake up device */
845 if (priv->exit_deep_sleep(priv))
846 lbs_deb_thread("Wakeup device failed\n");
847 continue;
848 }
849
825 /* command timeout stuff */ 850 /* command timeout stuff */
826 if (priv->cmd_timed_out && priv->cur_cmd) { 851 if (priv->cmd_timed_out && priv->cur_cmd) {
827 struct cmd_ctrl_node *cmdnode = priv->cur_cmd; 852 struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
@@ -849,18 +874,7 @@ static int lbs_thread(void *data)
849 } 874 }
850 priv->cmd_timed_out = 0; 875 priv->cmd_timed_out = 0;
851 876
852 /* Process hardware events, e.g. card removed, link lost */
853 spin_lock_irq(&priv->driver_lock);
854 while (__kfifo_len(priv->event_fifo)) {
855 u32 event;
856 877
857 __kfifo_get(priv->event_fifo, (unsigned char *) &event,
858 sizeof(event));
859 spin_unlock_irq(&priv->driver_lock);
860 lbs_process_event(priv, event);
861 spin_lock_irq(&priv->driver_lock);
862 }
863 spin_unlock_irq(&priv->driver_lock);
864 878
865 if (!priv->fw_ready) 879 if (!priv->fw_ready)
866 continue; 880 continue;
@@ -894,6 +908,9 @@ static int lbs_thread(void *data)
894 (priv->psstate == PS_STATE_PRE_SLEEP)) 908 (priv->psstate == PS_STATE_PRE_SLEEP))
895 continue; 909 continue;
896 910
911 if (priv->is_deep_sleep)
912 continue;
913
897 /* Execute the next command */ 914 /* Execute the next command */
898 if (!priv->dnld_sent && !priv->cur_cmd) 915 if (!priv->dnld_sent && !priv->cur_cmd)
899 lbs_execute_next_command(priv); 916 lbs_execute_next_command(priv);
@@ -928,6 +945,7 @@ static int lbs_thread(void *data)
928 } 945 }
929 946
930 del_timer(&priv->command_timer); 947 del_timer(&priv->command_timer);
948 del_timer(&priv->auto_deepsleep_timer);
931 wake_up_all(&priv->cmd_pending); 949 wake_up_all(&priv->cmd_pending);
932 950
933 lbs_deb_leave(LBS_DEB_THREAD); 951 lbs_deb_leave(LBS_DEB_THREAD);
@@ -1050,6 +1068,60 @@ out:
1050 lbs_deb_leave(LBS_DEB_CMD); 1068 lbs_deb_leave(LBS_DEB_CMD);
1051} 1069}
1052 1070
1071/**
1072 * This function put the device back to deep sleep mode when timer expires
1073 * and no activity (command, event, data etc.) is detected.
1074 */
1075static void auto_deepsleep_timer_fn(unsigned long data)
1076{
1077 struct lbs_private *priv = (struct lbs_private *)data;
1078 int ret;
1079
1080 lbs_deb_enter(LBS_DEB_CMD);
1081
1082 if (priv->is_activity_detected) {
1083 priv->is_activity_detected = 0;
1084 } else {
1085 if (priv->is_auto_deep_sleep_enabled &&
1086 (!priv->wakeup_dev_required) &&
1087 (priv->connect_status != LBS_CONNECTED)) {
1088 lbs_deb_main("Entering auto deep sleep mode...\n");
1089 ret = lbs_prepare_and_send_command(priv,
1090 CMD_802_11_DEEP_SLEEP, 0,
1091 0, 0, NULL);
1092 }
1093 }
1094 mod_timer(&priv->auto_deepsleep_timer , jiffies +
1095 (priv->auto_deep_sleep_timeout * HZ)/1000);
1096 lbs_deb_leave(LBS_DEB_CMD);
1097}
1098
1099int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
1100{
1101 lbs_deb_enter(LBS_DEB_SDIO);
1102
1103 priv->is_auto_deep_sleep_enabled = 1;
1104 if (priv->is_deep_sleep)
1105 priv->wakeup_dev_required = 1;
1106 mod_timer(&priv->auto_deepsleep_timer ,
1107 jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
1108
1109 lbs_deb_leave(LBS_DEB_SDIO);
1110 return 0;
1111}
1112
1113int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
1114{
1115 lbs_deb_enter(LBS_DEB_SDIO);
1116
1117 priv->is_auto_deep_sleep_enabled = 0;
1118 priv->auto_deep_sleep_timeout = 0;
1119 del_timer(&priv->auto_deepsleep_timer);
1120
1121 lbs_deb_leave(LBS_DEB_SDIO);
1122 return 0;
1123}
1124
1053static void lbs_sync_channel_worker(struct work_struct *work) 1125static void lbs_sync_channel_worker(struct work_struct *work)
1054{ 1126{
1055 struct lbs_private *priv = container_of(work, struct lbs_private, 1127 struct lbs_private *priv = container_of(work, struct lbs_private,
@@ -1099,11 +1171,17 @@ static int lbs_init_adapter(struct lbs_private *priv)
1099 priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; 1171 priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
1100 priv->psmode = LBS802_11POWERMODECAM; 1172 priv->psmode = LBS802_11POWERMODECAM;
1101 priv->psstate = PS_STATE_FULL_POWER; 1173 priv->psstate = PS_STATE_FULL_POWER;
1174 priv->is_deep_sleep = 0;
1175 priv->is_auto_deep_sleep_enabled = 0;
1176 priv->wakeup_dev_required = 0;
1177 init_waitqueue_head(&priv->ds_awake_q);
1102 1178
1103 mutex_init(&priv->lock); 1179 mutex_init(&priv->lock);
1104 1180
1105 setup_timer(&priv->command_timer, command_timer_fn, 1181 setup_timer(&priv->command_timer, command_timer_fn,
1106 (unsigned long)priv); 1182 (unsigned long)priv);
1183 setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
1184 (unsigned long)priv);
1107 1185
1108 INIT_LIST_HEAD(&priv->cmdfreeq); 1186 INIT_LIST_HEAD(&priv->cmdfreeq);
1109 INIT_LIST_HEAD(&priv->cmdpendingq); 1187 INIT_LIST_HEAD(&priv->cmdpendingq);
@@ -1142,6 +1220,7 @@ static void lbs_free_adapter(struct lbs_private *priv)
1142 if (priv->event_fifo) 1220 if (priv->event_fifo)
1143 kfifo_free(priv->event_fifo); 1221 kfifo_free(priv->event_fifo);
1144 del_timer(&priv->command_timer); 1222 del_timer(&priv->command_timer);
1223 del_timer(&priv->auto_deepsleep_timer);
1145 kfree(priv->networks); 1224 kfree(priv->networks);
1146 priv->networks = NULL; 1225 priv->networks = NULL;
1147 1226
@@ -1168,31 +1247,41 @@ static const struct net_device_ops lbs_netdev_ops = {
1168 */ 1247 */
1169struct lbs_private *lbs_add_card(void *card, struct device *dmdev) 1248struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1170{ 1249{
1171 struct net_device *dev = NULL; 1250 struct net_device *dev;
1251 struct wireless_dev *wdev;
1172 struct lbs_private *priv = NULL; 1252 struct lbs_private *priv = NULL;
1173 1253
1174 lbs_deb_enter(LBS_DEB_MAIN); 1254 lbs_deb_enter(LBS_DEB_MAIN);
1175 1255
1176 /* Allocate an Ethernet device and register it */ 1256 /* Allocate an Ethernet device and register it */
1177 dev = alloc_etherdev(sizeof(struct lbs_private)); 1257 wdev = lbs_cfg_alloc(dmdev);
1178 if (!dev) { 1258 if (IS_ERR(wdev)) {
1179 lbs_pr_err("init wlanX device failed\n"); 1259 lbs_pr_err("cfg80211 init failed\n");
1180 goto done; 1260 goto done;
1181 } 1261 }
1182 priv = netdev_priv(dev); 1262 /* TODO? */
1183 dev->ml_priv = priv; 1263 wdev->iftype = NL80211_IFTYPE_STATION;
1264 priv = wdev_priv(wdev);
1265 priv->wdev = wdev;
1184 1266
1185 if (lbs_init_adapter(priv)) { 1267 if (lbs_init_adapter(priv)) {
1186 lbs_pr_err("failed to initialize adapter structure.\n"); 1268 lbs_pr_err("failed to initialize adapter structure.\n");
1187 goto err_init_adapter; 1269 goto err_wdev;
1270 }
1271
1272 //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
1273 dev = alloc_netdev(0, "wlan%d", ether_setup);
1274 if (!dev) {
1275 dev_err(dmdev, "no memory for network device instance\n");
1276 goto err_adapter;
1188 } 1277 }
1189 1278
1279 dev->ieee80211_ptr = wdev;
1280 dev->ml_priv = priv;
1281 SET_NETDEV_DEV(dev, dmdev);
1282 wdev->netdev = dev;
1190 priv->dev = dev; 1283 priv->dev = dev;
1191 priv->card = card;
1192 priv->mesh_open = 0;
1193 priv->infra_open = 0;
1194 1284
1195 /* Setup the OS Interface to our functions */
1196 dev->netdev_ops = &lbs_netdev_ops; 1285 dev->netdev_ops = &lbs_netdev_ops;
1197 dev->watchdog_timeo = 5 * HZ; 1286 dev->watchdog_timeo = 5 * HZ;
1198 dev->ethtool_ops = &lbs_ethtool_ops; 1287 dev->ethtool_ops = &lbs_ethtool_ops;
@@ -1201,7 +1290,14 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1201#endif 1290#endif
1202 dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 1291 dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
1203 1292
1204 SET_NETDEV_DEV(dev, dmdev); 1293
1294 // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
1295
1296
1297 priv->card = card;
1298 priv->mesh_open = 0;
1299 priv->infra_open = 0;
1300
1205 1301
1206 priv->rtap_net_dev = NULL; 1302 priv->rtap_net_dev = NULL;
1207 strcpy(dev->name, "wlan%d"); 1303 strcpy(dev->name, "wlan%d");
@@ -1211,7 +1307,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1211 priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); 1307 priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
1212 if (IS_ERR(priv->main_thread)) { 1308 if (IS_ERR(priv->main_thread)) {
1213 lbs_deb_thread("Error creating main thread.\n"); 1309 lbs_deb_thread("Error creating main thread.\n");
1214 goto err_init_adapter; 1310 goto err_ndev;
1215 } 1311 }
1216 1312
1217 priv->work_thread = create_singlethread_workqueue("lbs_worker"); 1313 priv->work_thread = create_singlethread_workqueue("lbs_worker");
@@ -1228,9 +1324,15 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1228 1324
1229 goto done; 1325 goto done;
1230 1326
1231err_init_adapter: 1327 err_ndev:
1232 lbs_free_adapter(priv);
1233 free_netdev(dev); 1328 free_netdev(dev);
1329
1330 err_adapter:
1331 lbs_free_adapter(priv);
1332
1333 err_wdev:
1334 lbs_cfg_free(priv);
1335
1234 priv = NULL; 1336 priv = NULL;
1235 1337
1236done: 1338done:
@@ -1272,11 +1374,17 @@ void lbs_remove_card(struct lbs_private *priv)
1272 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 1374 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1273 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); 1375 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1274 1376
1377 if (priv->is_deep_sleep) {
1378 priv->is_deep_sleep = 0;
1379 wake_up_interruptible(&priv->ds_awake_q);
1380 }
1381
1275 /* Stop the thread servicing the interrupts */ 1382 /* Stop the thread servicing the interrupts */
1276 priv->surpriseremoved = 1; 1383 priv->surpriseremoved = 1;
1277 kthread_stop(priv->main_thread); 1384 kthread_stop(priv->main_thread);
1278 1385
1279 lbs_free_adapter(priv); 1386 lbs_free_adapter(priv);
1387 lbs_cfg_free(priv);
1280 1388
1281 priv->dev = NULL; 1389 priv->dev = NULL;
1282 free_netdev(dev); 1390 free_netdev(dev);
@@ -1301,8 +1409,8 @@ int lbs_start_card(struct lbs_private *priv)
1301 /* init 802.11d */ 1409 /* init 802.11d */
1302 lbs_init_11d(priv); 1410 lbs_init_11d(priv);
1303 1411
1304 if (register_netdev(dev)) { 1412 if (lbs_cfg_register(priv)) {
1305 lbs_pr_err("cannot register ethX device\n"); 1413 lbs_pr_err("cannot register device\n");
1306 goto done; 1414 goto done;
1307 } 1415 }
1308 1416
@@ -1392,6 +1500,7 @@ void lbs_stop_card(struct lbs_private *priv)
1392 1500
1393 /* Delete the timeout of the currently processing command */ 1501 /* Delete the timeout of the currently processing command */
1394 del_timer_sync(&priv->command_timer); 1502 del_timer_sync(&priv->command_timer);
1503 del_timer_sync(&priv->auto_deepsleep_timer);
1395 1504
1396 /* Flush pending command nodes */ 1505 /* Flush pending command nodes */
1397 spin_lock_irqsave(&priv->driver_lock, flags); 1506 spin_lock_irqsave(&priv->driver_lock, flags);
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index be837a0d2517..69dd19bf9558 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -45,7 +45,6 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv)
45 priv->pending_assoc_req = NULL; 45 priv->pending_assoc_req = NULL;
46} 46}
47 47
48
49/** 48/**
50 * @brief Find the channel frequency power info with specific channel 49 * @brief Find the channel frequency power info with specific channel
51 * 50 *
@@ -709,6 +708,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
709 struct iw_param *vwrq, char *extra) 708 struct iw_param *vwrq, char *extra)
710{ 709{
711 struct lbs_private *priv = dev->ml_priv; 710 struct lbs_private *priv = dev->ml_priv;
711 int ret = 0;
712 712
713 lbs_deb_enter(LBS_DEB_WEXT); 713 lbs_deb_enter(LBS_DEB_WEXT);
714 714
@@ -737,8 +737,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
737 "setting power timeout is not supported\n"); 737 "setting power timeout is not supported\n");
738 return -EINVAL; 738 return -EINVAL;
739 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { 739 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
740 lbs_deb_wext("setting power period not supported\n"); 740 vwrq->value = vwrq->value / 1000;
741 return -EINVAL; 741 if (!priv->enter_deep_sleep) {
742 lbs_pr_err("deep sleep feature is not implemented "
743 "for this interface driver\n");
744 return -EINVAL;
745 }
746
747 if (priv->connect_status == LBS_CONNECTED) {
748 if ((priv->is_auto_deep_sleep_enabled) &&
749 (vwrq->value == -1000)) {
750 lbs_exit_auto_deep_sleep(priv);
751 return 0;
752 } else {
753 lbs_pr_err("can't use deep sleep cmd in "
754 "connected state\n");
755 return -EINVAL;
756 }
757 }
758
759 if ((vwrq->value < 0) && (vwrq->value != -1000)) {
760 lbs_pr_err("unknown option\n");
761 return -EINVAL;
762 }
763
764 if (vwrq->value > 0) {
765 if (!priv->is_auto_deep_sleep_enabled) {
766 priv->is_activity_detected = 0;
767 priv->auto_deep_sleep_timeout = vwrq->value;
768 lbs_enter_auto_deep_sleep(priv);
769 } else {
770 priv->auto_deep_sleep_timeout = vwrq->value;
771 lbs_deb_debugfs("auto deep sleep: "
772 "already enabled\n");
773 }
774 return 0;
775 } else {
776 if (priv->is_auto_deep_sleep_enabled) {
777 lbs_exit_auto_deep_sleep(priv);
778 /* Try to exit deep sleep if auto */
779 /*deep sleep disabled */
780 ret = lbs_set_deep_sleep(priv, 0);
781 }
782 if (vwrq->value == 0)
783 ret = lbs_set_deep_sleep(priv, 1);
784 else if (vwrq->value == -1000)
785 ret = lbs_set_deep_sleep(priv, 0);
786 return ret;
787 }
742 } 788 }
743 789
744 if (priv->psmode != LBS802_11POWERMODECAM) { 790 if (priv->psmode != LBS802_11POWERMODECAM) {
@@ -752,6 +798,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
752 } 798 }
753 799
754 lbs_deb_leave(LBS_DEB_WEXT); 800 lbs_deb_leave(LBS_DEB_WEXT);
801
755 return 0; 802 return 0;
756} 803}
757 804
@@ -1000,6 +1047,7 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
1000 u8 rates[MAX_RATES + 1]; 1047 u8 rates[MAX_RATES + 1];
1001 1048
1002 lbs_deb_enter(LBS_DEB_WEXT); 1049 lbs_deb_enter(LBS_DEB_WEXT);
1050
1003 lbs_deb_wext("vwrq->value %d\n", vwrq->value); 1051 lbs_deb_wext("vwrq->value %d\n", vwrq->value);
1004 lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); 1052 lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
1005 1053