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