[PATCH] libertas: remove adapter->rxpd_rate
[deliverable/linux.git] / drivers / net / wireless / libertas / cmd.c
CommitLineData
876c9d3a
MT
1/**
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"
876c9d3a
MT
9#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[] = {
0aef64d7 18 CMD_802_11_RSSI,
876c9d3a
MT
19};
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 */
981f187b 28static u8 is_command_allowed_in_ps(__le16 command)
876c9d3a 29{
876c9d3a
MT
30 int i;
31
981f187b 32 for (i = 0; i < ARRAY_SIZE(commands_allowed_in_ps); i++) {
876c9d3a
MT
33 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
9012b28a 44 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 45
0aef64d7 46 cmd->command = cpu_to_le16(CMD_GET_HW_SPEC);
981f187b 47 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
876c9d3a
MT
48 memcpy(hwspec->permanentaddr, priv->adapter->current_addr, ETH_ALEN);
49
9012b28a 50 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
51 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;
876c9d3a
MT
59 wlan_adapter *adapter = priv->adapter;
60
9012b28a 61 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 62
0aef64d7 63 cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
981f187b
DW
64 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
65 S_DS_GEN);
876c9d3a
MT
66 psm->action = cpu_to_le16(cmd_action);
67 psm->multipledtim = 0;
981f187b 68 switch (cmd_action) {
0aef64d7 69 case CMD_SUBCMD_ENTER_PS:
9012b28a 70 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
8ff12da1 71 lbs_deb_cmd("locallisteninterval %d\n",
876c9d3a
MT
72 adapter->locallisteninterval);
73
74 psm->locallisteninterval =
75 cpu_to_le16(adapter->locallisteninterval);
76 psm->nullpktinterval =
77 cpu_to_le16(adapter->nullpktinterval);
78 psm->multipledtim =
79 cpu_to_le16(priv->adapter->multipledtim);
80 break;
81
0aef64d7 82 case CMD_SUBCMD_EXIT_PS:
9012b28a 83 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
876c9d3a
MT
84 break;
85
0aef64d7 86 case CMD_SUBCMD_SLEEP_CONFIRMED:
9012b28a 87 lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
876c9d3a
MT
88 break;
89
90 default:
91 break;
92 }
93
9012b28a 94 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
95 return 0;
96}
97
98static int wlan_cmd_802_11_inactivity_timeout(wlan_private * priv,
99 struct cmd_ds_command *cmd,
100 u16 cmd_action, void *pdata_buf)
101{
102 u16 *timeout = pdata_buf;
103
8ff12da1
HS
104 lbs_deb_enter(LBS_DEB_CMD);
105
0aef64d7 106 cmd->command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
876c9d3a
MT
107 cmd->size =
108 cpu_to_le16(sizeof(struct cmd_ds_802_11_inactivity_timeout)
109 + S_DS_GEN);
110
111 cmd->params.inactivity_timeout.action = cpu_to_le16(cmd_action);
112
113 if (cmd_action)
981f187b 114 cmd->params.inactivity_timeout.timeout = cpu_to_le16(*timeout);
876c9d3a
MT
115 else
116 cmd->params.inactivity_timeout.timeout = 0;
117
8ff12da1 118 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
119 return 0;
120}
121
122static int wlan_cmd_802_11_sleep_params(wlan_private * priv,
123 struct cmd_ds_command *cmd,
124 u16 cmd_action)
125{
126 wlan_adapter *adapter = priv->adapter;
127 struct cmd_ds_802_11_sleep_params *sp = &cmd->params.sleep_params;
128
9012b28a 129 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 130
981f187b
DW
131 cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
132 S_DS_GEN);
0aef64d7 133 cmd->command = cpu_to_le16(CMD_802_11_SLEEP_PARAMS);
876c9d3a 134
0aef64d7 135 if (cmd_action == CMD_ACT_GET) {
876c9d3a
MT
136 memset(&adapter->sp, 0, sizeof(struct sleep_params));
137 memset(sp, 0, sizeof(struct cmd_ds_802_11_sleep_params));
138 sp->action = cpu_to_le16(cmd_action);
0aef64d7 139 } else if (cmd_action == CMD_ACT_SET) {
876c9d3a
MT
140 sp->action = cpu_to_le16(cmd_action);
141 sp->error = cpu_to_le16(adapter->sp.sp_error);
142 sp->offset = cpu_to_le16(adapter->sp.sp_offset);
143 sp->stabletime = cpu_to_le16(adapter->sp.sp_stabletime);
144 sp->calcontrol = (u8) adapter->sp.sp_calcontrol;
145 sp->externalsleepclk = (u8) adapter->sp.sp_extsleepclk;
146 sp->reserved = cpu_to_le16(adapter->sp.sp_reserved);
147 }
148
9012b28a 149 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
150 return 0;
151}
152
153static int wlan_cmd_802_11_set_wep(wlan_private * priv,
154 struct cmd_ds_command *cmd,
155 u32 cmd_act,
156 void * pdata_buf)
157{
158 struct cmd_ds_802_11_set_wep *wep = &cmd->params.wep;
159 wlan_adapter *adapter = priv->adapter;
160 int ret = 0;
161 struct assoc_request * assoc_req = pdata_buf;
162
9012b28a 163 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 164
0aef64d7 165 cmd->command = cpu_to_le16(CMD_802_11_SET_WEP);
981f187b 166 cmd->size = cpu_to_le16(sizeof(*wep) + S_DS_GEN);
876c9d3a 167
0aef64d7 168 if (cmd_act == CMD_ACT_ADD) {
876c9d3a
MT
169 int i;
170
171 if (!assoc_req) {
9012b28a 172 lbs_deb_cmd("Invalid association request!");
876c9d3a
MT
173 ret = -1;
174 goto done;
175 }
176
0aef64d7 177 wep->action = cpu_to_le16(CMD_ACT_ADD);
876c9d3a
MT
178
179 /* default tx key index */
981f187b 180 wep->keyindex = cpu_to_le16((u16)(assoc_req->wep_tx_keyidx &
0aef64d7 181 (u32)CMD_WEP_KEY_INDEX_MASK));
876c9d3a 182
876c9d3a
MT
183 /* Copy key types and material to host command structure */
184 for (i = 0; i < 4; i++) {
1443b653 185 struct enc_key * pkey = &assoc_req->wep_keys[i];
876c9d3a
MT
186
187 switch (pkey->len) {
188 case KEY_LEN_WEP_40:
981f187b 189 wep->keytype[i] =
0aef64d7 190 cpu_to_le16(CMD_TYPE_WEP_40_BIT);
876c9d3a
MT
191 memmove(&wep->keymaterial[i], pkey->key,
192 pkey->len);
8ff12da1 193 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
876c9d3a
MT
194 break;
195 case KEY_LEN_WEP_104:
981f187b 196 wep->keytype[i] =
0aef64d7 197 cpu_to_le16(CMD_TYPE_WEP_104_BIT);
876c9d3a
MT
198 memmove(&wep->keymaterial[i], pkey->key,
199 pkey->len);
8ff12da1 200 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
876c9d3a
MT
201 break;
202 case 0:
203 break;
204 default:
8ff12da1 205 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
876c9d3a
MT
206 i, pkey->len);
207 ret = -1;
208 goto done;
209 break;
210 }
211 }
0aef64d7 212 } else if (cmd_act == CMD_ACT_REMOVE) {
876c9d3a 213 /* ACT_REMOVE clears _all_ WEP keys */
0aef64d7 214 wep->action = cpu_to_le16(CMD_ACT_REMOVE);
876c9d3a
MT
215
216 /* default tx key index */
981f187b 217 wep->keyindex = cpu_to_le16((u16)(adapter->wep_tx_keyidx &
0aef64d7 218 (u32)CMD_WEP_KEY_INDEX_MASK));
8ff12da1 219 lbs_deb_cmd("SET_WEP: remove key %d\n", adapter->wep_tx_keyidx);
876c9d3a
MT
220 }
221
222 ret = 0;
223
224done:
9012b28a 225 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
876c9d3a
MT
226 return ret;
227}
228
229static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
230 struct cmd_ds_command *cmd,
90a42210
DW
231 u16 cmd_action,
232 void * pdata_buf)
876c9d3a
MT
233{
234 struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn;
18c96c34 235 u32 * enable = pdata_buf;
90a42210
DW
236
237 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 238
0aef64d7 239 cmd->command = cpu_to_le16(CMD_802_11_ENABLE_RSN);
981f187b 240 cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN);
876c9d3a 241 penableRSN->action = cpu_to_le16(cmd_action);
18c96c34 242
0aef64d7 243 if (cmd_action == CMD_ACT_SET) {
18c96c34 244 if (*enable)
0aef64d7 245 penableRSN->enable = cpu_to_le16(CMD_ENABLE_RSN);
18c96c34 246 else
0aef64d7 247 penableRSN->enable = cpu_to_le16(CMD_DISABLE_RSN);
8ff12da1 248 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
876c9d3a
MT
249 }
250
90a42210 251 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
252 return 0;
253}
254
255
256static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
1443b653 257 struct enc_key * pkey)
876c9d3a 258{
8ff12da1
HS
259 lbs_deb_enter(LBS_DEB_CMD);
260
876c9d3a 261 if (pkey->flags & KEY_INFO_WPA_ENABLED) {
90a42210 262 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
876c9d3a 263 }
876c9d3a
MT
264 if (pkey->flags & KEY_INFO_WPA_UNICAST) {
265 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
90a42210
DW
266 }
267 if (pkey->flags & KEY_INFO_WPA_MCAST) {
876c9d3a
MT
268 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
269 }
270
271 pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
1443b653 272 pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
876c9d3a
MT
273 pkeyparamset->keylen = cpu_to_le16(pkey->len);
274 memcpy(pkeyparamset->key, pkey->key, pkey->len);
275 pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid)
276 + sizeof(pkeyparamset->keyinfo)
277 + sizeof(pkeyparamset->keylen)
278 + sizeof(pkeyparamset->key));
8ff12da1 279 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
280}
281
282static int wlan_cmd_802_11_key_material(wlan_private * priv,
283 struct cmd_ds_command *cmd,
284 u16 cmd_action,
285 u32 cmd_oid, void *pdata_buf)
286{
876c9d3a
MT
287 struct cmd_ds_802_11_key_material *pkeymaterial =
288 &cmd->params.keymaterial;
90a42210 289 struct assoc_request * assoc_req = pdata_buf;
876c9d3a
MT
290 int ret = 0;
291 int index = 0;
292
9012b28a 293 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 294
0aef64d7 295 cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL);
876c9d3a
MT
296 pkeymaterial->action = cpu_to_le16(cmd_action);
297
0aef64d7 298 if (cmd_action == CMD_ACT_GET) {
90a42210 299 cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
876c9d3a
MT
300 ret = 0;
301 goto done;
302 }
303
304 memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
305
90a42210 306 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
876c9d3a 307 set_one_wpa_key(&pkeymaterial->keyParamSet[index],
90a42210 308 &assoc_req->wpa_unicast_key);
876c9d3a
MT
309 index++;
310 }
311
90a42210 312 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
876c9d3a 313 set_one_wpa_key(&pkeymaterial->keyParamSet[index],
90a42210 314 &assoc_req->wpa_mcast_key);
876c9d3a
MT
315 index++;
316 }
317
318 cmd->size = cpu_to_le16( S_DS_GEN
90a42210
DW
319 + sizeof (pkeymaterial->action)
320 + (index * sizeof(struct MrvlIEtype_keyParamSet)));
876c9d3a
MT
321
322 ret = 0;
323
324done:
9012b28a 325 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
876c9d3a
MT
326 return ret;
327}
328
329static int wlan_cmd_802_11_reset(wlan_private * priv,
330 struct cmd_ds_command *cmd, int cmd_action)
331{
332 struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
333
8ff12da1
HS
334 lbs_deb_enter(LBS_DEB_CMD);
335
0aef64d7 336 cmd->command = cpu_to_le16(CMD_802_11_RESET);
876c9d3a
MT
337 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
338 reset->action = cpu_to_le16(cmd_action);
339
8ff12da1 340 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
341 return 0;
342}
343
344static int wlan_cmd_802_11_get_log(wlan_private * priv,
345 struct cmd_ds_command *cmd)
346{
8ff12da1 347 lbs_deb_enter(LBS_DEB_CMD);
0aef64d7 348 cmd->command = cpu_to_le16(CMD_802_11_GET_LOG);
876c9d3a
MT
349 cmd->size =
350 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN);
351
8ff12da1 352 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
353 return 0;
354}
355
356static int wlan_cmd_802_11_get_stat(wlan_private * priv,
357 struct cmd_ds_command *cmd)
358{
8ff12da1 359 lbs_deb_enter(LBS_DEB_CMD);
0aef64d7 360 cmd->command = cpu_to_le16(CMD_802_11_GET_STAT);
876c9d3a 361 cmd->size =
981f187b 362 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
876c9d3a 363
8ff12da1 364 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
365 return 0;
366}
367
368static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
369 struct cmd_ds_command *cmd,
370 int cmd_action,
371 int cmd_oid, void *pdata_buf)
372{
373 struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib;
374 wlan_adapter *adapter = priv->adapter;
375 u8 ucTemp;
376
9012b28a 377 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 378
9012b28a 379 lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
876c9d3a 380
0aef64d7 381 cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB);
981f187b 382 cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
876c9d3a
MT
383
384 switch (cmd_oid) {
385 case OID_802_11_INFRASTRUCTURE_MODE:
386 {
0dc5a290 387 u8 mode = (u8) (size_t) pdata_buf;
0aef64d7
DW
388 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
389 pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
876c9d3a 390 pSNMPMIB->bufsize = sizeof(u8);
0dc5a290 391 if (mode == IW_MODE_ADHOC) {
876c9d3a 392 ucTemp = SNMP_MIB_VALUE_ADHOC;
0dc5a290
DW
393 } else {
394 /* Infra and Auto modes */
395 ucTemp = SNMP_MIB_VALUE_INFRA;
396 }
876c9d3a
MT
397
398 memmove(pSNMPMIB->value, &ucTemp, sizeof(u8));
399
400 break;
401 }
402
403 case OID_802_11D_ENABLE:
404 {
405 u32 ulTemp;
406
0aef64d7 407 pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
876c9d3a 408
0aef64d7
DW
409 if (cmd_action == CMD_ACT_SET) {
410 pSNMPMIB->querytype = CMD_ACT_SET;
876c9d3a
MT
411 pSNMPMIB->bufsize = sizeof(u16);
412 ulTemp = *(u32 *)pdata_buf;
981f187b 413 *((__le16 *)(pSNMPMIB->value)) =
876c9d3a
MT
414 cpu_to_le16((u16) ulTemp);
415 }
416 break;
417 }
418
419 case OID_802_11_FRAGMENTATION_THRESHOLD:
420 {
421 u32 ulTemp;
422
0aef64d7 423 pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I);
876c9d3a 424
0aef64d7
DW
425 if (cmd_action == CMD_ACT_GET) {
426 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
427 } else if (cmd_action == CMD_ACT_SET) {
428 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
981f187b 429 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
876c9d3a 430 ulTemp = *((u32 *) pdata_buf);
981f187b 431 *((__le16 *)(pSNMPMIB->value)) =
876c9d3a
MT
432 cpu_to_le16((u16) ulTemp);
433
434 }
435
436 break;
437 }
438
439 case OID_802_11_RTS_THRESHOLD:
440 {
441
442 u32 ulTemp;
0aef64d7 443 pSNMPMIB->oid = le16_to_cpu((u16) RTSTHRESH_I);
876c9d3a 444
0aef64d7
DW
445 if (cmd_action == CMD_ACT_GET) {
446 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
447 } else if (cmd_action == CMD_ACT_SET) {
448 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
981f187b
DW
449 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
450 ulTemp = *((u32 *)pdata_buf);
451 *(__le16 *)(pSNMPMIB->value) =
876c9d3a
MT
452 cpu_to_le16((u16) ulTemp);
453
454 }
455 break;
456 }
457 case OID_802_11_TX_RETRYCOUNT:
0aef64d7 458 pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I);
876c9d3a 459
0aef64d7
DW
460 if (cmd_action == CMD_ACT_GET) {
461 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
462 } else if (cmd_action == CMD_ACT_SET) {
463 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
876c9d3a 464 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
981f187b 465 *((__le16 *)(pSNMPMIB->value)) =
876c9d3a
MT
466 cpu_to_le16((u16) adapter->txretrycount);
467 }
468
469 break;
470 default:
471 break;
472 }
473
9012b28a 474 lbs_deb_cmd(
876c9d3a 475 "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
981f187b
DW
476 le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
477 le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
876c9d3a 478
9012b28a 479 lbs_deb_cmd(
8ff12da1 480 "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
981f187b
DW
481 le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
482 le16_to_cpu(pSNMPMIB->bufsize),
483 le16_to_cpu(*(__le16 *) pSNMPMIB->value));
876c9d3a 484
9012b28a 485 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
486 return 0;
487}
488
489static int wlan_cmd_802_11_radio_control(wlan_private * priv,
490 struct cmd_ds_command *cmd,
491 int cmd_action)
492{
493 wlan_adapter *adapter = priv->adapter;
981f187b 494 struct cmd_ds_802_11_radio_control *pradiocontrol = &cmd->params.radio;
876c9d3a 495
9012b28a 496 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a
MT
497
498 cmd->size =
499 cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control)) +
500 S_DS_GEN);
0aef64d7 501 cmd->command = cpu_to_le16(CMD_802_11_RADIO_CONTROL);
876c9d3a
MT
502
503 pradiocontrol->action = cpu_to_le16(cmd_action);
504
505 switch (adapter->preamble) {
0aef64d7 506 case CMD_TYPE_SHORT_PREAMBLE:
876c9d3a
MT
507 pradiocontrol->control = cpu_to_le16(SET_SHORT_PREAMBLE);
508 break;
509
0aef64d7 510 case CMD_TYPE_LONG_PREAMBLE:
876c9d3a
MT
511 pradiocontrol->control = cpu_to_le16(SET_LONG_PREAMBLE);
512 break;
513
0aef64d7 514 case CMD_TYPE_AUTO_PREAMBLE:
876c9d3a
MT
515 default:
516 pradiocontrol->control = cpu_to_le16(SET_AUTO_PREAMBLE);
517 break;
518 }
519
520 if (adapter->radioon)
521 pradiocontrol->control |= cpu_to_le16(TURN_ON_RF);
522 else
523 pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF);
524
9012b28a 525 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
526 return 0;
527}
528
529static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
530 struct cmd_ds_command *cmd,
531 u16 cmd_action, void *pdata_buf)
532{
533
534 struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
535
9012b28a 536 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a
MT
537
538 cmd->size =
981f187b 539 cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
0aef64d7 540 cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER);
981f187b 541 prtp->action = cpu_to_le16(cmd_action);
876c9d3a 542
981f187b
DW
543 lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
544 le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
545 le16_to_cpu(prtp->action));
876c9d3a
MT
546
547 switch (cmd_action) {
0aef64d7
DW
548 case CMD_ACT_TX_POWER_OPT_GET:
549 prtp->action = cpu_to_le16(CMD_ACT_GET);
876c9d3a
MT
550 prtp->currentlevel = 0;
551 break;
552
0aef64d7
DW
553 case CMD_ACT_TX_POWER_OPT_SET_HIGH:
554 prtp->action = cpu_to_le16(CMD_ACT_SET);
555 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
876c9d3a
MT
556 break;
557
0aef64d7
DW
558 case CMD_ACT_TX_POWER_OPT_SET_MID:
559 prtp->action = cpu_to_le16(CMD_ACT_SET);
560 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID);
876c9d3a
MT
561 break;
562
0aef64d7
DW
563 case CMD_ACT_TX_POWER_OPT_SET_LOW:
564 prtp->action = cpu_to_le16(CMD_ACT_SET);
876c9d3a
MT
565 prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
566 break;
567 }
9012b28a
HS
568
569 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
570 return 0;
571}
572
876c9d3a
MT
573static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
574 struct cmd_ds_command *cmd,
575 u16 cmd_action)
576{
577 struct cmd_ds_802_11_rate_adapt_rateset
578 *rateadapt = &cmd->params.rateset;
579 wlan_adapter *adapter = priv->adapter;
580
8ff12da1 581 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a
MT
582 cmd->size =
583 cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset)
584 + S_DS_GEN);
0aef64d7 585 cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET);
876c9d3a 586
981f187b
DW
587 rateadapt->action = cpu_to_le16(cmd_action);
588 rateadapt->enablehwauto = cpu_to_le16(adapter->enablehwauto);
589 rateadapt->bitmap = cpu_to_le16(adapter->ratebitmap);
876c9d3a 590
9012b28a 591 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
592 return 0;
593}
594
595static int wlan_cmd_802_11_data_rate(wlan_private * priv,
596 struct cmd_ds_command *cmd,
597 u16 cmd_action)
598{
599 struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate;
600 wlan_adapter *adapter = priv->adapter;
876c9d3a 601
9012b28a 602 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 603
981f187b 604 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
876c9d3a 605 S_DS_GEN);
0aef64d7 606 cmd->command = cpu_to_le16(CMD_802_11_DATA_RATE);
876c9d3a 607 memset(pdatarate, 0, sizeof(struct cmd_ds_802_11_data_rate));
876c9d3a
MT
608 pdatarate->action = cpu_to_le16(cmd_action);
609
ffcae953 610 if (cmd_action == CMD_ACT_SET_TX_FIX_RATE) {
8c512765 611 pdatarate->rates[0] = libertas_data_rate_to_fw_index(adapter->cur_rate);
8ff12da1 612 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n",
8c512765 613 adapter->cur_rate);
ffcae953 614 } else if (cmd_action == CMD_ACT_SET_TX_AUTO) {
8ff12da1 615 lbs_deb_cmd("DATA_RATE: setting auto\n");
876c9d3a
MT
616 }
617
9012b28a 618 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
619 return 0;
620}
621
622static int wlan_cmd_mac_multicast_adr(wlan_private * priv,
623 struct cmd_ds_command *cmd,
624 u16 cmd_action)
625{
626 struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
627 wlan_adapter *adapter = priv->adapter;
628
8ff12da1 629 lbs_deb_enter(LBS_DEB_CMD);
981f187b 630 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
876c9d3a 631 S_DS_GEN);
0aef64d7 632 cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR);
876c9d3a 633
8ff12da1 634 lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs);
876c9d3a
MT
635 pMCastAdr->action = cpu_to_le16(cmd_action);
636 pMCastAdr->nr_of_adrs =
637 cpu_to_le16((u16) adapter->nr_of_multicastmacaddr);
638 memcpy(pMCastAdr->maclist, adapter->multicastlist,
639 adapter->nr_of_multicastmacaddr * ETH_ALEN);
640
8ff12da1 641 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
642 return 0;
643}
644
645static int wlan_cmd_802_11_rf_channel(wlan_private * priv,
646 struct cmd_ds_command *cmd,
647 int option, void *pdata_buf)
648{
649 struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
650
8ff12da1 651 lbs_deb_enter(LBS_DEB_CMD);
0aef64d7 652 cmd->command = cpu_to_le16(CMD_802_11_RF_CHANNEL);
981f187b
DW
653 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
654 S_DS_GEN);
876c9d3a 655
0aef64d7 656 if (option == CMD_OPT_802_11_RF_CHANNEL_SET) {
876c9d3a
MT
657 rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
658 }
659
660 rfchan->action = cpu_to_le16(option);
661
8ff12da1 662 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
663 return 0;
664}
665
666static int wlan_cmd_802_11_rssi(wlan_private * priv,
667 struct cmd_ds_command *cmd)
668{
669 wlan_adapter *adapter = priv->adapter;
670
8ff12da1 671 lbs_deb_enter(LBS_DEB_CMD);
0aef64d7 672 cmd->command = cpu_to_le16(CMD_802_11_RSSI);
981f187b
DW
673 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
674 cmd->params.rssi.N = cpu_to_le16(priv->adapter->bcn_avg_factor);
876c9d3a
MT
675
676 /* reset Beacon SNR/NF/RSSI values */
677 adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
678 adapter->SNR[TYPE_BEACON][TYPE_AVG] = 0;
679 adapter->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
680 adapter->NF[TYPE_BEACON][TYPE_AVG] = 0;
681 adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
682 adapter->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
683
8ff12da1 684 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
685 return 0;
686}
687
688static int wlan_cmd_reg_access(wlan_private * priv,
689 struct cmd_ds_command *cmdptr,
690 u8 cmd_action, void *pdata_buf)
691{
692 struct wlan_offset_value *offval;
693
9012b28a 694 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a
MT
695
696 offval = (struct wlan_offset_value *)pdata_buf;
697
698 switch (cmdptr->command) {
0aef64d7 699 case CMD_MAC_REG_ACCESS:
876c9d3a
MT
700 {
701 struct cmd_ds_mac_reg_access *macreg;
702
703 cmdptr->size =
981f187b
DW
704 cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
705 + S_DS_GEN);
876c9d3a
MT
706 macreg =
707 (struct cmd_ds_mac_reg_access *)&cmdptr->params.
708 macreg;
709
710 macreg->action = cpu_to_le16(cmd_action);
711 macreg->offset = cpu_to_le16((u16) offval->offset);
712 macreg->value = cpu_to_le32(offval->value);
713
714 break;
715 }
716
0aef64d7 717 case CMD_BBP_REG_ACCESS:
876c9d3a
MT
718 {
719 struct cmd_ds_bbp_reg_access *bbpreg;
720
721 cmdptr->size =
722 cpu_to_le16(sizeof
723 (struct cmd_ds_bbp_reg_access)
724 + S_DS_GEN);
725 bbpreg =
726 (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
727 bbpreg;
728
729 bbpreg->action = cpu_to_le16(cmd_action);
730 bbpreg->offset = cpu_to_le16((u16) offval->offset);
731 bbpreg->value = (u8) offval->value;
732
733 break;
734 }
735
0aef64d7 736 case CMD_RF_REG_ACCESS:
876c9d3a
MT
737 {
738 struct cmd_ds_rf_reg_access *rfreg;
739
740 cmdptr->size =
741 cpu_to_le16(sizeof
742 (struct cmd_ds_rf_reg_access) +
743 S_DS_GEN);
744 rfreg =
745 (struct cmd_ds_rf_reg_access *)&cmdptr->params.
746 rfreg;
747
748 rfreg->action = cpu_to_le16(cmd_action);
749 rfreg->offset = cpu_to_le16((u16) offval->offset);
750 rfreg->value = (u8) offval->value;
751
752 break;
753 }
754
755 default:
756 break;
757 }
758
9012b28a 759 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
760 return 0;
761}
762
763static int wlan_cmd_802_11_mac_address(wlan_private * priv,
764 struct cmd_ds_command *cmd,
765 u16 cmd_action)
766{
767 wlan_adapter *adapter = priv->adapter;
768
8ff12da1 769 lbs_deb_enter(LBS_DEB_CMD);
0aef64d7 770 cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
981f187b 771 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
876c9d3a
MT
772 S_DS_GEN);
773 cmd->result = 0;
774
775 cmd->params.macadd.action = cpu_to_le16(cmd_action);
776
0aef64d7 777 if (cmd_action == CMD_ACT_SET) {
876c9d3a
MT
778 memcpy(cmd->params.macadd.macadd,
779 adapter->current_addr, ETH_ALEN);
ece56191 780 lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", adapter->current_addr, 6);
876c9d3a
MT
781 }
782
8ff12da1 783 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
784 return 0;
785}
786
787static int wlan_cmd_802_11_eeprom_access(wlan_private * priv,
788 struct cmd_ds_command *cmd,
789 int cmd_action, void *pdata_buf)
790{
791 struct wlan_ioctl_regrdwr *ea = pdata_buf;
792
9012b28a 793 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 794
0aef64d7 795 cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
981f187b
DW
796 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
797 S_DS_GEN);
876c9d3a
MT
798 cmd->result = 0;
799
800 cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
801 cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
802 cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
803 cmd->params.rdeeprom.value = 0;
804
8ff12da1 805 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
806 return 0;
807}
808
809static int wlan_cmd_bt_access(wlan_private * priv,
810 struct cmd_ds_command *cmd,
811 u16 cmd_action, void *pdata_buf)
812{
813 struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
8ff12da1 814 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
876c9d3a 815
0aef64d7 816 cmd->command = cpu_to_le16(CMD_BT_ACCESS);
981f187b 817 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
876c9d3a
MT
818 cmd->result = 0;
819 bt_access->action = cpu_to_le16(cmd_action);
820
821 switch (cmd_action) {
0aef64d7 822 case CMD_ACT_BT_ACCESS_ADD:
876c9d3a 823 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
ece56191 824 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
876c9d3a 825 break;
0aef64d7 826 case CMD_ACT_BT_ACCESS_DEL:
876c9d3a 827 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
ece56191 828 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
876c9d3a 829 break;
0aef64d7 830 case CMD_ACT_BT_ACCESS_LIST:
876c9d3a
MT
831 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
832 break;
0aef64d7 833 case CMD_ACT_BT_ACCESS_RESET:
876c9d3a 834 break;
0aef64d7 835 case CMD_ACT_BT_ACCESS_SET_INVERT:
90e8eafc
LCC
836 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
837 break;
0aef64d7 838 case CMD_ACT_BT_ACCESS_GET_INVERT:
90e8eafc 839 break;
876c9d3a
MT
840 default:
841 break;
842 }
8ff12da1 843 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
844 return 0;
845}
846
847static int wlan_cmd_fwt_access(wlan_private * priv,
848 struct cmd_ds_command *cmd,
849 u16 cmd_action, void *pdata_buf)
850{
851 struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
8ff12da1 852 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
876c9d3a 853
0aef64d7 854 cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
981f187b 855 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
876c9d3a
MT
856 cmd->result = 0;
857
858 if (pdata_buf)
859 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
860 else
861 memset(fwt_access, 0, sizeof(*fwt_access));
862
863 fwt_access->action = cpu_to_le16(cmd_action);
864
8ff12da1 865 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
866 return 0;
867}
868
869static int wlan_cmd_mesh_access(wlan_private * priv,
870 struct cmd_ds_command *cmd,
871 u16 cmd_action, void *pdata_buf)
872{
873 struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh;
8ff12da1 874 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
876c9d3a 875
0aef64d7 876 cmd->command = cpu_to_le16(CMD_MESH_ACCESS);
981f187b 877 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN);
876c9d3a
MT
878 cmd->result = 0;
879
880 if (pdata_buf)
881 memcpy(mesh_access, pdata_buf, sizeof(*mesh_access));
882 else
883 memset(mesh_access, 0, sizeof(*mesh_access));
884
885 mesh_access->action = cpu_to_le16(cmd_action);
886
8ff12da1 887 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
888 return 0;
889}
890
891void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail)
892{
893 unsigned long flags;
894 struct cmd_ds_command *cmdptr;
895
8ff12da1 896 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a
MT
897
898 if (!cmdnode) {
8ff12da1 899 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
876c9d3a
MT
900 goto done;
901 }
902
903 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
904 if (!cmdptr) {
8ff12da1 905 lbs_deb_host("QUEUE_CMD: cmdptr is NULL\n");
876c9d3a
MT
906 goto done;
907 }
908
909 /* Exit_PS command needs to be queued in the header always. */
0aef64d7 910 if (cmdptr->command == CMD_802_11_PS_MODE) {
876c9d3a 911 struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode;
0aef64d7 912 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
876c9d3a
MT
913 if (adapter->psstate != PS_STATE_FULL_POWER)
914 addtail = 0;
915 }
916 }
917
918 spin_lock_irqsave(&adapter->driver_lock, flags);
919
920 if (addtail)
921 list_add_tail((struct list_head *)cmdnode,
922 &adapter->cmdpendingq);
923 else
924 list_add((struct list_head *)cmdnode, &adapter->cmdpendingq);
925
926 spin_unlock_irqrestore(&adapter->driver_lock, flags);
927
8ff12da1 928 lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
981f187b 929 le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command));
876c9d3a
MT
930
931done:
8ff12da1 932 lbs_deb_leave(LBS_DEB_HOST);
876c9d3a
MT
933}
934
935/*
936 * TODO: Fix the issue when DownloadcommandToStation is being called the
8ff12da1 937 * second time when the command times out. All the cmdptr->xxx are in little
876c9d3a
MT
938 * endian and therefore all the comparissions will fail.
939 * For now - we are not performing the endian conversion the second time - but
940 * for PS and DEEP_SLEEP we need to worry
941 */
942static int DownloadcommandToStation(wlan_private * priv,
943 struct cmd_ctrl_node *cmdnode)
944{
945 unsigned long flags;
946 struct cmd_ds_command *cmdptr;
947 wlan_adapter *adapter = priv->adapter;
948 int ret = 0;
949 u16 cmdsize;
950 u16 command;
951
8ff12da1 952 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a
MT
953
954 if (!adapter || !cmdnode) {
8ff12da1 955 lbs_deb_host("DNLD_CMD: adapter or cmdmode is NULL\n");
876c9d3a
MT
956 if (cmdnode) {
957 spin_lock_irqsave(&adapter->driver_lock, flags);
958 __libertas_cleanup_and_insert_cmd(priv, cmdnode);
959 spin_unlock_irqrestore(&adapter->driver_lock, flags);
960 }
961 ret = -1;
962 goto done;
963 }
964
965 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
966
876c9d3a
MT
967 spin_lock_irqsave(&adapter->driver_lock, flags);
968 if (!cmdptr || !cmdptr->size) {
8ff12da1 969 lbs_deb_host("DNLD_CMD: cmdptr is NULL or zero\n");
876c9d3a
MT
970 __libertas_cleanup_and_insert_cmd(priv, cmdnode);
971 spin_unlock_irqrestore(&adapter->driver_lock, flags);
972 ret = -1;
973 goto done;
974 }
975
976 adapter->cur_cmd = cmdnode;
977 adapter->cur_cmd_retcode = 0;
978 spin_unlock_irqrestore(&adapter->driver_lock, flags);
876c9d3a
MT
979
980 cmdsize = cmdptr->size;
876c9d3a
MT
981 command = cpu_to_le16(cmdptr->command);
982
8ff12da1
HS
983 lbs_deb_host("DNLD_CMD: command 0x%04x, size %d, jiffies %lu\n",
984 command, le16_to_cpu(cmdptr->size), jiffies);
985 lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", cmdnode->bufvirtualaddr, cmdsize);
986
876c9d3a
MT
987 cmdnode->cmdwaitqwoken = 0;
988 cmdsize = cpu_to_le16(cmdsize);
989
208fdd2f 990 ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
876c9d3a
MT
991
992 if (ret != 0) {
8ff12da1 993 lbs_deb_host("DNLD_CMD: hw_host_to_card failed\n");
876c9d3a
MT
994 spin_lock_irqsave(&adapter->driver_lock, flags);
995 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
996 adapter->cur_cmd = NULL;
997 spin_unlock_irqrestore(&adapter->driver_lock, flags);
998 ret = -1;
999 goto done;
1000 }
1001
8ff12da1 1002 lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", command, jiffies);
876c9d3a
MT
1003
1004 /* Setup the timer after transmit command */
0aef64d7
DW
1005 if (command == CMD_802_11_SCAN || command == CMD_802_11_AUTHENTICATE
1006 || command == CMD_802_11_ASSOCIATE)
876c9d3a
MT
1007 mod_timer(&adapter->command_timer, jiffies + (10*HZ));
1008 else
1009 mod_timer(&adapter->command_timer, jiffies + (5*HZ));
1010
1011 ret = 0;
1012
9012b28a 1013done:
8ff12da1 1014 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
876c9d3a
MT
1015 return ret;
1016}
1017
1018static int wlan_cmd_mac_control(wlan_private * priv,
1019 struct cmd_ds_command *cmd)
1020{
1021 struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
1022
9012b28a 1023 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 1024
0aef64d7 1025 cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
981f187b 1026 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
876c9d3a
MT
1027 mac->action = cpu_to_le16(priv->adapter->currentpacketfilter);
1028
8ff12da1 1029 lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
981f187b 1030 le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
876c9d3a 1031
9012b28a 1032 lbs_deb_leave(LBS_DEB_CMD);
876c9d3a
MT
1033 return 0;
1034}
1035
1036/**
1037 * This function inserts command node to cmdfreeq
1038 * after cleans it. Requires adapter->driver_lock held.
1039 */
1040void __libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
1041{
1042 wlan_adapter *adapter = priv->adapter;
1043
1044 if (!ptempcmd)
8ff12da1 1045 return;
876c9d3a
MT
1046
1047 cleanup_cmdnode(ptempcmd);
1048 list_add_tail((struct list_head *)ptempcmd, &adapter->cmdfreeq);
876c9d3a
MT
1049}
1050
ac558ca2 1051static void libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
876c9d3a
MT
1052{
1053 unsigned long flags;
1054
1055 spin_lock_irqsave(&priv->adapter->driver_lock, flags);
1056 __libertas_cleanup_and_insert_cmd(priv, ptempcmd);
1057 spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
1058}
1059
1060int libertas_set_radio_control(wlan_private * priv)
1061{
1062 int ret = 0;
1063
9012b28a 1064 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a
MT
1065
1066 ret = libertas_prepare_and_send_command(priv,
0aef64d7
DW
1067 CMD_802_11_RADIO_CONTROL,
1068 CMD_ACT_SET,
1069 CMD_OPTION_WAITFORRSP, 0, NULL);
876c9d3a 1070
8ff12da1 1071 lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n",
876c9d3a
MT
1072 priv->adapter->radioon, priv->adapter->preamble);
1073
9012b28a 1074 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
876c9d3a
MT
1075 return ret;
1076}
1077
1078int libertas_set_mac_packet_filter(wlan_private * priv)
1079{
1080 int ret = 0;
1081
9012b28a 1082 lbs_deb_enter(LBS_DEB_CMD);
876c9d3a 1083
876c9d3a
MT
1084 /* Send MAC control command to station */
1085 ret = libertas_prepare_and_send_command(priv,
0aef64d7 1086 CMD_MAC_CONTROL, 0, 0, 0, NULL);
876c9d3a 1087
9012b28a 1088 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
876c9d3a
MT
1089 return ret;
1090}
1091
1092/**
1093 * @brief This function prepare the command before send to firmware.
1094 *
1095 * @param priv A pointer to wlan_private structure
1096 * @param cmd_no command number
1097 * @param cmd_action command action: GET or SET
1098 * @param wait_option wait option: wait response or not
1099 * @param cmd_oid cmd oid: treated as sub command
1100 * @param pdata_buf A pointer to informaion buffer
1101 * @return 0 or -1
1102 */
1103int libertas_prepare_and_send_command(wlan_private * priv,
1104 u16 cmd_no,
1105 u16 cmd_action,
1106 u16 wait_option, u32 cmd_oid, void *pdata_buf)
1107{
1108 int ret = 0;
1109 wlan_adapter *adapter = priv->adapter;
1110 struct cmd_ctrl_node *cmdnode;
1111 struct cmd_ds_command *cmdptr;
1112 unsigned long flags;
1113
8ff12da1 1114 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a
MT
1115
1116 if (!adapter) {
8ff12da1 1117 lbs_deb_host("PREP_CMD: adapter is NULL\n");
876c9d3a
MT
1118 ret = -1;
1119 goto done;
1120 }
1121
1122 if (adapter->surpriseremoved) {
8ff12da1 1123 lbs_deb_host("PREP_CMD: card removed\n");
876c9d3a
MT
1124 ret = -1;
1125 goto done;
1126 }
1127
1128 cmdnode = libertas_get_free_cmd_ctrl_node(priv);
1129
1130 if (cmdnode == NULL) {
8ff12da1 1131 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
876c9d3a
MT
1132
1133 /* Wake up main thread to execute next command */
fe336150 1134 wake_up_interruptible(&priv->waitq);
876c9d3a
MT
1135 ret = -1;
1136 goto done;
1137 }
1138
1139 libertas_set_cmd_ctrl_node(priv, cmdnode, cmd_oid, wait_option, pdata_buf);
1140
1141 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1142
8ff12da1 1143 lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
876c9d3a
MT
1144
1145 if (!cmdptr) {
8ff12da1 1146 lbs_deb_host("PREP_CMD: cmdptr is NULL\n");
876c9d3a
MT
1147 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1148 ret = -1;
1149 goto done;
1150 }
1151
1152 /* Set sequence number, command and INT option */
1153 adapter->seqnum++;
1154 cmdptr->seqnum = cpu_to_le16(adapter->seqnum);
1155
981f187b 1156 cmdptr->command = cpu_to_le16(cmd_no);
876c9d3a
MT
1157 cmdptr->result = 0;
1158
1159 switch (cmd_no) {
0aef64d7 1160 case CMD_GET_HW_SPEC:
876c9d3a
MT
1161 ret = wlan_cmd_hw_spec(priv, cmdptr);
1162 break;
0aef64d7 1163 case CMD_802_11_PS_MODE:
876c9d3a
MT
1164 ret = wlan_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
1165 break;
1166
0aef64d7 1167 case CMD_802_11_SCAN:
876c9d3a
MT
1168 ret = libertas_cmd_80211_scan(priv, cmdptr, pdata_buf);
1169 break;
1170
0aef64d7 1171 case CMD_MAC_CONTROL:
876c9d3a
MT
1172 ret = wlan_cmd_mac_control(priv, cmdptr);
1173 break;
1174
0aef64d7
DW
1175 case CMD_802_11_ASSOCIATE:
1176 case CMD_802_11_REASSOCIATE:
876c9d3a
MT
1177 ret = libertas_cmd_80211_associate(priv, cmdptr, pdata_buf);
1178 break;
1179
0aef64d7 1180 case CMD_802_11_DEAUTHENTICATE:
876c9d3a
MT
1181 ret = libertas_cmd_80211_deauthenticate(priv, cmdptr);
1182 break;
1183
0aef64d7 1184 case CMD_802_11_SET_WEP:
876c9d3a
MT
1185 ret = wlan_cmd_802_11_set_wep(priv, cmdptr, cmd_action, pdata_buf);
1186 break;
1187
0aef64d7 1188 case CMD_802_11_AD_HOC_START:
876c9d3a
MT
1189 ret = libertas_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
1190 break;
0aef64d7 1191 case CMD_CODE_DNLD:
876c9d3a
MT
1192 break;
1193
0aef64d7 1194 case CMD_802_11_RESET:
876c9d3a
MT
1195 ret = wlan_cmd_802_11_reset(priv, cmdptr, cmd_action);
1196 break;
1197
0aef64d7 1198 case CMD_802_11_GET_LOG:
876c9d3a
MT
1199 ret = wlan_cmd_802_11_get_log(priv, cmdptr);
1200 break;
1201
0aef64d7 1202 case CMD_802_11_AUTHENTICATE:
876c9d3a
MT
1203 ret = libertas_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
1204 break;
1205
0aef64d7 1206 case CMD_802_11_GET_STAT:
876c9d3a
MT
1207 ret = wlan_cmd_802_11_get_stat(priv, cmdptr);
1208 break;
1209
0aef64d7 1210 case CMD_802_11_SNMP_MIB:
876c9d3a
MT
1211 ret = wlan_cmd_802_11_snmp_mib(priv, cmdptr,
1212 cmd_action, cmd_oid, pdata_buf);
1213 break;
1214
0aef64d7
DW
1215 case CMD_MAC_REG_ACCESS:
1216 case CMD_BBP_REG_ACCESS:
1217 case CMD_RF_REG_ACCESS:
876c9d3a
MT
1218 ret = wlan_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
1219 break;
1220
0aef64d7 1221 case CMD_802_11_RF_CHANNEL:
876c9d3a
MT
1222 ret = wlan_cmd_802_11_rf_channel(priv, cmdptr,
1223 cmd_action, pdata_buf);
1224 break;
1225
0aef64d7 1226 case CMD_802_11_RF_TX_POWER:
876c9d3a
MT
1227 ret = wlan_cmd_802_11_rf_tx_power(priv, cmdptr,
1228 cmd_action, pdata_buf);
1229 break;
1230
0aef64d7 1231 case CMD_802_11_RADIO_CONTROL:
876c9d3a
MT
1232 ret = wlan_cmd_802_11_radio_control(priv, cmdptr, cmd_action);
1233 break;
1234
0aef64d7 1235 case CMD_802_11_DATA_RATE:
876c9d3a
MT
1236 ret = wlan_cmd_802_11_data_rate(priv, cmdptr, cmd_action);
1237 break;
0aef64d7 1238 case CMD_802_11_RATE_ADAPT_RATESET:
876c9d3a
MT
1239 ret = wlan_cmd_802_11_rate_adapt_rateset(priv,
1240 cmdptr, cmd_action);
1241 break;
1242
0aef64d7 1243 case CMD_MAC_MULTICAST_ADR:
876c9d3a
MT
1244 ret = wlan_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
1245 break;
1246
0aef64d7 1247 case CMD_802_11_AD_HOC_JOIN:
876c9d3a
MT
1248 ret = libertas_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
1249 break;
1250
0aef64d7 1251 case CMD_802_11_RSSI:
876c9d3a
MT
1252 ret = wlan_cmd_802_11_rssi(priv, cmdptr);
1253 break;
1254
0aef64d7 1255 case CMD_802_11_AD_HOC_STOP:
876c9d3a
MT
1256 ret = libertas_cmd_80211_ad_hoc_stop(priv, cmdptr);
1257 break;
1258
0aef64d7 1259 case CMD_802_11_ENABLE_RSN:
90a42210
DW
1260 ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
1261 pdata_buf);
876c9d3a
MT
1262 break;
1263
0aef64d7 1264 case CMD_802_11_KEY_MATERIAL:
90a42210
DW
1265 ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
1266 cmd_oid, pdata_buf);
876c9d3a
MT
1267 break;
1268
0aef64d7 1269 case CMD_802_11_PAIRWISE_TSC:
876c9d3a 1270 break;
0aef64d7 1271 case CMD_802_11_GROUP_TSC:
876c9d3a
MT
1272 break;
1273
0aef64d7 1274 case CMD_802_11_MAC_ADDRESS:
876c9d3a
MT
1275 ret = wlan_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
1276 break;
1277
0aef64d7 1278 case CMD_802_11_EEPROM_ACCESS:
876c9d3a
MT
1279 ret = wlan_cmd_802_11_eeprom_access(priv, cmdptr,
1280 cmd_action, pdata_buf);
1281 break;
1282
0aef64d7
DW
1283 case CMD_802_11_SET_AFC:
1284 case CMD_802_11_GET_AFC:
876c9d3a
MT
1285
1286 cmdptr->command = cpu_to_le16(cmd_no);
981f187b
DW
1287 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
1288 S_DS_GEN);
876c9d3a
MT
1289
1290 memmove(&cmdptr->params.afc,
1291 pdata_buf, sizeof(struct cmd_ds_802_11_afc));
1292
1293 ret = 0;
1294 goto done;
1295
0aef64d7 1296 case CMD_802_11D_DOMAIN_INFO:
876c9d3a
MT
1297 ret = libertas_cmd_802_11d_domain_info(priv, cmdptr,
1298 cmd_no, cmd_action);
1299 break;
1300
0aef64d7 1301 case CMD_802_11_SLEEP_PARAMS:
876c9d3a
MT
1302 ret = wlan_cmd_802_11_sleep_params(priv, cmdptr, cmd_action);
1303 break;
0aef64d7 1304 case CMD_802_11_INACTIVITY_TIMEOUT:
876c9d3a
MT
1305 ret = wlan_cmd_802_11_inactivity_timeout(priv, cmdptr,
1306 cmd_action, pdata_buf);
1307 libertas_set_cmd_ctrl_node(priv, cmdnode, 0, 0, pdata_buf);
1308 break;
1309
0aef64d7
DW
1310 case CMD_802_11_TPC_CFG:
1311 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
876c9d3a
MT
1312 cmdptr->size =
1313 cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
1314 S_DS_GEN);
1315
1316 memmove(&cmdptr->params.tpccfg,
1317 pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
1318
1319 ret = 0;
1320 break;
0aef64d7 1321 case CMD_802_11_LED_GPIO_CTRL:
876c9d3a
MT
1322 {
1323 struct mrvlietypes_ledgpio *gpio =
1324 (struct mrvlietypes_ledgpio*)
1325 cmdptr->params.ledgpio.data;
1326
1327 memmove(&cmdptr->params.ledgpio,
1328 pdata_buf,
1329 sizeof(struct cmd_ds_802_11_led_ctrl));
1330
1331 cmdptr->command =
0aef64d7 1332 cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
876c9d3a
MT
1333
1334#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
1335 cmdptr->size =
1336 cpu_to_le16(gpio->header.len + S_DS_GEN +
1337 ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
1338 gpio->header.len = cpu_to_le16(gpio->header.len);
1339
1340 ret = 0;
1341 break;
1342 }
0aef64d7
DW
1343 case CMD_802_11_PWR_CFG:
1344 cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
876c9d3a
MT
1345 cmdptr->size =
1346 cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
1347 S_DS_GEN);
1348 memmove(&cmdptr->params.pwrcfg, pdata_buf,
1349 sizeof(struct cmd_ds_802_11_pwr_cfg));
1350
1351 ret = 0;
1352 break;
0aef64d7 1353 case CMD_BT_ACCESS:
876c9d3a
MT
1354 ret = wlan_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
1355 break;
1356
0aef64d7 1357 case CMD_FWT_ACCESS:
876c9d3a
MT
1358 ret = wlan_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
1359 break;
1360
0aef64d7 1361 case CMD_MESH_ACCESS:
876c9d3a
MT
1362 ret = wlan_cmd_mesh_access(priv, cmdptr, cmd_action, pdata_buf);
1363 break;
1364
0aef64d7
DW
1365 case CMD_GET_TSF:
1366 cmdptr->command = cpu_to_le16(CMD_GET_TSF);
981f187b
DW
1367 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
1368 S_DS_GEN);
876c9d3a
MT
1369 ret = 0;
1370 break;
876c9d3a 1371 default:
8ff12da1 1372 lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no);
876c9d3a
MT
1373 ret = -1;
1374 break;
1375 }
1376
1377 /* return error, since the command preparation failed */
1378 if (ret != 0) {
8ff12da1 1379 lbs_deb_host("PREP_CMD: command preparation failed\n");
876c9d3a
MT
1380 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1381 ret = -1;
1382 goto done;
1383 }
1384
1385 cmdnode->cmdwaitqwoken = 0;
1386
1387 libertas_queue_cmd(adapter, cmdnode, 1);
1388 adapter->nr_cmd_pending++;
fe336150 1389 wake_up_interruptible(&priv->waitq);
876c9d3a 1390
0aef64d7 1391 if (wait_option & CMD_OPTION_WAITFORRSP) {
8ff12da1 1392 lbs_deb_host("PREP_CMD: wait for response\n");
876c9d3a
MT
1393 might_sleep();
1394 wait_event_interruptible(cmdnode->cmdwait_q,
1395 cmdnode->cmdwaitqwoken);
1396 }
1397
1398 spin_lock_irqsave(&adapter->driver_lock, flags);
1399 if (adapter->cur_cmd_retcode) {
8ff12da1 1400 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
876c9d3a
MT
1401 adapter->cur_cmd_retcode);
1402 adapter->cur_cmd_retcode = 0;
1403 ret = -1;
1404 }
1405 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1406
1407done:
8ff12da1 1408 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
876c9d3a
MT
1409 return ret;
1410}
084708b6 1411EXPORT_SYMBOL_GPL(libertas_prepare_and_send_command);
876c9d3a
MT
1412
1413/**
1414 * @brief This function allocates the command buffer and link
1415 * it to command free queue.
1416 *
1417 * @param priv A pointer to wlan_private structure
1418 * @return 0 or -1
1419 */
1420int libertas_allocate_cmd_buffer(wlan_private * priv)
1421{
1422 int ret = 0;
1423 u32 ulbufsize;
1424 u32 i;
1425 struct cmd_ctrl_node *tempcmd_array;
1426 u8 *ptempvirtualaddr;
1427 wlan_adapter *adapter = priv->adapter;
1428
8ff12da1 1429 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a
MT
1430
1431 /* Allocate and initialize cmdCtrlNode */
1432 ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
1433
fb3dddf2 1434 if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) {
8ff12da1 1435 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
876c9d3a
MT
1436 ret = -1;
1437 goto done;
1438 }
876c9d3a 1439 adapter->cmd_array = tempcmd_array;
876c9d3a
MT
1440
1441 /* Allocate and initialize command buffers */
1442 ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1443 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
fb3dddf2 1444 if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) {
8ff12da1 1445 lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
876c9d3a
MT
1446 ret = -1;
1447 goto done;
1448 }
1449
876c9d3a
MT
1450 /* Update command buffer virtual */
1451 tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr;
1452 }
1453
1454 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1455 init_waitqueue_head(&tempcmd_array[i].cmdwait_q);
1456 libertas_cleanup_and_insert_cmd(priv, &tempcmd_array[i]);
1457 }
1458
1459 ret = 0;
9012b28a
HS
1460
1461done:
8ff12da1 1462 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
876c9d3a
MT
1463 return ret;
1464}
1465
1466/**
1467 * @brief This function frees the command buffer.
1468 *
1469 * @param priv A pointer to wlan_private structure
1470 * @return 0 or -1
1471 */
1472int libertas_free_cmd_buffer(wlan_private * priv)
1473{
981f187b 1474 u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */
876c9d3a
MT
1475 unsigned int i;
1476 struct cmd_ctrl_node *tempcmd_array;
1477 wlan_adapter *adapter = priv->adapter;
1478
8ff12da1 1479 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a
MT
1480
1481 /* need to check if cmd array is allocated or not */
1482 if (adapter->cmd_array == NULL) {
8ff12da1 1483 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
876c9d3a
MT
1484 goto done;
1485 }
1486
1487 tempcmd_array = adapter->cmd_array;
1488
1489 /* Release shared memory buffers */
1490 ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
1491 for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1492 if (tempcmd_array[i].bufvirtualaddr) {
876c9d3a
MT
1493 kfree(tempcmd_array[i].bufvirtualaddr);
1494 tempcmd_array[i].bufvirtualaddr = NULL;
1495 }
1496 }
1497
1498 /* Release cmd_ctrl_node */
1499 if (adapter->cmd_array) {
876c9d3a
MT
1500 kfree(adapter->cmd_array);
1501 adapter->cmd_array = NULL;
1502 }
1503
1504done:
8ff12da1 1505 lbs_deb_leave(LBS_DEB_HOST);
876c9d3a
MT
1506 return 0;
1507}
1508
1509/**
1510 * @brief This function gets a free command node if available in
1511 * command free queue.
1512 *
1513 * @param priv A pointer to wlan_private structure
1514 * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1515 */
1516struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv)
1517{
1518 struct cmd_ctrl_node *tempnode;
1519 wlan_adapter *adapter = priv->adapter;
1520 unsigned long flags;
1521
8ff12da1
HS
1522 lbs_deb_enter(LBS_DEB_HOST);
1523
876c9d3a
MT
1524 if (!adapter)
1525 return NULL;
1526
1527 spin_lock_irqsave(&adapter->driver_lock, flags);
1528
1529 if (!list_empty(&adapter->cmdfreeq)) {
1530 tempnode = (struct cmd_ctrl_node *)adapter->cmdfreeq.next;
1531 list_del((struct list_head *)tempnode);
1532 } else {
8ff12da1 1533 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
876c9d3a
MT
1534 tempnode = NULL;
1535 }
1536
1537 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1538
8ff12da1 1539 if (tempnode)
876c9d3a 1540 cleanup_cmdnode(tempnode);
876c9d3a 1541
8ff12da1 1542 lbs_deb_leave(LBS_DEB_HOST);
876c9d3a
MT
1543 return tempnode;
1544}
1545
1546/**
1547 * @brief This function cleans command node.
1548 *
1549 * @param ptempnode A pointer to cmdCtrlNode structure
1550 * @return n/a
1551 */
1552static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode)
1553{
8ff12da1
HS
1554 lbs_deb_enter(LBS_DEB_HOST);
1555
876c9d3a
MT
1556 if (!ptempnode)
1557 return;
1558 ptempnode->cmdwaitqwoken = 1;
1559 wake_up_interruptible(&ptempnode->cmdwait_q);
1560 ptempnode->status = 0;
1561 ptempnode->cmd_oid = (u32) 0;
1562 ptempnode->wait_option = 0;
1563 ptempnode->pdata_buf = NULL;
1564
1565 if (ptempnode->bufvirtualaddr != NULL)
1566 memset(ptempnode->bufvirtualaddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
8ff12da1
HS
1567
1568 lbs_deb_leave(LBS_DEB_HOST);
876c9d3a
MT
1569}
1570
1571/**
1572 * @brief This function initializes the command node.
1573 *
1574 * @param priv A pointer to wlan_private structure
1575 * @param ptempnode A pointer to cmd_ctrl_node structure
1576 * @param cmd_oid cmd oid: treated as sub command
1577 * @param wait_option wait option: wait response or not
1578 * @param pdata_buf A pointer to informaion buffer
1579 * @return 0 or -1
1580 */
1581void libertas_set_cmd_ctrl_node(wlan_private * priv,
1582 struct cmd_ctrl_node *ptempnode,
1583 u32 cmd_oid, u16 wait_option, void *pdata_buf)
1584{
8ff12da1 1585 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a
MT
1586
1587 if (!ptempnode)
1588 return;
1589
1590 ptempnode->cmd_oid = cmd_oid;
1591 ptempnode->wait_option = wait_option;
1592 ptempnode->pdata_buf = pdata_buf;
1593
8ff12da1 1594 lbs_deb_leave(LBS_DEB_HOST);
876c9d3a
MT
1595}
1596
1597/**
1598 * @brief This function executes next command in command
1599 * pending queue. It will put fimware back to PS mode
1600 * if applicable.
1601 *
1602 * @param priv A pointer to wlan_private structure
1603 * @return 0 or -1
1604 */
1605int libertas_execute_next_command(wlan_private * priv)
1606{
1607 wlan_adapter *adapter = priv->adapter;
1608 struct cmd_ctrl_node *cmdnode = NULL;
1609 struct cmd_ds_command *cmdptr;
1610 unsigned long flags;
1611 int ret = 0;
1612
8ff12da1
HS
1613 // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
1614 // only caller to us is libertas_thread() and we get even when a
1615 // data packet is received
1616 lbs_deb_enter(LBS_DEB_THREAD);
876c9d3a
MT
1617
1618 spin_lock_irqsave(&adapter->driver_lock, flags);
1619
1620 if (adapter->cur_cmd) {
8ff12da1 1621 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
876c9d3a
MT
1622 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1623 ret = -1;
1624 goto done;
1625 }
1626
1627 if (!list_empty(&adapter->cmdpendingq)) {
1628 cmdnode = (struct cmd_ctrl_node *)
1629 adapter->cmdpendingq.next;
1630 }
1631
1632 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1633
1634 if (cmdnode) {
876c9d3a
MT
1635 cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
1636
1637 if (is_command_allowed_in_ps(cmdptr->command)) {
981f187b
DW
1638 if ((adapter->psstate == PS_STATE_SLEEP) ||
1639 (adapter->psstate == PS_STATE_PRE_SLEEP)) {
8ff12da1
HS
1640 lbs_deb_host(
1641 "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
981f187b
DW
1642 le16_to_cpu(cmdptr->command),
1643 adapter->psstate);
876c9d3a
MT
1644 ret = -1;
1645 goto done;
1646 }
8ff12da1
HS
1647 lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1648 "0x%04x in psstate %d\n",
981f187b
DW
1649 le16_to_cpu(cmdptr->command),
1650 adapter->psstate);
876c9d3a
MT
1651 } else if (adapter->psstate != PS_STATE_FULL_POWER) {
1652 /*
1653 * 1. Non-PS command:
1654 * Queue it. set needtowakeup to TRUE if current state
1655 * is SLEEP, otherwise call libertas_ps_wakeup to send Exit_PS.
1656 * 2. PS command but not Exit_PS:
1657 * Ignore it.
1658 * 3. PS command Exit_PS:
1659 * Set needtowakeup to TRUE if current state is SLEEP,
1660 * otherwise send this command down to firmware
1661 * immediately.
1662 */
1663 if (cmdptr->command !=
0aef64d7 1664 cpu_to_le16(CMD_802_11_PS_MODE)) {
876c9d3a
MT
1665 /* Prepare to send Exit PS,
1666 * this non PS command will be sent later */
1667 if ((adapter->psstate == PS_STATE_SLEEP)
1668 || (adapter->psstate == PS_STATE_PRE_SLEEP)
1669 ) {
1670 /* w/ new scheme, it will not reach here.
1671 since it is blocked in main_thread. */
1672 adapter->needtowakeup = 1;
1673 } else
1674 libertas_ps_wakeup(priv, 0);
1675
1676 ret = 0;
1677 goto done;
1678 } else {
1679 /*
1680 * PS command. Ignore it if it is not Exit_PS.
1681 * otherwise send it down immediately.
1682 */
1683 struct cmd_ds_802_11_ps_mode *psm =
1684 &cmdptr->params.psmode;
1685
8ff12da1
HS
1686 lbs_deb_host(
1687 "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
876c9d3a
MT
1688 psm->action);
1689 if (psm->action !=
0aef64d7 1690 cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
8ff12da1
HS
1691 lbs_deb_host(
1692 "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
876c9d3a
MT
1693 list_del((struct list_head *)cmdnode);
1694 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1695
1696 ret = 0;
1697 goto done;
1698 }
1699
981f187b
DW
1700 if ((adapter->psstate == PS_STATE_SLEEP) ||
1701 (adapter->psstate == PS_STATE_PRE_SLEEP)) {
8ff12da1
HS
1702 lbs_deb_host(
1703 "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
876c9d3a
MT
1704 list_del((struct list_head *)cmdnode);
1705 libertas_cleanup_and_insert_cmd(priv, cmdnode);
1706 adapter->needtowakeup = 1;
1707
1708 ret = 0;
1709 goto done;
1710 }
1711
8ff12da1
HS
1712 lbs_deb_host(
1713 "EXEC_NEXT_CMD: sending EXIT_PS\n");
876c9d3a
MT
1714 }
1715 }
1716 list_del((struct list_head *)cmdnode);
8ff12da1 1717 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
981f187b 1718 le16_to_cpu(cmdptr->command));
876c9d3a
MT
1719 DownloadcommandToStation(priv, cmdnode);
1720 } else {
1721 /*
1722 * check if in power save mode, if yes, put the device back
1723 * to PS mode
1724 */
0aef64d7 1725 if ((adapter->psmode != WLAN802_11POWERMODECAM) &&
876c9d3a 1726 (adapter->psstate == PS_STATE_FULL_POWER) &&
0aef64d7 1727 (adapter->connect_status == LIBERTAS_CONNECTED)) {
981f187b
DW
1728 if (adapter->secinfo.WPAenabled ||
1729 adapter->secinfo.WPA2enabled) {
876c9d3a 1730 /* check for valid WPA group keys */
981f187b
DW
1731 if (adapter->wpa_mcast_key.len ||
1732 adapter->wpa_unicast_key.len) {
8ff12da1 1733 lbs_deb_host(
876c9d3a
MT
1734 "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1735 " go back to PS_SLEEP");
1736 libertas_ps_sleep(priv, 0);
1737 }
1738 } else {
8ff12da1
HS
1739 lbs_deb_host(
1740 "EXEC_NEXT_CMD: cmdpendingq empty, "
1741 "go back to PS_SLEEP");
876c9d3a
MT
1742 libertas_ps_sleep(priv, 0);
1743 }
1744 }
1745 }
1746
1747 ret = 0;
1748done:
8ff12da1 1749 lbs_deb_leave(LBS_DEB_THREAD);
876c9d3a
MT
1750 return ret;
1751}
1752
1753void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
1754{
1755 union iwreq_data iwrq;
1756 u8 buf[50];
1757
8ff12da1 1758 lbs_deb_enter(LBS_DEB_WEXT);
876c9d3a
MT
1759
1760 memset(&iwrq, 0, sizeof(union iwreq_data));
1761 memset(buf, 0, sizeof(buf));
1762
1763 snprintf(buf, sizeof(buf) - 1, "%s", str);
1764
1765 iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
1766
1767 /* Send Event to upper layer */
8ff12da1
HS
1768 lbs_deb_wext("event indication string %s\n", (char *)buf);
1769 lbs_deb_wext("event indication length %d\n", iwrq.data.length);
1770 lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
876c9d3a 1771
634b8f49 1772 wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
876c9d3a 1773
8ff12da1 1774 lbs_deb_leave(LBS_DEB_WEXT);
876c9d3a
MT
1775}
1776
1777static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
1778{
1779 unsigned long flags;
1780 wlan_adapter *adapter = priv->adapter;
1781 int ret = 0;
1782
8ff12da1 1783 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a 1784
8ff12da1 1785 lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
876c9d3a
MT
1786 size);
1787
8ff12da1 1788 lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
876c9d3a 1789
208fdd2f 1790 ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
634b8f49 1791 priv->dnld_sent = DNLD_RES_RECEIVED;
876c9d3a
MT
1792
1793 spin_lock_irqsave(&adapter->driver_lock, flags);
1794 if (adapter->intcounter || adapter->currenttxskb)
8ff12da1 1795 lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
876c9d3a
MT
1796 adapter->intcounter, adapter->currenttxskb);
1797 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1798
1799 if (ret) {
1800 lbs_pr_alert(
1801 "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
1802 } else {
1803 spin_lock_irqsave(&adapter->driver_lock, flags);
1804 if (!adapter->intcounter) {
1805 adapter->psstate = PS_STATE_SLEEP;
1806 } else {
8ff12da1 1807 lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
876c9d3a
MT
1808 adapter->intcounter);
1809 }
1810 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1811
8ff12da1 1812 lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
876c9d3a
MT
1813 }
1814
8ff12da1 1815 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
876c9d3a
MT
1816 return ret;
1817}
1818
1819void libertas_ps_sleep(wlan_private * priv, int wait_option)
1820{
8ff12da1 1821 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a
MT
1822
1823 /*
1824 * PS is currently supported only in Infrastructure mode
1825 * Remove this check if it is to be supported in IBSS mode also
1826 */
1827
0aef64d7
DW
1828 libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1829 CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
876c9d3a 1830
8ff12da1 1831 lbs_deb_leave(LBS_DEB_HOST);
876c9d3a
MT
1832}
1833
1834/**
8ff12da1 1835 * @brief This function sends Exit_PS command to firmware.
876c9d3a
MT
1836 *
1837 * @param priv A pointer to wlan_private structure
1838 * @param wait_option wait response or not
1839 * @return n/a
1840 */
1841void libertas_ps_wakeup(wlan_private * priv, int wait_option)
1842{
981f187b 1843 __le32 Localpsmode;
876c9d3a 1844
8ff12da1 1845 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a 1846
0aef64d7 1847 Localpsmode = cpu_to_le32(WLAN802_11POWERMODECAM);
876c9d3a 1848
0aef64d7
DW
1849 libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1850 CMD_SUBCMD_EXIT_PS,
876c9d3a
MT
1851 wait_option, 0, &Localpsmode);
1852
8ff12da1 1853 lbs_deb_leave(LBS_DEB_HOST);
876c9d3a
MT
1854}
1855
1856/**
1857 * @brief This function checks condition and prepares to
1858 * send sleep confirm command to firmware if ok.
1859 *
1860 * @param priv A pointer to wlan_private structure
1861 * @param psmode Power Saving mode
1862 * @return n/a
1863 */
1864void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode)
1865{
1866 unsigned long flags =0;
1867 wlan_adapter *adapter = priv->adapter;
1868 u8 allowed = 1;
1869
8ff12da1 1870 lbs_deb_enter(LBS_DEB_HOST);
876c9d3a 1871
634b8f49 1872 if (priv->dnld_sent) {
876c9d3a 1873 allowed = 0;
8ff12da1 1874 lbs_deb_host("dnld_sent was set");
876c9d3a
MT
1875 }
1876
1877 spin_lock_irqsave(&adapter->driver_lock, flags);
1878 if (adapter->cur_cmd) {
1879 allowed = 0;
8ff12da1 1880 lbs_deb_host("cur_cmd was set");
876c9d3a
MT
1881 }
1882 if (adapter->intcounter > 0) {
1883 allowed = 0;
8ff12da1 1884 lbs_deb_host("intcounter %d", adapter->intcounter);
876c9d3a
MT
1885 }
1886 spin_unlock_irqrestore(&adapter->driver_lock, flags);
1887
1888 if (allowed) {
8ff12da1 1889 lbs_deb_host("sending libertas_ps_confirm_sleep\n");
876c9d3a
MT
1890 sendconfirmsleep(priv, (u8 *) & adapter->libertas_ps_confirm_sleep,
1891 sizeof(struct PS_CMD_ConfirmSleep));
1892 } else {
8ff12da1 1893 lbs_deb_host("sleep confirm has been delayed\n");
876c9d3a
MT
1894 }
1895
8ff12da1 1896 lbs_deb_leave(LBS_DEB_HOST);
876c9d3a 1897}
This page took 0.180978 seconds and 5 git commands to generate.