blob: cd3bddb243b1d3583e07f9ebd3648c5dfff5492f [file] [log] [blame]
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001/**
2 * This file contains the handling of command.
3 * It prepares command and sends it to firmware when it is ready.
4 */
5
6#include <net/iw_handler.h>
7#include "host.h"
8#include "hostcmd.h"
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02009#include "decl.h"
10#include "defs.h"
11#include "dev.h"
12#include "join.h"
13#include "wext.h"
14
15static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode);
16
17static u16 commands_allowed_in_ps[] = {
Dan Williams0aef64d2007-08-02 11:31:18 -040018 CMD_802_11_RSSI,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020019};
20
21/**
22 * @brief This function checks if the commans is allowed
23 * in PS mode not.
24 *
25 * @param command the command ID
26 * @return TRUE or FALSE
27 */
David Woodhouse981f1872007-05-25 23:36:54 -040028static u8 is_command_allowed_in_ps(__le16 command)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020029{
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020030 int i;
31
David Woodhouse981f1872007-05-25 23:36:54 -040032 for (i = 0; i < ARRAY_SIZE(commands_allowed_in_ps); i++) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020033 if (command == cpu_to_le16(commands_allowed_in_ps[i]))
34 return 1;
35 }
36
37 return 0;
38}
39
40static int wlan_cmd_hw_spec(wlan_private * priv, struct cmd_ds_command *cmd)
41{
42 struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec;
43
Holger Schurig9012b282007-05-25 11:27:16 -040044 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020045
Dan Williams0aef64d2007-08-02 11:31:18 -040046 cmd->command = cpu_to_le16(CMD_GET_HW_SPEC);
David Woodhouse981f1872007-05-25 23:36:54 -040047 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020048 memcpy(hwspec->permanentaddr, priv->adapter->current_addr, ETH_ALEN);
49
Holger Schurig9012b282007-05-25 11:27:16 -040050 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020051 return 0;
52}
53
54static int wlan_cmd_802_11_ps_mode(wlan_private * priv,
55 struct cmd_ds_command *cmd,
56 u16 cmd_action)
57{
58 struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020059
Holger Schurig9012b282007-05-25 11:27:16 -040060 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020061
Dan Williams0aef64d2007-08-02 11:31:18 -040062 cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
David Woodhouse981f1872007-05-25 23:36:54 -040063 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
64 S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020065 psm->action = cpu_to_le16(cmd_action);
66 psm->multipledtim = 0;
David Woodhouse981f1872007-05-25 23:36:54 -040067 switch (cmd_action) {
Dan Williams0aef64d2007-08-02 11:31:18 -040068 case CMD_SUBCMD_ENTER_PS:
Holger Schurig9012b282007-05-25 11:27:16 -040069 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020070
Holger Schurig252cf0d2007-08-02 13:09:34 -040071 psm->locallisteninterval = 0;
Holger Schurig97605c32007-08-02 13:09:15 -040072 psm->nullpktinterval = 0;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020073 psm->multipledtim =
Holger Schurig56c46562007-08-02 13:09:49 -040074 cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020075 break;
76
Dan Williams0aef64d2007-08-02 11:31:18 -040077 case CMD_SUBCMD_EXIT_PS:
Holger Schurig9012b282007-05-25 11:27:16 -040078 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020079 break;
80
Dan Williams0aef64d2007-08-02 11:31:18 -040081 case CMD_SUBCMD_SLEEP_CONFIRMED:
Holger Schurig9012b282007-05-25 11:27:16 -040082 lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020083 break;
84
85 default:
86 break;
87 }
88
Holger Schurig9012b282007-05-25 11:27:16 -040089 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020090 return 0;
91}
92
93static int wlan_cmd_802_11_inactivity_timeout(wlan_private * priv,
94 struct cmd_ds_command *cmd,
95 u16 cmd_action, void *pdata_buf)
96{
97 u16 *timeout = pdata_buf;
98
Holger Schurig8ff12da2007-08-02 11:54:31 -040099 lbs_deb_enter(LBS_DEB_CMD);
100
Dan Williams0aef64d2007-08-02 11:31:18 -0400101 cmd->command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200102 cmd->size =
103 cpu_to_le16(sizeof(struct cmd_ds_802_11_inactivity_timeout)
104 + S_DS_GEN);
105
106 cmd->params.inactivity_timeout.action = cpu_to_le16(cmd_action);
107
108 if (cmd_action)
David Woodhouse981f1872007-05-25 23:36:54 -0400109 cmd->params.inactivity_timeout.timeout = cpu_to_le16(*timeout);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200110 else
111 cmd->params.inactivity_timeout.timeout = 0;
112
Holger Schurig8ff12da2007-08-02 11:54:31 -0400113 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200114 return 0;
115}
116
117static int wlan_cmd_802_11_sleep_params(wlan_private * priv,
118 struct cmd_ds_command *cmd,
119 u16 cmd_action)
120{
121 wlan_adapter *adapter = priv->adapter;
122 struct cmd_ds_802_11_sleep_params *sp = &cmd->params.sleep_params;
123
Holger Schurig9012b282007-05-25 11:27:16 -0400124 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200125
David Woodhouse981f1872007-05-25 23:36:54 -0400126 cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
127 S_DS_GEN);
Dan Williams0aef64d2007-08-02 11:31:18 -0400128 cmd->command = cpu_to_le16(CMD_802_11_SLEEP_PARAMS);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200129
Dan Williams0aef64d2007-08-02 11:31:18 -0400130 if (cmd_action == CMD_ACT_GET) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200131 memset(&adapter->sp, 0, sizeof(struct sleep_params));
132 memset(sp, 0, sizeof(struct cmd_ds_802_11_sleep_params));
133 sp->action = cpu_to_le16(cmd_action);
Dan Williams0aef64d2007-08-02 11:31:18 -0400134 } else if (cmd_action == CMD_ACT_SET) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200135 sp->action = cpu_to_le16(cmd_action);
136 sp->error = cpu_to_le16(adapter->sp.sp_error);
137 sp->offset = cpu_to_le16(adapter->sp.sp_offset);
138 sp->stabletime = cpu_to_le16(adapter->sp.sp_stabletime);
139 sp->calcontrol = (u8) adapter->sp.sp_calcontrol;
140 sp->externalsleepclk = (u8) adapter->sp.sp_extsleepclk;
141 sp->reserved = cpu_to_le16(adapter->sp.sp_reserved);
142 }
143
Holger Schurig9012b282007-05-25 11:27:16 -0400144 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200145 return 0;
146}
147
148static int wlan_cmd_802_11_set_wep(wlan_private * priv,
149 struct cmd_ds_command *cmd,
150 u32 cmd_act,
151 void * pdata_buf)
152{
153 struct cmd_ds_802_11_set_wep *wep = &cmd->params.wep;
154 wlan_adapter *adapter = priv->adapter;
155 int ret = 0;
156 struct assoc_request * assoc_req = pdata_buf;
157
Holger Schurig9012b282007-05-25 11:27:16 -0400158 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200159
Dan Williams0aef64d2007-08-02 11:31:18 -0400160 cmd->command = cpu_to_le16(CMD_802_11_SET_WEP);
David Woodhouse981f1872007-05-25 23:36:54 -0400161 cmd->size = cpu_to_le16(sizeof(*wep) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200162
Dan Williams0aef64d2007-08-02 11:31:18 -0400163 if (cmd_act == CMD_ACT_ADD) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200164 int i;
165
166 if (!assoc_req) {
Holger Schurig9012b282007-05-25 11:27:16 -0400167 lbs_deb_cmd("Invalid association request!");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200168 ret = -1;
169 goto done;
170 }
171
Dan Williams0aef64d2007-08-02 11:31:18 -0400172 wep->action = cpu_to_le16(CMD_ACT_ADD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200173
174 /* default tx key index */
David Woodhouse981f1872007-05-25 23:36:54 -0400175 wep->keyindex = cpu_to_le16((u16)(assoc_req->wep_tx_keyidx &
Dan Williams0aef64d2007-08-02 11:31:18 -0400176 (u32)CMD_WEP_KEY_INDEX_MASK));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200177
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200178 /* Copy key types and material to host command structure */
179 for (i = 0; i < 4; i++) {
Dan Williams1443b652007-08-02 10:45:55 -0400180 struct enc_key * pkey = &assoc_req->wep_keys[i];
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200181
182 switch (pkey->len) {
183 case KEY_LEN_WEP_40:
David Woodhouse981f1872007-05-25 23:36:54 -0400184 wep->keytype[i] =
Dan Williams0aef64d2007-08-02 11:31:18 -0400185 cpu_to_le16(CMD_TYPE_WEP_40_BIT);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200186 memmove(&wep->keymaterial[i], pkey->key,
187 pkey->len);
Holger Schurig8ff12da2007-08-02 11:54:31 -0400188 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200189 break;
190 case KEY_LEN_WEP_104:
David Woodhouse981f1872007-05-25 23:36:54 -0400191 wep->keytype[i] =
Dan Williams0aef64d2007-08-02 11:31:18 -0400192 cpu_to_le16(CMD_TYPE_WEP_104_BIT);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200193 memmove(&wep->keymaterial[i], pkey->key,
194 pkey->len);
Holger Schurig8ff12da2007-08-02 11:54:31 -0400195 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200196 break;
197 case 0:
198 break;
199 default:
Holger Schurig8ff12da2007-08-02 11:54:31 -0400200 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200201 i, pkey->len);
202 ret = -1;
203 goto done;
204 break;
205 }
206 }
Dan Williams0aef64d2007-08-02 11:31:18 -0400207 } else if (cmd_act == CMD_ACT_REMOVE) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200208 /* ACT_REMOVE clears _all_ WEP keys */
Dan Williams0aef64d2007-08-02 11:31:18 -0400209 wep->action = cpu_to_le16(CMD_ACT_REMOVE);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200210
211 /* default tx key index */
David Woodhouse981f1872007-05-25 23:36:54 -0400212 wep->keyindex = cpu_to_le16((u16)(adapter->wep_tx_keyidx &
Dan Williams0aef64d2007-08-02 11:31:18 -0400213 (u32)CMD_WEP_KEY_INDEX_MASK));
Holger Schurig8ff12da2007-08-02 11:54:31 -0400214 lbs_deb_cmd("SET_WEP: remove key %d\n", adapter->wep_tx_keyidx);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200215 }
216
217 ret = 0;
218
219done:
Holger Schurig9012b282007-05-25 11:27:16 -0400220 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200221 return ret;
222}
223
224static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
225 struct cmd_ds_command *cmd,
Dan Williams90a42212007-05-25 23:01:24 -0400226 u16 cmd_action,
227 void * pdata_buf)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200228{
229 struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn;
Dan Williams18c96c342007-06-18 12:01:12 -0400230 u32 * enable = pdata_buf;
Dan Williams90a42212007-05-25 23:01:24 -0400231
232 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200233
Dan Williams0aef64d2007-08-02 11:31:18 -0400234 cmd->command = cpu_to_le16(CMD_802_11_ENABLE_RSN);
David Woodhouse981f1872007-05-25 23:36:54 -0400235 cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200236 penableRSN->action = cpu_to_le16(cmd_action);
Dan Williams18c96c342007-06-18 12:01:12 -0400237
Dan Williams0aef64d2007-08-02 11:31:18 -0400238 if (cmd_action == CMD_ACT_SET) {
Dan Williams18c96c342007-06-18 12:01:12 -0400239 if (*enable)
Dan Williams0aef64d2007-08-02 11:31:18 -0400240 penableRSN->enable = cpu_to_le16(CMD_ENABLE_RSN);
Dan Williams18c96c342007-06-18 12:01:12 -0400241 else
Dan Williams0aef64d2007-08-02 11:31:18 -0400242 penableRSN->enable = cpu_to_le16(CMD_DISABLE_RSN);
Holger Schurig8ff12da2007-08-02 11:54:31 -0400243 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200244 }
245
Dan Williams90a42212007-05-25 23:01:24 -0400246 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200247 return 0;
248}
249
250
251static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
Dan Williams1443b652007-08-02 10:45:55 -0400252 struct enc_key * pkey)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200253{
Holger Schurig8ff12da2007-08-02 11:54:31 -0400254 lbs_deb_enter(LBS_DEB_CMD);
255
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200256 if (pkey->flags & KEY_INFO_WPA_ENABLED) {
Dan Williams90a42212007-05-25 23:01:24 -0400257 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200258 }
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200259 if (pkey->flags & KEY_INFO_WPA_UNICAST) {
260 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
Dan Williams90a42212007-05-25 23:01:24 -0400261 }
262 if (pkey->flags & KEY_INFO_WPA_MCAST) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200263 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
264 }
265
266 pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
Dan Williams1443b652007-08-02 10:45:55 -0400267 pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200268 pkeyparamset->keylen = cpu_to_le16(pkey->len);
269 memcpy(pkeyparamset->key, pkey->key, pkey->len);
270 pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid)
271 + sizeof(pkeyparamset->keyinfo)
272 + sizeof(pkeyparamset->keylen)
273 + sizeof(pkeyparamset->key));
Holger Schurig8ff12da2007-08-02 11:54:31 -0400274 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200275}
276
277static int wlan_cmd_802_11_key_material(wlan_private * priv,
278 struct cmd_ds_command *cmd,
279 u16 cmd_action,
280 u32 cmd_oid, void *pdata_buf)
281{
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200282 struct cmd_ds_802_11_key_material *pkeymaterial =
283 &cmd->params.keymaterial;
Dan Williams90a42212007-05-25 23:01:24 -0400284 struct assoc_request * assoc_req = pdata_buf;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200285 int ret = 0;
286 int index = 0;
287
Holger Schurig9012b282007-05-25 11:27:16 -0400288 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200289
Dan Williams0aef64d2007-08-02 11:31:18 -0400290 cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200291 pkeymaterial->action = cpu_to_le16(cmd_action);
292
Dan Williams0aef64d2007-08-02 11:31:18 -0400293 if (cmd_action == CMD_ACT_GET) {
Dan Williams90a42212007-05-25 23:01:24 -0400294 cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200295 ret = 0;
296 goto done;
297 }
298
299 memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
300
Dan Williams90a42212007-05-25 23:01:24 -0400301 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200302 set_one_wpa_key(&pkeymaterial->keyParamSet[index],
Dan Williams90a42212007-05-25 23:01:24 -0400303 &assoc_req->wpa_unicast_key);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200304 index++;
305 }
306
Dan Williams90a42212007-05-25 23:01:24 -0400307 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200308 set_one_wpa_key(&pkeymaterial->keyParamSet[index],
Dan Williams90a42212007-05-25 23:01:24 -0400309 &assoc_req->wpa_mcast_key);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200310 index++;
311 }
312
313 cmd->size = cpu_to_le16( S_DS_GEN
Dan Williams90a42212007-05-25 23:01:24 -0400314 + sizeof (pkeymaterial->action)
315 + (index * sizeof(struct MrvlIEtype_keyParamSet)));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200316
317 ret = 0;
318
319done:
Holger Schurig9012b282007-05-25 11:27:16 -0400320 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200321 return ret;
322}
323
324static int wlan_cmd_802_11_reset(wlan_private * priv,
325 struct cmd_ds_command *cmd, int cmd_action)
326{
327 struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
328
Holger Schurig8ff12da2007-08-02 11:54:31 -0400329 lbs_deb_enter(LBS_DEB_CMD);
330
Dan Williams0aef64d2007-08-02 11:31:18 -0400331 cmd->command = cpu_to_le16(CMD_802_11_RESET);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200332 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
333 reset->action = cpu_to_le16(cmd_action);
334
Holger Schurig8ff12da2007-08-02 11:54:31 -0400335 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200336 return 0;
337}
338
339static int wlan_cmd_802_11_get_log(wlan_private * priv,
340 struct cmd_ds_command *cmd)
341{
Holger Schurig8ff12da2007-08-02 11:54:31 -0400342 lbs_deb_enter(LBS_DEB_CMD);
Dan Williams0aef64d2007-08-02 11:31:18 -0400343 cmd->command = cpu_to_le16(CMD_802_11_GET_LOG);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200344 cmd->size =
345 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN);
346
Holger Schurig8ff12da2007-08-02 11:54:31 -0400347 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200348 return 0;
349}
350
351static int wlan_cmd_802_11_get_stat(wlan_private * priv,
352 struct cmd_ds_command *cmd)
353{
Holger Schurig8ff12da2007-08-02 11:54:31 -0400354 lbs_deb_enter(LBS_DEB_CMD);
Dan Williams0aef64d2007-08-02 11:31:18 -0400355 cmd->command = cpu_to_le16(CMD_802_11_GET_STAT);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200356 cmd->size =
David Woodhouse981f1872007-05-25 23:36:54 -0400357 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200358
Holger Schurig8ff12da2007-08-02 11:54:31 -0400359 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200360 return 0;
361}
362
363static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
364 struct cmd_ds_command *cmd,
365 int cmd_action,
366 int cmd_oid, void *pdata_buf)
367{
368 struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib;
369 wlan_adapter *adapter = priv->adapter;
370 u8 ucTemp;
371
Holger Schurig9012b282007-05-25 11:27:16 -0400372 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200373
Holger Schurig9012b282007-05-25 11:27:16 -0400374 lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200375
Dan Williams0aef64d2007-08-02 11:31:18 -0400376 cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB);
David Woodhouse981f1872007-05-25 23:36:54 -0400377 cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200378
379 switch (cmd_oid) {
380 case OID_802_11_INFRASTRUCTURE_MODE:
381 {
Dan Williams0dc5a292007-05-10 22:58:02 -0400382 u8 mode = (u8) (size_t) pdata_buf;
Dan Williams0aef64d2007-08-02 11:31:18 -0400383 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
384 pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200385 pSNMPMIB->bufsize = sizeof(u8);
Dan Williams0dc5a292007-05-10 22:58:02 -0400386 if (mode == IW_MODE_ADHOC) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200387 ucTemp = SNMP_MIB_VALUE_ADHOC;
Dan Williams0dc5a292007-05-10 22:58:02 -0400388 } else {
389 /* Infra and Auto modes */
390 ucTemp = SNMP_MIB_VALUE_INFRA;
391 }
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200392
393 memmove(pSNMPMIB->value, &ucTemp, sizeof(u8));
394
395 break;
396 }
397
398 case OID_802_11D_ENABLE:
399 {
400 u32 ulTemp;
401
Dan Williams0aef64d2007-08-02 11:31:18 -0400402 pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200403
Dan Williams0aef64d2007-08-02 11:31:18 -0400404 if (cmd_action == CMD_ACT_SET) {
405 pSNMPMIB->querytype = CMD_ACT_SET;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200406 pSNMPMIB->bufsize = sizeof(u16);
407 ulTemp = *(u32 *)pdata_buf;
David Woodhouse981f1872007-05-25 23:36:54 -0400408 *((__le16 *)(pSNMPMIB->value)) =
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200409 cpu_to_le16((u16) ulTemp);
410 }
411 break;
412 }
413
414 case OID_802_11_FRAGMENTATION_THRESHOLD:
415 {
416 u32 ulTemp;
417
Dan Williams0aef64d2007-08-02 11:31:18 -0400418 pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200419
Dan Williams0aef64d2007-08-02 11:31:18 -0400420 if (cmd_action == CMD_ACT_GET) {
421 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
422 } else if (cmd_action == CMD_ACT_SET) {
423 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
David Woodhouse981f1872007-05-25 23:36:54 -0400424 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200425 ulTemp = *((u32 *) pdata_buf);
David Woodhouse981f1872007-05-25 23:36:54 -0400426 *((__le16 *)(pSNMPMIB->value)) =
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200427 cpu_to_le16((u16) ulTemp);
428
429 }
430
431 break;
432 }
433
434 case OID_802_11_RTS_THRESHOLD:
435 {
436
437 u32 ulTemp;
Dan Williams0aef64d2007-08-02 11:31:18 -0400438 pSNMPMIB->oid = le16_to_cpu((u16) RTSTHRESH_I);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200439
Dan Williams0aef64d2007-08-02 11:31:18 -0400440 if (cmd_action == CMD_ACT_GET) {
441 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
442 } else if (cmd_action == CMD_ACT_SET) {
443 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
David Woodhouse981f1872007-05-25 23:36:54 -0400444 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
445 ulTemp = *((u32 *)pdata_buf);
446 *(__le16 *)(pSNMPMIB->value) =
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200447 cpu_to_le16((u16) ulTemp);
448
449 }
450 break;
451 }
452 case OID_802_11_TX_RETRYCOUNT:
Dan Williams0aef64d2007-08-02 11:31:18 -0400453 pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200454
Dan Williams0aef64d2007-08-02 11:31:18 -0400455 if (cmd_action == CMD_ACT_GET) {
456 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
457 } else if (cmd_action == CMD_ACT_SET) {
458 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200459 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
David Woodhouse981f1872007-05-25 23:36:54 -0400460 *((__le16 *)(pSNMPMIB->value)) =
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200461 cpu_to_le16((u16) adapter->txretrycount);
462 }
463
464 break;
465 default:
466 break;
467 }
468
Holger Schurig9012b282007-05-25 11:27:16 -0400469 lbs_deb_cmd(
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200470 "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400471 le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
472 le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200473
Holger Schurig9012b282007-05-25 11:27:16 -0400474 lbs_deb_cmd(
Holger Schurig8ff12da2007-08-02 11:54:31 -0400475 "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400476 le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
477 le16_to_cpu(pSNMPMIB->bufsize),
478 le16_to_cpu(*(__le16 *) pSNMPMIB->value));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200479
Holger Schurig9012b282007-05-25 11:27:16 -0400480 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200481 return 0;
482}
483
484static int wlan_cmd_802_11_radio_control(wlan_private * priv,
485 struct cmd_ds_command *cmd,
486 int cmd_action)
487{
488 wlan_adapter *adapter = priv->adapter;
David Woodhouse981f1872007-05-25 23:36:54 -0400489 struct cmd_ds_802_11_radio_control *pradiocontrol = &cmd->params.radio;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200490
Holger Schurig9012b282007-05-25 11:27:16 -0400491 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200492
493 cmd->size =
494 cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control)) +
495 S_DS_GEN);
Dan Williams0aef64d2007-08-02 11:31:18 -0400496 cmd->command = cpu_to_le16(CMD_802_11_RADIO_CONTROL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200497
498 pradiocontrol->action = cpu_to_le16(cmd_action);
499
500 switch (adapter->preamble) {
Dan Williams0aef64d2007-08-02 11:31:18 -0400501 case CMD_TYPE_SHORT_PREAMBLE:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200502 pradiocontrol->control = cpu_to_le16(SET_SHORT_PREAMBLE);
503 break;
504
Dan Williams0aef64d2007-08-02 11:31:18 -0400505 case CMD_TYPE_LONG_PREAMBLE:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200506 pradiocontrol->control = cpu_to_le16(SET_LONG_PREAMBLE);
507 break;
508
Dan Williams0aef64d2007-08-02 11:31:18 -0400509 case CMD_TYPE_AUTO_PREAMBLE:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200510 default:
511 pradiocontrol->control = cpu_to_le16(SET_AUTO_PREAMBLE);
512 break;
513 }
514
515 if (adapter->radioon)
516 pradiocontrol->control |= cpu_to_le16(TURN_ON_RF);
517 else
518 pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF);
519
Holger Schurig9012b282007-05-25 11:27:16 -0400520 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200521 return 0;
522}
523
524static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
525 struct cmd_ds_command *cmd,
526 u16 cmd_action, void *pdata_buf)
527{
528
529 struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
530
Holger Schurig9012b282007-05-25 11:27:16 -0400531 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200532
533 cmd->size =
David Woodhouse981f1872007-05-25 23:36:54 -0400534 cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
Dan Williams0aef64d2007-08-02 11:31:18 -0400535 cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER);
David Woodhouse981f1872007-05-25 23:36:54 -0400536 prtp->action = cpu_to_le16(cmd_action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200537
David Woodhouse981f1872007-05-25 23:36:54 -0400538 lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
539 le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
540 le16_to_cpu(prtp->action));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200541
542 switch (cmd_action) {
Dan Williams0aef64d2007-08-02 11:31:18 -0400543 case CMD_ACT_TX_POWER_OPT_GET:
544 prtp->action = cpu_to_le16(CMD_ACT_GET);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200545 prtp->currentlevel = 0;
546 break;
547
Dan Williams0aef64d2007-08-02 11:31:18 -0400548 case CMD_ACT_TX_POWER_OPT_SET_HIGH:
549 prtp->action = cpu_to_le16(CMD_ACT_SET);
550 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200551 break;
552
Dan Williams0aef64d2007-08-02 11:31:18 -0400553 case CMD_ACT_TX_POWER_OPT_SET_MID:
554 prtp->action = cpu_to_le16(CMD_ACT_SET);
555 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200556 break;
557
Dan Williams0aef64d2007-08-02 11:31:18 -0400558 case CMD_ACT_TX_POWER_OPT_SET_LOW:
559 prtp->action = cpu_to_le16(CMD_ACT_SET);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200560 prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
561 break;
562 }
Holger Schurig9012b282007-05-25 11:27:16 -0400563
564 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200565 return 0;
566}
567
Luis Carlos Cobo965f8bbc2007-08-02 13:16:55 -0400568static int wlan_cmd_802_11_monitor_mode(wlan_private * priv,
569 struct cmd_ds_command *cmd,
570 u16 cmd_action, void *pdata_buf)
571{
572 struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
573
574 cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
575 cmd->size =
576 cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
577 S_DS_GEN);
578
579 monitor->action = cpu_to_le16(cmd_action);
580 if (cmd_action == CMD_ACT_SET) {
581 monitor->mode =
582 cpu_to_le16((u16) (*(u32 *) pdata_buf));
583 }
584
585 return 0;
586}
587
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200588static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
589 struct cmd_ds_command *cmd,
590 u16 cmd_action)
591{
592 struct cmd_ds_802_11_rate_adapt_rateset
593 *rateadapt = &cmd->params.rateset;
594 wlan_adapter *adapter = priv->adapter;
595
Holger Schurig8ff12da2007-08-02 11:54:31 -0400596 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200597 cmd->size =
598 cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset)
599 + S_DS_GEN);
Dan Williams0aef64d2007-08-02 11:31:18 -0400600 cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200601
David Woodhouse981f1872007-05-25 23:36:54 -0400602 rateadapt->action = cpu_to_le16(cmd_action);
603 rateadapt->enablehwauto = cpu_to_le16(adapter->enablehwauto);
604 rateadapt->bitmap = cpu_to_le16(adapter->ratebitmap);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200605
Holger Schurig9012b282007-05-25 11:27:16 -0400606 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200607 return 0;
608}
609
610static int wlan_cmd_802_11_data_rate(wlan_private * priv,
611 struct cmd_ds_command *cmd,
612 u16 cmd_action)
613{
614 struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate;
615 wlan_adapter *adapter = priv->adapter;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200616
Holger Schurig9012b282007-05-25 11:27:16 -0400617 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200618
David Woodhouse981f1872007-05-25 23:36:54 -0400619 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200620 S_DS_GEN);
Dan Williams0aef64d2007-08-02 11:31:18 -0400621 cmd->command = cpu_to_le16(CMD_802_11_DATA_RATE);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200622 memset(pdatarate, 0, sizeof(struct cmd_ds_802_11_data_rate));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200623 pdatarate->action = cpu_to_le16(cmd_action);
624
Dan Williamsffcae952007-08-02 11:35:46 -0400625 if (cmd_action == CMD_ACT_SET_TX_FIX_RATE) {
Dan Williams8c512762007-08-02 11:40:45 -0400626 pdatarate->rates[0] = libertas_data_rate_to_fw_index(adapter->cur_rate);
Holger Schurig8ff12da2007-08-02 11:54:31 -0400627 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n",
Dan Williams8c512762007-08-02 11:40:45 -0400628 adapter->cur_rate);
Dan Williamsffcae952007-08-02 11:35:46 -0400629 } else if (cmd_action == CMD_ACT_SET_TX_AUTO) {
Holger Schurig8ff12da2007-08-02 11:54:31 -0400630 lbs_deb_cmd("DATA_RATE: setting auto\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200631 }
632
Holger Schurig9012b282007-05-25 11:27:16 -0400633 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200634 return 0;
635}
636
637static int wlan_cmd_mac_multicast_adr(wlan_private * priv,
638 struct cmd_ds_command *cmd,
639 u16 cmd_action)
640{
641 struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
642 wlan_adapter *adapter = priv->adapter;
643
Holger Schurig8ff12da2007-08-02 11:54:31 -0400644 lbs_deb_enter(LBS_DEB_CMD);
David Woodhouse981f1872007-05-25 23:36:54 -0400645 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200646 S_DS_GEN);
Dan Williams0aef64d2007-08-02 11:31:18 -0400647 cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200648
Holger Schurig8ff12da2007-08-02 11:54:31 -0400649 lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200650 pMCastAdr->action = cpu_to_le16(cmd_action);
651 pMCastAdr->nr_of_adrs =
652 cpu_to_le16((u16) adapter->nr_of_multicastmacaddr);
653 memcpy(pMCastAdr->maclist, adapter->multicastlist,
654 adapter->nr_of_multicastmacaddr * ETH_ALEN);
655
Holger Schurig8ff12da2007-08-02 11:54:31 -0400656 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200657 return 0;
658}
659
660static int wlan_cmd_802_11_rf_channel(wlan_private * priv,
661 struct cmd_ds_command *cmd,
662 int option, void *pdata_buf)
663{
664 struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
665
Holger Schurig8ff12da2007-08-02 11:54:31 -0400666 lbs_deb_enter(LBS_DEB_CMD);
Dan Williams0aef64d2007-08-02 11:31:18 -0400667 cmd->command = cpu_to_le16(CMD_802_11_RF_CHANNEL);
David Woodhouse981f1872007-05-25 23:36:54 -0400668 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
669 S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200670
Dan Williams0aef64d2007-08-02 11:31:18 -0400671 if (option == CMD_OPT_802_11_RF_CHANNEL_SET) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200672 rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
673 }
674
675 rfchan->action = cpu_to_le16(option);
676
Holger Schurig8ff12da2007-08-02 11:54:31 -0400677 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200678 return 0;
679}
680
681static int wlan_cmd_802_11_rssi(wlan_private * priv,
682 struct cmd_ds_command *cmd)
683{
684 wlan_adapter *adapter = priv->adapter;
685
Holger Schurig8ff12da2007-08-02 11:54:31 -0400686 lbs_deb_enter(LBS_DEB_CMD);
Dan Williams0aef64d2007-08-02 11:31:18 -0400687 cmd->command = cpu_to_le16(CMD_802_11_RSSI);
David Woodhouse981f1872007-05-25 23:36:54 -0400688 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
Holger Schuriga783f1e2007-08-02 13:08:24 -0400689 cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200690
691 /* reset Beacon SNR/NF/RSSI values */
692 adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
693 adapter->SNR[TYPE_BEACON][TYPE_AVG] = 0;
694 adapter->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
695 adapter->NF[TYPE_BEACON][TYPE_AVG] = 0;
696 adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
697 adapter->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
698
Holger Schurig8ff12da2007-08-02 11:54:31 -0400699 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200700 return 0;
701}
702
703static int wlan_cmd_reg_access(wlan_private * priv,
704 struct cmd_ds_command *cmdptr,
705 u8 cmd_action, void *pdata_buf)
706{
707 struct wlan_offset_value *offval;
708
Holger Schurig9012b282007-05-25 11:27:16 -0400709 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200710
711 offval = (struct wlan_offset_value *)pdata_buf;
712
713 switch (cmdptr->command) {
Dan Williams0aef64d2007-08-02 11:31:18 -0400714 case CMD_MAC_REG_ACCESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200715 {
716 struct cmd_ds_mac_reg_access *macreg;
717
718 cmdptr->size =
David Woodhouse981f1872007-05-25 23:36:54 -0400719 cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
720 + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200721 macreg =
722 (struct cmd_ds_mac_reg_access *)&cmdptr->params.
723 macreg;
724
725 macreg->action = cpu_to_le16(cmd_action);
726 macreg->offset = cpu_to_le16((u16) offval->offset);
727 macreg->value = cpu_to_le32(offval->value);
728
729 break;
730 }
731
Dan Williams0aef64d2007-08-02 11:31:18 -0400732 case CMD_BBP_REG_ACCESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200733 {
734 struct cmd_ds_bbp_reg_access *bbpreg;
735
736 cmdptr->size =
737 cpu_to_le16(sizeof
738 (struct cmd_ds_bbp_reg_access)
739 + S_DS_GEN);
740 bbpreg =
741 (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
742 bbpreg;
743
744 bbpreg->action = cpu_to_le16(cmd_action);
745 bbpreg->offset = cpu_to_le16((u16) offval->offset);
746 bbpreg->value = (u8) offval->value;
747
748 break;
749 }
750
Dan Williams0aef64d2007-08-02 11:31:18 -0400751 case CMD_RF_REG_ACCESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200752 {
753 struct cmd_ds_rf_reg_access *rfreg;
754
755 cmdptr->size =
756 cpu_to_le16(sizeof
757 (struct cmd_ds_rf_reg_access) +
758 S_DS_GEN);
759 rfreg =
760 (struct cmd_ds_rf_reg_access *)&cmdptr->params.
761 rfreg;
762
763 rfreg->action = cpu_to_le16(cmd_action);
764 rfreg->offset = cpu_to_le16((u16) offval->offset);
765 rfreg->value = (u8) offval->value;
766
767 break;
768 }
769
770 default:
771 break;
772 }
773
Holger Schurig9012b282007-05-25 11:27:16 -0400774 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200775 return 0;
776}
777
778static int wlan_cmd_802_11_mac_address(wlan_private * priv,
779 struct cmd_ds_command *cmd,
780 u16 cmd_action)
781{
782 wlan_adapter *adapter = priv->adapter;
783
Holger Schurig8ff12da2007-08-02 11:54:31 -0400784 lbs_deb_enter(LBS_DEB_CMD);
Dan Williams0aef64d2007-08-02 11:31:18 -0400785 cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
David Woodhouse981f1872007-05-25 23:36:54 -0400786 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200787 S_DS_GEN);
788 cmd->result = 0;
789
790 cmd->params.macadd.action = cpu_to_le16(cmd_action);
791
Dan Williams0aef64d2007-08-02 11:31:18 -0400792 if (cmd_action == CMD_ACT_SET) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200793 memcpy(cmd->params.macadd.macadd,
794 adapter->current_addr, ETH_ALEN);
Holger Schurigece56192007-08-02 11:53:06 -0400795 lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", adapter->current_addr, 6);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200796 }
797
Holger Schurig8ff12da2007-08-02 11:54:31 -0400798 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200799 return 0;
800}
801
802static int wlan_cmd_802_11_eeprom_access(wlan_private * priv,
803 struct cmd_ds_command *cmd,
804 int cmd_action, void *pdata_buf)
805{
806 struct wlan_ioctl_regrdwr *ea = pdata_buf;
807
Holger Schurig9012b282007-05-25 11:27:16 -0400808 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200809
Dan Williams0aef64d2007-08-02 11:31:18 -0400810 cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
David Woodhouse981f1872007-05-25 23:36:54 -0400811 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
812 S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200813 cmd->result = 0;
814
815 cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
816 cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
817 cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
818 cmd->params.rdeeprom.value = 0;
819
Holger Schurig8ff12da2007-08-02 11:54:31 -0400820 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200821 return 0;
822}
823
824static int wlan_cmd_bt_access(wlan_private * priv,
825 struct cmd_ds_command *cmd,
826 u16 cmd_action, void *pdata_buf)
827{
828 struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
Holger Schurig8ff12da2007-08-02 11:54:31 -0400829 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200830
Dan Williams0aef64d2007-08-02 11:31:18 -0400831 cmd->command = cpu_to_le16(CMD_BT_ACCESS);
David Woodhouse981f1872007-05-25 23:36:54 -0400832 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200833 cmd->result = 0;
834 bt_access->action = cpu_to_le16(cmd_action);
835
836 switch (cmd_action) {
Dan Williams0aef64d2007-08-02 11:31:18 -0400837 case CMD_ACT_BT_ACCESS_ADD:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200838 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
Holger Schurigece56192007-08-02 11:53:06 -0400839 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200840 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400841 case CMD_ACT_BT_ACCESS_DEL:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200842 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
Holger Schurigece56192007-08-02 11:53:06 -0400843 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200844 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400845 case CMD_ACT_BT_ACCESS_LIST:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200846 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
847 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400848 case CMD_ACT_BT_ACCESS_RESET:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200849 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400850 case CMD_ACT_BT_ACCESS_SET_INVERT:
Luis Carlos Cobo90e8eaf2007-05-25 13:53:26 -0400851 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
852 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400853 case CMD_ACT_BT_ACCESS_GET_INVERT:
Luis Carlos Cobo90e8eaf2007-05-25 13:53:26 -0400854 break;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200855 default:
856 break;
857 }
Holger Schurig8ff12da2007-08-02 11:54:31 -0400858 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200859 return 0;
860}
861
862static int wlan_cmd_fwt_access(wlan_private * priv,
863 struct cmd_ds_command *cmd,
864 u16 cmd_action, void *pdata_buf)
865{
866 struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
Holger Schurig8ff12da2007-08-02 11:54:31 -0400867 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200868
Dan Williams0aef64d2007-08-02 11:31:18 -0400869 cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
David Woodhouse981f1872007-05-25 23:36:54 -0400870 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200871 cmd->result = 0;
872
873 if (pdata_buf)
874 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
875 else
876 memset(fwt_access, 0, sizeof(*fwt_access));
877
878 fwt_access->action = cpu_to_le16(cmd_action);
879
Holger Schurig8ff12da2007-08-02 11:54:31 -0400880 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200881 return 0;
882}
883
884static int wlan_cmd_mesh_access(wlan_private * priv,
885 struct cmd_ds_command *cmd,
886 u16 cmd_action, void *pdata_buf)
887{
888 struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh;
Holger Schurig8ff12da2007-08-02 11:54:31 -0400889 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200890
Dan Williams0aef64d2007-08-02 11:31:18 -0400891 cmd->command = cpu_to_le16(CMD_MESH_ACCESS);
David Woodhouse981f1872007-05-25 23:36:54 -0400892 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200893 cmd->result = 0;
894
895 if (pdata_buf)
896 memcpy(mesh_access, pdata_buf, sizeof(*mesh_access));
897 else
898 memset(mesh_access, 0, sizeof(*mesh_access));
899
900 mesh_access->action = cpu_to_le16(cmd_action);
901
Holger Schurig8ff12da2007-08-02 11:54:31 -0400902 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200903 return 0;
904}
905
906void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail)
907{
908 unsigned long flags;
909 struct cmd_ds_command *cmdptr;
910
Holger Schurig8ff12da2007-08-02 11:54:31 -0400911 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200912
913 if (!cmdnode) {
Holger Schurig8ff12da2007-08-02 11:54:31 -0400914 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200915 goto done;
916 }
917
918 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
919 if (!cmdptr) {
Holger Schurig8ff12da2007-08-02 11:54:31 -0400920 lbs_deb_host("QUEUE_CMD: cmdptr is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200921 goto done;
922 }
923
924 /* Exit_PS command needs to be queued in the header always. */
Dan Williams0aef64d2007-08-02 11:31:18 -0400925 if (cmdptr->command == CMD_802_11_PS_MODE) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200926 struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode;
Dan Williams0aef64d2007-08-02 11:31:18 -0400927 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200928 if (adapter->psstate != PS_STATE_FULL_POWER)
929 addtail = 0;
930 }
931 }
932
933 spin_lock_irqsave(&adapter->driver_lock, flags);
934
935 if (addtail)
936 list_add_tail((struct list_head *)cmdnode,
937 &adapter->cmdpendingq);
938 else
939 list_add((struct list_head *)cmdnode, &adapter->cmdpendingq);
940
941 spin_unlock_irqrestore(&adapter->driver_lock, flags);
942
Holger Schurig8ff12da2007-08-02 11:54:31 -0400943 lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400944 le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200945
946done:
Holger Schurig8ff12da2007-08-02 11:54:31 -0400947 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200948}
949
950/*
951 * TODO: Fix the issue when DownloadcommandToStation is being called the
Holger Schurig8ff12da2007-08-02 11:54:31 -0400952 * second time when the command times out. All the cmdptr->xxx are in little
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200953 * endian and therefore all the comparissions will fail.
954 * For now - we are not performing the endian conversion the second time - but
955 * for PS and DEEP_SLEEP we need to worry
956 */
957static int DownloadcommandToStation(wlan_private * priv,
958 struct cmd_ctrl_node *cmdnode)
959{
960 unsigned long flags;
961 struct cmd_ds_command *cmdptr;
962 wlan_adapter *adapter = priv->adapter;
963 int ret = 0;
964 u16 cmdsize;
965 u16 command;
966
Holger Schurig8ff12da2007-08-02 11:54:31 -0400967 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200968
969 if (!adapter || !cmdnode) {
Holger Schurig8ff12da2007-08-02 11:54:31 -0400970 lbs_deb_host("DNLD_CMD: adapter or cmdmode is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200971 if (cmdnode) {
972 spin_lock_irqsave(&adapter->driver_lock, flags);
973 __libertas_cleanup_and_insert_cmd(priv, cmdnode);
974 spin_unlock_irqrestore(&adapter->driver_lock, flags);
975 }
976 ret = -1;
977 goto done;
978 }
979
980 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
981
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200982 spin_lock_irqsave(&adapter->driver_lock, flags);
983 if (!cmdptr || !cmdptr->size) {
Holger Schurig8ff12da2007-08-02 11:54:31 -0400984 lbs_deb_host("DNLD_CMD: cmdptr is NULL or zero\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200985 __libertas_cleanup_and_insert_cmd(priv, cmdnode);
986 spin_unlock_irqrestore(&adapter->driver_lock, flags);
987 ret = -1;
988 goto done;
989 }
990
991 adapter->cur_cmd = cmdnode;
992 adapter->cur_cmd_retcode = 0;
993 spin_unlock_irqrestore(&adapter->driver_lock, flags);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200994
995 cmdsize = cmdptr->size;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200996 command = cpu_to_le16(cmdptr->command);
997
Holger Schurig8ff12da2007-08-02 11:54:31 -0400998 lbs_deb_host("DNLD_CMD: command 0x%04x, size %d, jiffies %lu\n",
999 command, le16_to_cpu(cmdptr->size), jiffies);
1000 lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", cmdnode->bufvirtualaddr, cmdsize);
1001
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001002 cmdnode->cmdwaitqwoken = 0;
1003 cmdsize = cpu_to_le16(cmdsize);
1004
Holger Schurig208fdd22007-05-25 12:17:06 -04001005 ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001006
1007 if (ret != 0) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001008 lbs_deb_host("DNLD_CMD: hw_host_to_card failed\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001009 spin_lock_irqsave(&adapter->driver_lock, flags);
1010 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
1011 adapter->cur_cmd = NULL;
1012 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1013 ret = -1;
1014 goto done;
1015 }
1016
Holger Schurig8ff12da2007-08-02 11:54:31 -04001017 lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", command, jiffies);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001018
1019 /* Setup the timer after transmit command */
Dan Williams0aef64d2007-08-02 11:31:18 -04001020 if (command == CMD_802_11_SCAN || command == CMD_802_11_AUTHENTICATE
1021 || command == CMD_802_11_ASSOCIATE)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001022 mod_timer(&adapter->command_timer, jiffies + (10*HZ));
1023 else
1024 mod_timer(&adapter->command_timer, jiffies + (5*HZ));
1025
1026 ret = 0;
1027
Holger Schurig9012b282007-05-25 11:27:16 -04001028done:
Holger Schurig8ff12da2007-08-02 11:54:31 -04001029 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001030 return ret;
1031}
1032
1033static int wlan_cmd_mac_control(wlan_private * priv,
1034 struct cmd_ds_command *cmd)
1035{
1036 struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
1037
Holger Schurig9012b282007-05-25 11:27:16 -04001038 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001039
Dan Williams0aef64d2007-08-02 11:31:18 -04001040 cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
David Woodhouse981f1872007-05-25 23:36:54 -04001041 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001042 mac->action = cpu_to_le16(priv->adapter->currentpacketfilter);
1043
Holger Schurig8ff12da2007-08-02 11:54:31 -04001044 lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
David Woodhouse981f1872007-05-25 23:36:54 -04001045 le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001046
Holger Schurig9012b282007-05-25 11:27:16 -04001047 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001048 return 0;
1049}
1050
1051/**
1052 * This function inserts command node to cmdfreeq
1053 * after cleans it. Requires adapter->driver_lock held.
1054 */
1055void __libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
1056{
1057 wlan_adapter *adapter = priv->adapter;
1058
1059 if (!ptempcmd)
Holger Schurig8ff12da2007-08-02 11:54:31 -04001060 return;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001061
1062 cleanup_cmdnode(ptempcmd);
1063 list_add_tail((struct list_head *)ptempcmd, &adapter->cmdfreeq);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001064}
1065
Holger Schurigac558ca2007-08-02 11:49:06 -04001066static void libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001067{
1068 unsigned long flags;
1069
1070 spin_lock_irqsave(&priv->adapter->driver_lock, flags);
1071 __libertas_cleanup_and_insert_cmd(priv, ptempcmd);
1072 spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
1073}
1074
1075int libertas_set_radio_control(wlan_private * priv)
1076{
1077 int ret = 0;
1078
Holger Schurig9012b282007-05-25 11:27:16 -04001079 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001080
1081 ret = libertas_prepare_and_send_command(priv,
Dan Williams0aef64d2007-08-02 11:31:18 -04001082 CMD_802_11_RADIO_CONTROL,
1083 CMD_ACT_SET,
1084 CMD_OPTION_WAITFORRSP, 0, NULL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001085
Holger Schurig8ff12da2007-08-02 11:54:31 -04001086 lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001087 priv->adapter->radioon, priv->adapter->preamble);
1088
Holger Schurig9012b282007-05-25 11:27:16 -04001089 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001090 return ret;
1091}
1092
1093int libertas_set_mac_packet_filter(wlan_private * priv)
1094{
1095 int ret = 0;
1096
Holger Schurig9012b282007-05-25 11:27:16 -04001097 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001098
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001099 /* Send MAC control command to station */
1100 ret = libertas_prepare_and_send_command(priv,
Dan Williams0aef64d2007-08-02 11:31:18 -04001101 CMD_MAC_CONTROL, 0, 0, 0, NULL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001102
Holger Schurig9012b282007-05-25 11:27:16 -04001103 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001104 return ret;
1105}
1106
1107/**
1108 * @brief This function prepare the command before send to firmware.
1109 *
1110 * @param priv A pointer to wlan_private structure
1111 * @param cmd_no command number
1112 * @param cmd_action command action: GET or SET
1113 * @param wait_option wait option: wait response or not
1114 * @param cmd_oid cmd oid: treated as sub command
1115 * @param pdata_buf A pointer to informaion buffer
1116 * @return 0 or -1
1117 */
1118int libertas_prepare_and_send_command(wlan_private * priv,
1119 u16 cmd_no,
1120 u16 cmd_action,
1121 u16 wait_option, u32 cmd_oid, void *pdata_buf)
1122{
1123 int ret = 0;
1124 wlan_adapter *adapter = priv->adapter;
1125 struct cmd_ctrl_node *cmdnode;
1126 struct cmd_ds_command *cmdptr;
1127 unsigned long flags;
1128
Holger Schurig8ff12da2007-08-02 11:54:31 -04001129 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001130
1131 if (!adapter) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001132 lbs_deb_host("PREP_CMD: adapter is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001133 ret = -1;
1134 goto done;
1135 }
1136
1137 if (adapter->surpriseremoved) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001138 lbs_deb_host("PREP_CMD: card removed\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001139 ret = -1;
1140 goto done;
1141 }
1142
1143 cmdnode = libertas_get_free_cmd_ctrl_node(priv);
1144
1145 if (cmdnode == NULL) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001146 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001147
1148 /* Wake up main thread to execute next command */
Dan Williamsfe336152007-08-02 11:32:25 -04001149 wake_up_interruptible(&priv->waitq);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001150 ret = -1;
1151 goto done;
1152 }
1153
1154 libertas_set_cmd_ctrl_node(priv, cmdnode, cmd_oid, wait_option, pdata_buf);
1155
1156 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1157
Holger Schurig8ff12da2007-08-02 11:54:31 -04001158 lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001159
1160 if (!cmdptr) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001161 lbs_deb_host("PREP_CMD: cmdptr is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001162 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1163 ret = -1;
1164 goto done;
1165 }
1166
1167 /* Set sequence number, command and INT option */
1168 adapter->seqnum++;
1169 cmdptr->seqnum = cpu_to_le16(adapter->seqnum);
1170
David Woodhouse981f1872007-05-25 23:36:54 -04001171 cmdptr->command = cpu_to_le16(cmd_no);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001172 cmdptr->result = 0;
1173
1174 switch (cmd_no) {
Dan Williams0aef64d2007-08-02 11:31:18 -04001175 case CMD_GET_HW_SPEC:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001176 ret = wlan_cmd_hw_spec(priv, cmdptr);
1177 break;
Dan Williams0aef64d2007-08-02 11:31:18 -04001178 case CMD_802_11_PS_MODE:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001179 ret = wlan_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
1180 break;
1181
Dan Williams0aef64d2007-08-02 11:31:18 -04001182 case CMD_802_11_SCAN:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001183 ret = libertas_cmd_80211_scan(priv, cmdptr, pdata_buf);
1184 break;
1185
Dan Williams0aef64d2007-08-02 11:31:18 -04001186 case CMD_MAC_CONTROL:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001187 ret = wlan_cmd_mac_control(priv, cmdptr);
1188 break;
1189
Dan Williams0aef64d2007-08-02 11:31:18 -04001190 case CMD_802_11_ASSOCIATE:
1191 case CMD_802_11_REASSOCIATE:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001192 ret = libertas_cmd_80211_associate(priv, cmdptr, pdata_buf);
1193 break;
1194
Dan Williams0aef64d2007-08-02 11:31:18 -04001195 case CMD_802_11_DEAUTHENTICATE:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001196 ret = libertas_cmd_80211_deauthenticate(priv, cmdptr);
1197 break;
1198
Dan Williams0aef64d2007-08-02 11:31:18 -04001199 case CMD_802_11_SET_WEP:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001200 ret = wlan_cmd_802_11_set_wep(priv, cmdptr, cmd_action, pdata_buf);
1201 break;
1202
Dan Williams0aef64d2007-08-02 11:31:18 -04001203 case CMD_802_11_AD_HOC_START:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001204 ret = libertas_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
1205 break;
Dan Williams0aef64d2007-08-02 11:31:18 -04001206 case CMD_CODE_DNLD:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001207 break;
1208
Dan Williams0aef64d2007-08-02 11:31:18 -04001209 case CMD_802_11_RESET:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001210 ret = wlan_cmd_802_11_reset(priv, cmdptr, cmd_action);
1211 break;
1212
Dan Williams0aef64d2007-08-02 11:31:18 -04001213 case CMD_802_11_GET_LOG:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001214 ret = wlan_cmd_802_11_get_log(priv, cmdptr);
1215 break;
1216
Dan Williams0aef64d2007-08-02 11:31:18 -04001217 case CMD_802_11_AUTHENTICATE:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001218 ret = libertas_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
1219 break;
1220
Dan Williams0aef64d2007-08-02 11:31:18 -04001221 case CMD_802_11_GET_STAT:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001222 ret = wlan_cmd_802_11_get_stat(priv, cmdptr);
1223 break;
1224
Dan Williams0aef64d2007-08-02 11:31:18 -04001225 case CMD_802_11_SNMP_MIB:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001226 ret = wlan_cmd_802_11_snmp_mib(priv, cmdptr,
1227 cmd_action, cmd_oid, pdata_buf);
1228 break;
1229
Dan Williams0aef64d2007-08-02 11:31:18 -04001230 case CMD_MAC_REG_ACCESS:
1231 case CMD_BBP_REG_ACCESS:
1232 case CMD_RF_REG_ACCESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001233 ret = wlan_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
1234 break;
1235
Dan Williams0aef64d2007-08-02 11:31:18 -04001236 case CMD_802_11_RF_CHANNEL:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001237 ret = wlan_cmd_802_11_rf_channel(priv, cmdptr,
1238 cmd_action, pdata_buf);
1239 break;
1240
Dan Williams0aef64d2007-08-02 11:31:18 -04001241 case CMD_802_11_RF_TX_POWER:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001242 ret = wlan_cmd_802_11_rf_tx_power(priv, cmdptr,
1243 cmd_action, pdata_buf);
1244 break;
1245
Dan Williams0aef64d2007-08-02 11:31:18 -04001246 case CMD_802_11_RADIO_CONTROL:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001247 ret = wlan_cmd_802_11_radio_control(priv, cmdptr, cmd_action);
1248 break;
1249
Dan Williams0aef64d2007-08-02 11:31:18 -04001250 case CMD_802_11_DATA_RATE:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001251 ret = wlan_cmd_802_11_data_rate(priv, cmdptr, cmd_action);
1252 break;
Dan Williams0aef64d2007-08-02 11:31:18 -04001253 case CMD_802_11_RATE_ADAPT_RATESET:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001254 ret = wlan_cmd_802_11_rate_adapt_rateset(priv,
1255 cmdptr, cmd_action);
1256 break;
1257
Dan Williams0aef64d2007-08-02 11:31:18 -04001258 case CMD_MAC_MULTICAST_ADR:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001259 ret = wlan_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
1260 break;
1261
Luis Carlos Cobo965f8bbc2007-08-02 13:16:55 -04001262 case CMD_802_11_MONITOR_MODE:
1263 ret = wlan_cmd_802_11_monitor_mode(priv, cmdptr,
1264 cmd_action, pdata_buf);
1265 break;
1266
Dan Williams0aef64d2007-08-02 11:31:18 -04001267 case CMD_802_11_AD_HOC_JOIN:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001268 ret = libertas_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
1269 break;
1270
Dan Williams0aef64d2007-08-02 11:31:18 -04001271 case CMD_802_11_RSSI:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001272 ret = wlan_cmd_802_11_rssi(priv, cmdptr);
1273 break;
1274
Dan Williams0aef64d2007-08-02 11:31:18 -04001275 case CMD_802_11_AD_HOC_STOP:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001276 ret = libertas_cmd_80211_ad_hoc_stop(priv, cmdptr);
1277 break;
1278
Dan Williams0aef64d2007-08-02 11:31:18 -04001279 case CMD_802_11_ENABLE_RSN:
Dan Williams90a42212007-05-25 23:01:24 -04001280 ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
1281 pdata_buf);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001282 break;
1283
Dan Williams0aef64d2007-08-02 11:31:18 -04001284 case CMD_802_11_KEY_MATERIAL:
Dan Williams90a42212007-05-25 23:01:24 -04001285 ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
1286 cmd_oid, pdata_buf);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001287 break;
1288
Dan Williams0aef64d2007-08-02 11:31:18 -04001289 case CMD_802_11_PAIRWISE_TSC:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001290 break;
Dan Williams0aef64d2007-08-02 11:31:18 -04001291 case CMD_802_11_GROUP_TSC:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001292 break;
1293
Dan Williams0aef64d2007-08-02 11:31:18 -04001294 case CMD_802_11_MAC_ADDRESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001295 ret = wlan_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
1296 break;
1297
Dan Williams0aef64d2007-08-02 11:31:18 -04001298 case CMD_802_11_EEPROM_ACCESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001299 ret = wlan_cmd_802_11_eeprom_access(priv, cmdptr,
1300 cmd_action, pdata_buf);
1301 break;
1302
Dan Williams0aef64d2007-08-02 11:31:18 -04001303 case CMD_802_11_SET_AFC:
1304 case CMD_802_11_GET_AFC:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001305
1306 cmdptr->command = cpu_to_le16(cmd_no);
David Woodhouse981f1872007-05-25 23:36:54 -04001307 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
1308 S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001309
1310 memmove(&cmdptr->params.afc,
1311 pdata_buf, sizeof(struct cmd_ds_802_11_afc));
1312
1313 ret = 0;
1314 goto done;
1315
Dan Williams0aef64d2007-08-02 11:31:18 -04001316 case CMD_802_11D_DOMAIN_INFO:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001317 ret = libertas_cmd_802_11d_domain_info(priv, cmdptr,
1318 cmd_no, cmd_action);
1319 break;
1320
Dan Williams0aef64d2007-08-02 11:31:18 -04001321 case CMD_802_11_SLEEP_PARAMS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001322 ret = wlan_cmd_802_11_sleep_params(priv, cmdptr, cmd_action);
1323 break;
Dan Williams0aef64d2007-08-02 11:31:18 -04001324 case CMD_802_11_INACTIVITY_TIMEOUT:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001325 ret = wlan_cmd_802_11_inactivity_timeout(priv, cmdptr,
1326 cmd_action, pdata_buf);
1327 libertas_set_cmd_ctrl_node(priv, cmdnode, 0, 0, pdata_buf);
1328 break;
1329
Dan Williams0aef64d2007-08-02 11:31:18 -04001330 case CMD_802_11_TPC_CFG:
1331 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001332 cmdptr->size =
1333 cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
1334 S_DS_GEN);
1335
1336 memmove(&cmdptr->params.tpccfg,
1337 pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
1338
1339 ret = 0;
1340 break;
Dan Williams0aef64d2007-08-02 11:31:18 -04001341 case CMD_802_11_LED_GPIO_CTRL:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001342 {
1343 struct mrvlietypes_ledgpio *gpio =
1344 (struct mrvlietypes_ledgpio*)
1345 cmdptr->params.ledgpio.data;
1346
1347 memmove(&cmdptr->params.ledgpio,
1348 pdata_buf,
1349 sizeof(struct cmd_ds_802_11_led_ctrl));
1350
1351 cmdptr->command =
Dan Williams0aef64d2007-08-02 11:31:18 -04001352 cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001353
1354#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
1355 cmdptr->size =
1356 cpu_to_le16(gpio->header.len + S_DS_GEN +
1357 ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
1358 gpio->header.len = cpu_to_le16(gpio->header.len);
1359
1360 ret = 0;
1361 break;
1362 }
Dan Williams0aef64d2007-08-02 11:31:18 -04001363 case CMD_802_11_PWR_CFG:
1364 cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001365 cmdptr->size =
1366 cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
1367 S_DS_GEN);
1368 memmove(&cmdptr->params.pwrcfg, pdata_buf,
1369 sizeof(struct cmd_ds_802_11_pwr_cfg));
1370
1371 ret = 0;
1372 break;
Dan Williams0aef64d2007-08-02 11:31:18 -04001373 case CMD_BT_ACCESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001374 ret = wlan_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
1375 break;
1376
Dan Williams0aef64d2007-08-02 11:31:18 -04001377 case CMD_FWT_ACCESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001378 ret = wlan_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
1379 break;
1380
Dan Williams0aef64d2007-08-02 11:31:18 -04001381 case CMD_MESH_ACCESS:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001382 ret = wlan_cmd_mesh_access(priv, cmdptr, cmd_action, pdata_buf);
1383 break;
1384
Dan Williams0aef64d2007-08-02 11:31:18 -04001385 case CMD_GET_TSF:
1386 cmdptr->command = cpu_to_le16(CMD_GET_TSF);
David Woodhouse981f1872007-05-25 23:36:54 -04001387 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
1388 S_DS_GEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001389 ret = 0;
1390 break;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001391 default:
Holger Schurig8ff12da2007-08-02 11:54:31 -04001392 lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001393 ret = -1;
1394 break;
1395 }
1396
1397 /* return error, since the command preparation failed */
1398 if (ret != 0) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001399 lbs_deb_host("PREP_CMD: command preparation failed\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001400 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1401 ret = -1;
1402 goto done;
1403 }
1404
1405 cmdnode->cmdwaitqwoken = 0;
1406
1407 libertas_queue_cmd(adapter, cmdnode, 1);
1408 adapter->nr_cmd_pending++;
Dan Williamsfe336152007-08-02 11:32:25 -04001409 wake_up_interruptible(&priv->waitq);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001410
Dan Williams0aef64d2007-08-02 11:31:18 -04001411 if (wait_option & CMD_OPTION_WAITFORRSP) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001412 lbs_deb_host("PREP_CMD: wait for response\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001413 might_sleep();
1414 wait_event_interruptible(cmdnode->cmdwait_q,
1415 cmdnode->cmdwaitqwoken);
1416 }
1417
1418 spin_lock_irqsave(&adapter->driver_lock, flags);
1419 if (adapter->cur_cmd_retcode) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001420 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001421 adapter->cur_cmd_retcode);
1422 adapter->cur_cmd_retcode = 0;
1423 ret = -1;
1424 }
1425 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1426
1427done:
Holger Schurig8ff12da2007-08-02 11:54:31 -04001428 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001429 return ret;
1430}
Holger Schurig084708b2007-05-25 12:37:58 -04001431EXPORT_SYMBOL_GPL(libertas_prepare_and_send_command);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001432
1433/**
1434 * @brief This function allocates the command buffer and link
1435 * it to command free queue.
1436 *
1437 * @param priv A pointer to wlan_private structure
1438 * @return 0 or -1
1439 */
1440int libertas_allocate_cmd_buffer(wlan_private * priv)
1441{
1442 int ret = 0;
1443 u32 ulbufsize;
1444 u32 i;
1445 struct cmd_ctrl_node *tempcmd_array;
1446 u8 *ptempvirtualaddr;
1447 wlan_adapter *adapter = priv->adapter;
1448
Holger Schurig8ff12da2007-08-02 11:54:31 -04001449 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001450
1451 /* Allocate and initialize cmdCtrlNode */
1452 ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
1453
Holger Schurigfb3dddf2007-05-25 11:58:22 -04001454 if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001455 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001456 ret = -1;
1457 goto done;
1458 }
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001459 adapter->cmd_array = tempcmd_array;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001460
1461 /* Allocate and initialize command buffers */
1462 ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1463 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
Holger Schurigfb3dddf2007-05-25 11:58:22 -04001464 if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001465 lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001466 ret = -1;
1467 goto done;
1468 }
1469
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001470 /* Update command buffer virtual */
1471 tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr;
1472 }
1473
1474 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1475 init_waitqueue_head(&tempcmd_array[i].cmdwait_q);
1476 libertas_cleanup_and_insert_cmd(priv, &tempcmd_array[i]);
1477 }
1478
1479 ret = 0;
Holger Schurig9012b282007-05-25 11:27:16 -04001480
1481done:
Holger Schurig8ff12da2007-08-02 11:54:31 -04001482 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001483 return ret;
1484}
1485
1486/**
1487 * @brief This function frees the command buffer.
1488 *
1489 * @param priv A pointer to wlan_private structure
1490 * @return 0 or -1
1491 */
1492int libertas_free_cmd_buffer(wlan_private * priv)
1493{
David Woodhouse981f1872007-05-25 23:36:54 -04001494 u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001495 unsigned int i;
1496 struct cmd_ctrl_node *tempcmd_array;
1497 wlan_adapter *adapter = priv->adapter;
1498
Holger Schurig8ff12da2007-08-02 11:54:31 -04001499 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001500
1501 /* need to check if cmd array is allocated or not */
1502 if (adapter->cmd_array == NULL) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001503 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001504 goto done;
1505 }
1506
1507 tempcmd_array = adapter->cmd_array;
1508
1509 /* Release shared memory buffers */
1510 ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1511 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1512 if (tempcmd_array[i].bufvirtualaddr) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001513 kfree(tempcmd_array[i].bufvirtualaddr);
1514 tempcmd_array[i].bufvirtualaddr = NULL;
1515 }
1516 }
1517
1518 /* Release cmd_ctrl_node */
1519 if (adapter->cmd_array) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001520 kfree(adapter->cmd_array);
1521 adapter->cmd_array = NULL;
1522 }
1523
1524done:
Holger Schurig8ff12da2007-08-02 11:54:31 -04001525 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001526 return 0;
1527}
1528
1529/**
1530 * @brief This function gets a free command node if available in
1531 * command free queue.
1532 *
1533 * @param priv A pointer to wlan_private structure
1534 * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1535 */
1536struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv)
1537{
1538 struct cmd_ctrl_node *tempnode;
1539 wlan_adapter *adapter = priv->adapter;
1540 unsigned long flags;
1541
Holger Schurig8ff12da2007-08-02 11:54:31 -04001542 lbs_deb_enter(LBS_DEB_HOST);
1543
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001544 if (!adapter)
1545 return NULL;
1546
1547 spin_lock_irqsave(&adapter->driver_lock, flags);
1548
1549 if (!list_empty(&adapter->cmdfreeq)) {
1550 tempnode = (struct cmd_ctrl_node *)adapter->cmdfreeq.next;
1551 list_del((struct list_head *)tempnode);
1552 } else {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001553 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001554 tempnode = NULL;
1555 }
1556
1557 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1558
Holger Schurig8ff12da2007-08-02 11:54:31 -04001559 if (tempnode)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001560 cleanup_cmdnode(tempnode);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001561
Holger Schurig8ff12da2007-08-02 11:54:31 -04001562 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001563 return tempnode;
1564}
1565
1566/**
1567 * @brief This function cleans command node.
1568 *
1569 * @param ptempnode A pointer to cmdCtrlNode structure
1570 * @return n/a
1571 */
1572static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode)
1573{
Holger Schurig8ff12da2007-08-02 11:54:31 -04001574 lbs_deb_enter(LBS_DEB_HOST);
1575
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001576 if (!ptempnode)
1577 return;
1578 ptempnode->cmdwaitqwoken = 1;
1579 wake_up_interruptible(&ptempnode->cmdwait_q);
1580 ptempnode->status = 0;
1581 ptempnode->cmd_oid = (u32) 0;
1582 ptempnode->wait_option = 0;
1583 ptempnode->pdata_buf = NULL;
1584
1585 if (ptempnode->bufvirtualaddr != NULL)
1586 memset(ptempnode->bufvirtualaddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
Holger Schurig8ff12da2007-08-02 11:54:31 -04001587
1588 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001589}
1590
1591/**
1592 * @brief This function initializes the command node.
1593 *
1594 * @param priv A pointer to wlan_private structure
1595 * @param ptempnode A pointer to cmd_ctrl_node structure
1596 * @param cmd_oid cmd oid: treated as sub command
1597 * @param wait_option wait option: wait response or not
1598 * @param pdata_buf A pointer to informaion buffer
1599 * @return 0 or -1
1600 */
1601void libertas_set_cmd_ctrl_node(wlan_private * priv,
1602 struct cmd_ctrl_node *ptempnode,
1603 u32 cmd_oid, u16 wait_option, void *pdata_buf)
1604{
Holger Schurig8ff12da2007-08-02 11:54:31 -04001605 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001606
1607 if (!ptempnode)
1608 return;
1609
1610 ptempnode->cmd_oid = cmd_oid;
1611 ptempnode->wait_option = wait_option;
1612 ptempnode->pdata_buf = pdata_buf;
1613
Holger Schurig8ff12da2007-08-02 11:54:31 -04001614 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001615}
1616
1617/**
1618 * @brief This function executes next command in command
1619 * pending queue. It will put fimware back to PS mode
1620 * if applicable.
1621 *
1622 * @param priv A pointer to wlan_private structure
1623 * @return 0 or -1
1624 */
1625int libertas_execute_next_command(wlan_private * priv)
1626{
1627 wlan_adapter *adapter = priv->adapter;
1628 struct cmd_ctrl_node *cmdnode = NULL;
1629 struct cmd_ds_command *cmdptr;
1630 unsigned long flags;
1631 int ret = 0;
1632
Holger Schurig8ff12da2007-08-02 11:54:31 -04001633 // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
1634 // only caller to us is libertas_thread() and we get even when a
1635 // data packet is received
1636 lbs_deb_enter(LBS_DEB_THREAD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001637
1638 spin_lock_irqsave(&adapter->driver_lock, flags);
1639
1640 if (adapter->cur_cmd) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001641 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001642 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1643 ret = -1;
1644 goto done;
1645 }
1646
1647 if (!list_empty(&adapter->cmdpendingq)) {
1648 cmdnode = (struct cmd_ctrl_node *)
1649 adapter->cmdpendingq.next;
1650 }
1651
1652 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1653
1654 if (cmdnode) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001655 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1656
1657 if (is_command_allowed_in_ps(cmdptr->command)) {
David Woodhouse981f1872007-05-25 23:36:54 -04001658 if ((adapter->psstate == PS_STATE_SLEEP) ||
1659 (adapter->psstate == PS_STATE_PRE_SLEEP)) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001660 lbs_deb_host(
1661 "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
David Woodhouse981f1872007-05-25 23:36:54 -04001662 le16_to_cpu(cmdptr->command),
1663 adapter->psstate);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001664 ret = -1;
1665 goto done;
1666 }
Holger Schurig8ff12da2007-08-02 11:54:31 -04001667 lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1668 "0x%04x in psstate %d\n",
David Woodhouse981f1872007-05-25 23:36:54 -04001669 le16_to_cpu(cmdptr->command),
1670 adapter->psstate);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001671 } else if (adapter->psstate != PS_STATE_FULL_POWER) {
1672 /*
1673 * 1. Non-PS command:
1674 * Queue it. set needtowakeup to TRUE if current state
1675 * is SLEEP, otherwise call libertas_ps_wakeup to send Exit_PS.
1676 * 2. PS command but not Exit_PS:
1677 * Ignore it.
1678 * 3. PS command Exit_PS:
1679 * Set needtowakeup to TRUE if current state is SLEEP,
1680 * otherwise send this command down to firmware
1681 * immediately.
1682 */
1683 if (cmdptr->command !=
Dan Williams0aef64d2007-08-02 11:31:18 -04001684 cpu_to_le16(CMD_802_11_PS_MODE)) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001685 /* Prepare to send Exit PS,
1686 * this non PS command will be sent later */
1687 if ((adapter->psstate == PS_STATE_SLEEP)
1688 || (adapter->psstate == PS_STATE_PRE_SLEEP)
1689 ) {
1690 /* w/ new scheme, it will not reach here.
1691 since it is blocked in main_thread. */
1692 adapter->needtowakeup = 1;
1693 } else
1694 libertas_ps_wakeup(priv, 0);
1695
1696 ret = 0;
1697 goto done;
1698 } else {
1699 /*
1700 * PS command. Ignore it if it is not Exit_PS.
1701 * otherwise send it down immediately.
1702 */
1703 struct cmd_ds_802_11_ps_mode *psm =
1704 &cmdptr->params.psmode;
1705
Holger Schurig8ff12da2007-08-02 11:54:31 -04001706 lbs_deb_host(
1707 "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001708 psm->action);
1709 if (psm->action !=
Dan Williams0aef64d2007-08-02 11:31:18 -04001710 cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001711 lbs_deb_host(
1712 "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001713 list_del((struct list_head *)cmdnode);
1714 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1715
1716 ret = 0;
1717 goto done;
1718 }
1719
David Woodhouse981f1872007-05-25 23:36:54 -04001720 if ((adapter->psstate == PS_STATE_SLEEP) ||
1721 (adapter->psstate == PS_STATE_PRE_SLEEP)) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001722 lbs_deb_host(
1723 "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001724 list_del((struct list_head *)cmdnode);
1725 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1726 adapter->needtowakeup = 1;
1727
1728 ret = 0;
1729 goto done;
1730 }
1731
Holger Schurig8ff12da2007-08-02 11:54:31 -04001732 lbs_deb_host(
1733 "EXEC_NEXT_CMD: sending EXIT_PS\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001734 }
1735 }
1736 list_del((struct list_head *)cmdnode);
Holger Schurig8ff12da2007-08-02 11:54:31 -04001737 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
David Woodhouse981f1872007-05-25 23:36:54 -04001738 le16_to_cpu(cmdptr->command));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001739 DownloadcommandToStation(priv, cmdnode);
1740 } else {
1741 /*
1742 * check if in power save mode, if yes, put the device back
1743 * to PS mode
1744 */
Dan Williams0aef64d2007-08-02 11:31:18 -04001745 if ((adapter->psmode != WLAN802_11POWERMODECAM) &&
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001746 (adapter->psstate == PS_STATE_FULL_POWER) &&
Dan Williams0aef64d2007-08-02 11:31:18 -04001747 (adapter->connect_status == LIBERTAS_CONNECTED)) {
David Woodhouse981f1872007-05-25 23:36:54 -04001748 if (adapter->secinfo.WPAenabled ||
1749 adapter->secinfo.WPA2enabled) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001750 /* check for valid WPA group keys */
David Woodhouse981f1872007-05-25 23:36:54 -04001751 if (adapter->wpa_mcast_key.len ||
1752 adapter->wpa_unicast_key.len) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001753 lbs_deb_host(
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001754 "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1755 " go back to PS_SLEEP");
1756 libertas_ps_sleep(priv, 0);
1757 }
1758 } else {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001759 lbs_deb_host(
1760 "EXEC_NEXT_CMD: cmdpendingq empty, "
1761 "go back to PS_SLEEP");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001762 libertas_ps_sleep(priv, 0);
1763 }
1764 }
1765 }
1766
1767 ret = 0;
1768done:
Holger Schurig8ff12da2007-08-02 11:54:31 -04001769 lbs_deb_leave(LBS_DEB_THREAD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001770 return ret;
1771}
1772
1773void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
1774{
1775 union iwreq_data iwrq;
1776 u8 buf[50];
1777
Holger Schurig8ff12da2007-08-02 11:54:31 -04001778 lbs_deb_enter(LBS_DEB_WEXT);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001779
1780 memset(&iwrq, 0, sizeof(union iwreq_data));
1781 memset(buf, 0, sizeof(buf));
1782
1783 snprintf(buf, sizeof(buf) - 1, "%s", str);
1784
1785 iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
1786
1787 /* Send Event to upper layer */
Holger Schurig8ff12da2007-08-02 11:54:31 -04001788 lbs_deb_wext("event indication string %s\n", (char *)buf);
1789 lbs_deb_wext("event indication length %d\n", iwrq.data.length);
1790 lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001791
Holger Schurig634b8f42007-05-25 13:05:16 -04001792 wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001793
Holger Schurig8ff12da2007-08-02 11:54:31 -04001794 lbs_deb_leave(LBS_DEB_WEXT);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001795}
1796
1797static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
1798{
1799 unsigned long flags;
1800 wlan_adapter *adapter = priv->adapter;
1801 int ret = 0;
1802
Holger Schurig8ff12da2007-08-02 11:54:31 -04001803 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001804
Holger Schurig8ff12da2007-08-02 11:54:31 -04001805 lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001806 size);
1807
Holger Schurig8ff12da2007-08-02 11:54:31 -04001808 lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001809
Holger Schurig208fdd22007-05-25 12:17:06 -04001810 ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
Holger Schurig634b8f42007-05-25 13:05:16 -04001811 priv->dnld_sent = DNLD_RES_RECEIVED;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001812
1813 spin_lock_irqsave(&adapter->driver_lock, flags);
1814 if (adapter->intcounter || adapter->currenttxskb)
Holger Schurig8ff12da2007-08-02 11:54:31 -04001815 lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001816 adapter->intcounter, adapter->currenttxskb);
1817 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1818
1819 if (ret) {
1820 lbs_pr_alert(
1821 "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
1822 } else {
1823 spin_lock_irqsave(&adapter->driver_lock, flags);
1824 if (!adapter->intcounter) {
1825 adapter->psstate = PS_STATE_SLEEP;
1826 } else {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001827 lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001828 adapter->intcounter);
1829 }
1830 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1831
Holger Schurig8ff12da2007-08-02 11:54:31 -04001832 lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001833 }
1834
Holger Schurig8ff12da2007-08-02 11:54:31 -04001835 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001836 return ret;
1837}
1838
1839void libertas_ps_sleep(wlan_private * priv, int wait_option)
1840{
Holger Schurig8ff12da2007-08-02 11:54:31 -04001841 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001842
1843 /*
1844 * PS is currently supported only in Infrastructure mode
1845 * Remove this check if it is to be supported in IBSS mode also
1846 */
1847
Dan Williams0aef64d2007-08-02 11:31:18 -04001848 libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1849 CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001850
Holger Schurig8ff12da2007-08-02 11:54:31 -04001851 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001852}
1853
1854/**
Holger Schurig8ff12da2007-08-02 11:54:31 -04001855 * @brief This function sends Exit_PS command to firmware.
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001856 *
1857 * @param priv A pointer to wlan_private structure
1858 * @param wait_option wait response or not
1859 * @return n/a
1860 */
1861void libertas_ps_wakeup(wlan_private * priv, int wait_option)
1862{
David Woodhouse981f1872007-05-25 23:36:54 -04001863 __le32 Localpsmode;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001864
Holger Schurig8ff12da2007-08-02 11:54:31 -04001865 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001866
Dan Williams0aef64d2007-08-02 11:31:18 -04001867 Localpsmode = cpu_to_le32(WLAN802_11POWERMODECAM);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001868
Dan Williams0aef64d2007-08-02 11:31:18 -04001869 libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1870 CMD_SUBCMD_EXIT_PS,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001871 wait_option, 0, &Localpsmode);
1872
Holger Schurig8ff12da2007-08-02 11:54:31 -04001873 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001874}
1875
1876/**
1877 * @brief This function checks condition and prepares to
1878 * send sleep confirm command to firmware if ok.
1879 *
1880 * @param priv A pointer to wlan_private structure
1881 * @param psmode Power Saving mode
1882 * @return n/a
1883 */
1884void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode)
1885{
1886 unsigned long flags =0;
1887 wlan_adapter *adapter = priv->adapter;
1888 u8 allowed = 1;
1889
Holger Schurig8ff12da2007-08-02 11:54:31 -04001890 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001891
Holger Schurig634b8f42007-05-25 13:05:16 -04001892 if (priv->dnld_sent) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001893 allowed = 0;
Holger Schurig8ff12da2007-08-02 11:54:31 -04001894 lbs_deb_host("dnld_sent was set");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001895 }
1896
1897 spin_lock_irqsave(&adapter->driver_lock, flags);
1898 if (adapter->cur_cmd) {
1899 allowed = 0;
Holger Schurig8ff12da2007-08-02 11:54:31 -04001900 lbs_deb_host("cur_cmd was set");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001901 }
1902 if (adapter->intcounter > 0) {
1903 allowed = 0;
Holger Schurig8ff12da2007-08-02 11:54:31 -04001904 lbs_deb_host("intcounter %d", adapter->intcounter);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001905 }
1906 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1907
1908 if (allowed) {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001909 lbs_deb_host("sending libertas_ps_confirm_sleep\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001910 sendconfirmsleep(priv, (u8 *) & adapter->libertas_ps_confirm_sleep,
1911 sizeof(struct PS_CMD_ConfirmSleep));
1912 } else {
Holger Schurig8ff12da2007-08-02 11:54:31 -04001913 lbs_deb_host("sleep confirm has been delayed\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001914 }
1915
Holger Schurig8ff12da2007-08-02 11:54:31 -04001916 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001917}