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