2 * This file contains the handling of command.
3 * It prepares command and sends it to firmware when it is ready.
6 #include <net/iw_handler.h>
15 static void cleanup_cmdnode(struct cmd_ctrl_node
*ptempnode
);
16 struct cmd_ctrl_node
*lbs_get_cmd_ctrl_node(struct lbs_private
*priv
);
17 void lbs_set_cmd_ctrl_node(struct lbs_private
*priv
,
18 struct cmd_ctrl_node
*ptempnode
,
19 u16 wait_option
, void *pdata_buf
);
22 static u16 commands_allowed_in_ps
[] = {
27 * @brief This function checks if the commans is allowed
30 * @param command the command ID
31 * @return TRUE or FALSE
33 static u8
is_command_allowed_in_ps(__le16 command
)
37 for (i
= 0; i
< ARRAY_SIZE(commands_allowed_in_ps
); i
++) {
38 if (command
== cpu_to_le16(commands_allowed_in_ps
[i
]))
45 static int lbs_cmd_hw_spec(struct lbs_private
*priv
, struct cmd_ds_command
*cmd
)
47 struct cmd_ds_get_hw_spec
*hwspec
= &cmd
->params
.hwspec
;
49 lbs_deb_enter(LBS_DEB_CMD
);
51 cmd
->command
= cpu_to_le16(CMD_GET_HW_SPEC
);
52 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec
) + S_DS_GEN
);
53 memcpy(hwspec
->permanentaddr
, priv
->adapter
->current_addr
, ETH_ALEN
);
55 lbs_deb_leave(LBS_DEB_CMD
);
59 static int lbs_cmd_802_11_ps_mode(struct lbs_private
*priv
,
60 struct cmd_ds_command
*cmd
,
63 struct cmd_ds_802_11_ps_mode
*psm
= &cmd
->params
.psmode
;
65 lbs_deb_enter(LBS_DEB_CMD
);
67 cmd
->command
= cpu_to_le16(CMD_802_11_PS_MODE
);
68 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode
) +
70 psm
->action
= cpu_to_le16(cmd_action
);
71 psm
->multipledtim
= 0;
73 case CMD_SUBCMD_ENTER_PS
:
74 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
76 psm
->locallisteninterval
= 0;
77 psm
->nullpktinterval
= 0;
79 cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM
);
82 case CMD_SUBCMD_EXIT_PS
:
83 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
86 case CMD_SUBCMD_SLEEP_CONFIRMED
:
87 lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
94 lbs_deb_leave(LBS_DEB_CMD
);
98 static int lbs_cmd_802_11_inactivity_timeout(struct lbs_private
*priv
,
99 struct cmd_ds_command
*cmd
,
100 u16 cmd_action
, void *pdata_buf
)
102 u16
*timeout
= pdata_buf
;
104 lbs_deb_enter(LBS_DEB_CMD
);
106 cmd
->command
= cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT
);
108 cpu_to_le16(sizeof(struct cmd_ds_802_11_inactivity_timeout
)
111 cmd
->params
.inactivity_timeout
.action
= cpu_to_le16(cmd_action
);
114 cmd
->params
.inactivity_timeout
.timeout
= cpu_to_le16(*timeout
);
116 cmd
->params
.inactivity_timeout
.timeout
= 0;
118 lbs_deb_leave(LBS_DEB_CMD
);
122 static int lbs_cmd_802_11_sleep_params(struct lbs_private
*priv
,
123 struct cmd_ds_command
*cmd
,
126 struct lbs_adapter
*adapter
= priv
->adapter
;
127 struct cmd_ds_802_11_sleep_params
*sp
= &cmd
->params
.sleep_params
;
129 lbs_deb_enter(LBS_DEB_CMD
);
131 cmd
->size
= cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params
)) +
133 cmd
->command
= cpu_to_le16(CMD_802_11_SLEEP_PARAMS
);
135 if (cmd_action
== CMD_ACT_GET
) {
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
);
139 } else if (cmd_action
== CMD_ACT_SET
) {
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
);
149 lbs_deb_leave(LBS_DEB_CMD
);
153 static int lbs_cmd_802_11_set_wep(struct lbs_private
*priv
,
154 struct cmd_ds_command
*cmd
,
158 struct cmd_ds_802_11_set_wep
*wep
= &cmd
->params
.wep
;
159 struct lbs_adapter
*adapter
= priv
->adapter
;
161 struct assoc_request
* assoc_req
= pdata_buf
;
163 lbs_deb_enter(LBS_DEB_CMD
);
165 cmd
->command
= cpu_to_le16(CMD_802_11_SET_WEP
);
166 cmd
->size
= cpu_to_le16(sizeof(*wep
) + S_DS_GEN
);
168 if (cmd_act
== CMD_ACT_ADD
) {
172 lbs_deb_cmd("Invalid association request!");
177 wep
->action
= cpu_to_le16(CMD_ACT_ADD
);
179 /* default tx key index */
180 wep
->keyindex
= cpu_to_le16((u16
)(assoc_req
->wep_tx_keyidx
&
181 (u32
)CMD_WEP_KEY_INDEX_MASK
));
183 /* Copy key types and material to host command structure */
184 for (i
= 0; i
< 4; i
++) {
185 struct enc_key
* pkey
= &assoc_req
->wep_keys
[i
];
189 wep
->keytype
[i
] = CMD_TYPE_WEP_40_BIT
;
190 memmove(&wep
->keymaterial
[i
], pkey
->key
,
192 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i
);
194 case KEY_LEN_WEP_104
:
195 wep
->keytype
[i
] = CMD_TYPE_WEP_104_BIT
;
196 memmove(&wep
->keymaterial
[i
], pkey
->key
,
198 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i
);
203 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
210 } else if (cmd_act
== CMD_ACT_REMOVE
) {
211 /* ACT_REMOVE clears _all_ WEP keys */
212 wep
->action
= cpu_to_le16(CMD_ACT_REMOVE
);
214 /* default tx key index */
215 wep
->keyindex
= cpu_to_le16((u16
)(adapter
->wep_tx_keyidx
&
216 (u32
)CMD_WEP_KEY_INDEX_MASK
));
217 lbs_deb_cmd("SET_WEP: remove key %d\n", adapter
->wep_tx_keyidx
);
223 lbs_deb_leave_args(LBS_DEB_CMD
, "ret %d", ret
);
227 static int lbs_cmd_802_11_enable_rsn(struct lbs_private
*priv
,
228 struct cmd_ds_command
*cmd
,
232 struct cmd_ds_802_11_enable_rsn
*penableRSN
= &cmd
->params
.enbrsn
;
233 u32
* enable
= pdata_buf
;
235 lbs_deb_enter(LBS_DEB_CMD
);
237 cmd
->command
= cpu_to_le16(CMD_802_11_ENABLE_RSN
);
238 cmd
->size
= cpu_to_le16(sizeof(*penableRSN
) + S_DS_GEN
);
239 penableRSN
->action
= cpu_to_le16(cmd_action
);
241 if (cmd_action
== CMD_ACT_SET
) {
243 penableRSN
->enable
= cpu_to_le16(CMD_ENABLE_RSN
);
245 penableRSN
->enable
= cpu_to_le16(CMD_DISABLE_RSN
);
246 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable
);
249 lbs_deb_leave(LBS_DEB_CMD
);
254 static ssize_t
lbs_tlv_size(const u8
*tlv
, u16 size
)
257 struct mrvlietypesheader
*tlv_h
;
260 tlv_h
= (struct mrvlietypesheader
*) tlv
;
263 length
= le16_to_cpu(tlv_h
->len
) +
264 sizeof(struct mrvlietypesheader
);
272 static void lbs_cmd_802_11_subscribe_event(struct lbs_private
*priv
,
273 struct cmd_ds_command
*cmd
, u16 cmd_action
,
276 struct cmd_ds_802_11_subscribe_event
*events
=
277 (struct cmd_ds_802_11_subscribe_event
*) pdata_buf
;
279 /* pdata_buf points to a struct cmd_ds_802_11_subscribe_event and room
280 * for various Marvell TLVs */
282 lbs_deb_enter(LBS_DEB_CMD
);
284 cmd
->size
= cpu_to_le16(sizeof(*events
)
285 - sizeof(events
->tlv
)
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;
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
);
297 lbs_deb_leave(LBS_DEB_CMD
);
300 static void set_one_wpa_key(struct MrvlIEtype_keyParamSet
* pkeyparamset
,
301 struct enc_key
* pkey
)
303 lbs_deb_enter(LBS_DEB_CMD
);
305 if (pkey
->flags
& KEY_INFO_WPA_ENABLED
) {
306 pkeyparamset
->keyinfo
|= cpu_to_le16(KEY_INFO_WPA_ENABLED
);
308 if (pkey
->flags
& KEY_INFO_WPA_UNICAST
) {
309 pkeyparamset
->keyinfo
|= cpu_to_le16(KEY_INFO_WPA_UNICAST
);
311 if (pkey
->flags
& KEY_INFO_WPA_MCAST
) {
312 pkeyparamset
->keyinfo
|= cpu_to_le16(KEY_INFO_WPA_MCAST
);
315 pkeyparamset
->type
= cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
316 pkeyparamset
->keytypeid
= cpu_to_le16(pkey
->type
);
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
));
323 lbs_deb_leave(LBS_DEB_CMD
);
326 static int lbs_cmd_802_11_key_material(struct lbs_private
*priv
,
327 struct cmd_ds_command
*cmd
,
329 u32 cmd_oid
, void *pdata_buf
)
331 struct cmd_ds_802_11_key_material
*pkeymaterial
=
332 &cmd
->params
.keymaterial
;
333 struct assoc_request
* assoc_req
= pdata_buf
;
337 lbs_deb_enter(LBS_DEB_CMD
);
339 cmd
->command
= cpu_to_le16(CMD_802_11_KEY_MATERIAL
);
340 pkeymaterial
->action
= cpu_to_le16(cmd_action
);
342 if (cmd_action
== CMD_ACT_GET
) {
343 cmd
->size
= cpu_to_le16(S_DS_GEN
+ sizeof (pkeymaterial
->action
));
348 memset(&pkeymaterial
->keyParamSet
, 0, sizeof(pkeymaterial
->keyParamSet
));
350 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY
, &assoc_req
->flags
)) {
351 set_one_wpa_key(&pkeymaterial
->keyParamSet
[index
],
352 &assoc_req
->wpa_unicast_key
);
356 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY
, &assoc_req
->flags
)) {
357 set_one_wpa_key(&pkeymaterial
->keyParamSet
[index
],
358 &assoc_req
->wpa_mcast_key
);
362 cmd
->size
= cpu_to_le16( S_DS_GEN
363 + sizeof (pkeymaterial
->action
)
364 + (index
* sizeof(struct MrvlIEtype_keyParamSet
)));
369 lbs_deb_leave_args(LBS_DEB_CMD
, "ret %d", ret
);
373 static int lbs_cmd_802_11_reset(struct lbs_private
*priv
,
374 struct cmd_ds_command
*cmd
, int cmd_action
)
376 struct cmd_ds_802_11_reset
*reset
= &cmd
->params
.reset
;
378 lbs_deb_enter(LBS_DEB_CMD
);
380 cmd
->command
= cpu_to_le16(CMD_802_11_RESET
);
381 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_reset
) + S_DS_GEN
);
382 reset
->action
= cpu_to_le16(cmd_action
);
384 lbs_deb_leave(LBS_DEB_CMD
);
388 static int lbs_cmd_802_11_get_log(struct lbs_private
*priv
,
389 struct cmd_ds_command
*cmd
)
391 lbs_deb_enter(LBS_DEB_CMD
);
392 cmd
->command
= cpu_to_le16(CMD_802_11_GET_LOG
);
394 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log
) + S_DS_GEN
);
396 lbs_deb_leave(LBS_DEB_CMD
);
400 static int lbs_cmd_802_11_get_stat(struct lbs_private
*priv
,
401 struct cmd_ds_command
*cmd
)
403 lbs_deb_enter(LBS_DEB_CMD
);
404 cmd
->command
= cpu_to_le16(CMD_802_11_GET_STAT
);
406 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat
) + S_DS_GEN
);
408 lbs_deb_leave(LBS_DEB_CMD
);
412 static int lbs_cmd_802_11_snmp_mib(struct lbs_private
*priv
,
413 struct cmd_ds_command
*cmd
,
415 int cmd_oid
, void *pdata_buf
)
417 struct cmd_ds_802_11_snmp_mib
*pSNMPMIB
= &cmd
->params
.smib
;
418 struct lbs_adapter
*adapter
= priv
->adapter
;
421 lbs_deb_enter(LBS_DEB_CMD
);
423 lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid
);
425 cmd
->command
= cpu_to_le16(CMD_802_11_SNMP_MIB
);
426 cmd
->size
= cpu_to_le16(sizeof(*pSNMPMIB
) + S_DS_GEN
);
429 case OID_802_11_INFRASTRUCTURE_MODE
:
431 u8 mode
= (u8
) (size_t) pdata_buf
;
432 pSNMPMIB
->querytype
= cpu_to_le16(CMD_ACT_SET
);
433 pSNMPMIB
->oid
= cpu_to_le16((u16
) DESIRED_BSSTYPE_I
);
434 pSNMPMIB
->bufsize
= cpu_to_le16(sizeof(u8
));
435 if (mode
== IW_MODE_ADHOC
) {
436 ucTemp
= SNMP_MIB_VALUE_ADHOC
;
438 /* Infra and Auto modes */
439 ucTemp
= SNMP_MIB_VALUE_INFRA
;
442 memmove(pSNMPMIB
->value
, &ucTemp
, sizeof(u8
));
447 case OID_802_11D_ENABLE
:
451 pSNMPMIB
->oid
= cpu_to_le16((u16
) DOT11D_I
);
453 if (cmd_action
== CMD_ACT_SET
) {
454 pSNMPMIB
->querytype
= cpu_to_le16(CMD_ACT_SET
);
455 pSNMPMIB
->bufsize
= cpu_to_le16(sizeof(u16
));
456 ulTemp
= *(u32
*)pdata_buf
;
457 *((__le16
*)(pSNMPMIB
->value
)) =
458 cpu_to_le16((u16
) ulTemp
);
463 case OID_802_11_FRAGMENTATION_THRESHOLD
:
467 pSNMPMIB
->oid
= cpu_to_le16((u16
) FRAGTHRESH_I
);
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
);
473 pSNMPMIB
->bufsize
= cpu_to_le16(sizeof(u16
));
474 ulTemp
= *((u32
*) pdata_buf
);
475 *((__le16
*)(pSNMPMIB
->value
)) =
476 cpu_to_le16((u16
) ulTemp
);
483 case OID_802_11_RTS_THRESHOLD
:
487 pSNMPMIB
->oid
= cpu_to_le16(RTSTHRESH_I
);
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
);
493 pSNMPMIB
->bufsize
= cpu_to_le16(sizeof(u16
));
494 ulTemp
= *((u32
*)pdata_buf
);
495 *(__le16
*)(pSNMPMIB
->value
) =
496 cpu_to_le16((u16
) ulTemp
);
501 case OID_802_11_TX_RETRYCOUNT
:
502 pSNMPMIB
->oid
= cpu_to_le16((u16
) SHORT_RETRYLIM_I
);
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
);
508 pSNMPMIB
->bufsize
= cpu_to_le16(sizeof(u16
));
509 *((__le16
*)(pSNMPMIB
->value
)) =
510 cpu_to_le16((u16
) adapter
->txretrycount
);
519 "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
520 le16_to_cpu(cmd
->command
), le16_to_cpu(cmd
->size
),
521 le16_to_cpu(cmd
->seqnum
), le16_to_cpu(cmd
->result
));
524 "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
525 le16_to_cpu(pSNMPMIB
->querytype
), le16_to_cpu(pSNMPMIB
->oid
),
526 le16_to_cpu(pSNMPMIB
->bufsize
),
527 le16_to_cpu(*(__le16
*) pSNMPMIB
->value
));
529 lbs_deb_leave(LBS_DEB_CMD
);
533 static int lbs_cmd_802_11_radio_control(struct lbs_private
*priv
,
534 struct cmd_ds_command
*cmd
,
537 struct lbs_adapter
*adapter
= priv
->adapter
;
538 struct cmd_ds_802_11_radio_control
*pradiocontrol
= &cmd
->params
.radio
;
540 lbs_deb_enter(LBS_DEB_CMD
);
543 cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control
)) +
545 cmd
->command
= cpu_to_le16(CMD_802_11_RADIO_CONTROL
);
547 pradiocontrol
->action
= cpu_to_le16(cmd_action
);
549 switch (adapter
->preamble
) {
550 case CMD_TYPE_SHORT_PREAMBLE
:
551 pradiocontrol
->control
= cpu_to_le16(SET_SHORT_PREAMBLE
);
554 case CMD_TYPE_LONG_PREAMBLE
:
555 pradiocontrol
->control
= cpu_to_le16(SET_LONG_PREAMBLE
);
558 case CMD_TYPE_AUTO_PREAMBLE
:
560 pradiocontrol
->control
= cpu_to_le16(SET_AUTO_PREAMBLE
);
564 if (adapter
->radioon
)
565 pradiocontrol
->control
|= cpu_to_le16(TURN_ON_RF
);
567 pradiocontrol
->control
&= cpu_to_le16(~TURN_ON_RF
);
569 lbs_deb_leave(LBS_DEB_CMD
);
573 static int lbs_cmd_802_11_rf_tx_power(struct lbs_private
*priv
,
574 struct cmd_ds_command
*cmd
,
575 u16 cmd_action
, void *pdata_buf
)
578 struct cmd_ds_802_11_rf_tx_power
*prtp
= &cmd
->params
.txp
;
580 lbs_deb_enter(LBS_DEB_CMD
);
583 cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power
)) + S_DS_GEN
);
584 cmd
->command
= cpu_to_le16(CMD_802_11_RF_TX_POWER
);
585 prtp
->action
= cpu_to_le16(cmd_action
);
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
));
591 switch (cmd_action
) {
592 case CMD_ACT_TX_POWER_OPT_GET
:
593 prtp
->action
= cpu_to_le16(CMD_ACT_GET
);
594 prtp
->currentlevel
= 0;
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
);
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
);
607 case CMD_ACT_TX_POWER_OPT_SET_LOW
:
608 prtp
->action
= cpu_to_le16(CMD_ACT_SET
);
609 prtp
->currentlevel
= cpu_to_le16(*((u16
*) pdata_buf
));
613 lbs_deb_leave(LBS_DEB_CMD
);
617 static int lbs_cmd_802_11_monitor_mode(struct lbs_private
*priv
,
618 struct cmd_ds_command
*cmd
,
619 u16 cmd_action
, void *pdata_buf
)
621 struct cmd_ds_802_11_monitor_mode
*monitor
= &cmd
->params
.monitor
;
623 cmd
->command
= cpu_to_le16(CMD_802_11_MONITOR_MODE
);
625 cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode
) +
628 monitor
->action
= cpu_to_le16(cmd_action
);
629 if (cmd_action
== CMD_ACT_SET
) {
631 cpu_to_le16((u16
) (*(u32
*) pdata_buf
));
637 static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private
*priv
,
638 struct cmd_ds_command
*cmd
,
641 struct cmd_ds_802_11_rate_adapt_rateset
642 *rateadapt
= &cmd
->params
.rateset
;
643 struct lbs_adapter
*adapter
= priv
->adapter
;
645 lbs_deb_enter(LBS_DEB_CMD
);
647 cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset
)
649 cmd
->command
= cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET
);
651 rateadapt
->action
= cpu_to_le16(cmd_action
);
652 rateadapt
->enablehwauto
= cpu_to_le16(adapter
->enablehwauto
);
653 rateadapt
->bitmap
= cpu_to_le16(adapter
->ratebitmap
);
655 lbs_deb_leave(LBS_DEB_CMD
);
659 static int lbs_cmd_802_11_data_rate(struct lbs_private
*priv
,
660 struct cmd_ds_command
*cmd
,
663 struct cmd_ds_802_11_data_rate
*pdatarate
= &cmd
->params
.drate
;
664 struct lbs_adapter
*adapter
= priv
->adapter
;
666 lbs_deb_enter(LBS_DEB_CMD
);
668 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate
) +
670 cmd
->command
= cpu_to_le16(CMD_802_11_DATA_RATE
);
671 memset(pdatarate
, 0, sizeof(struct cmd_ds_802_11_data_rate
));
672 pdatarate
->action
= cpu_to_le16(cmd_action
);
674 if (cmd_action
== CMD_ACT_SET_TX_FIX_RATE
) {
675 pdatarate
->rates
[0] = lbs_data_rate_to_fw_index(adapter
->cur_rate
);
676 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n",
678 } else if (cmd_action
== CMD_ACT_SET_TX_AUTO
) {
679 lbs_deb_cmd("DATA_RATE: setting auto\n");
682 lbs_deb_leave(LBS_DEB_CMD
);
686 static int lbs_cmd_mac_multicast_adr(struct lbs_private
*priv
,
687 struct cmd_ds_command
*cmd
,
690 struct cmd_ds_mac_multicast_adr
*pMCastAdr
= &cmd
->params
.madr
;
691 struct lbs_adapter
*adapter
= priv
->adapter
;
693 lbs_deb_enter(LBS_DEB_CMD
);
694 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr
) +
696 cmd
->command
= cpu_to_le16(CMD_MAC_MULTICAST_ADR
);
698 lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr
->nr_of_adrs
);
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
);
705 lbs_deb_leave(LBS_DEB_CMD
);
709 static int lbs_cmd_802_11_rf_channel(struct lbs_private
*priv
,
710 struct cmd_ds_command
*cmd
,
711 int option
, void *pdata_buf
)
713 struct cmd_ds_802_11_rf_channel
*rfchan
= &cmd
->params
.rfchannel
;
715 lbs_deb_enter(LBS_DEB_CMD
);
716 cmd
->command
= cpu_to_le16(CMD_802_11_RF_CHANNEL
);
717 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel
) +
720 if (option
== CMD_OPT_802_11_RF_CHANNEL_SET
) {
721 rfchan
->currentchannel
= cpu_to_le16(*((u16
*) pdata_buf
));
724 rfchan
->action
= cpu_to_le16(option
);
726 lbs_deb_leave(LBS_DEB_CMD
);
730 static int lbs_cmd_802_11_rssi(struct lbs_private
*priv
,
731 struct cmd_ds_command
*cmd
)
733 struct lbs_adapter
*adapter
= priv
->adapter
;
735 lbs_deb_enter(LBS_DEB_CMD
);
736 cmd
->command
= cpu_to_le16(CMD_802_11_RSSI
);
737 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi
) + S_DS_GEN
);
738 cmd
->params
.rssi
.N
= cpu_to_le16(DEFAULT_BCN_AVG_FACTOR
);
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;
748 lbs_deb_leave(LBS_DEB_CMD
);
752 static int lbs_cmd_reg_access(struct lbs_private
*priv
,
753 struct cmd_ds_command
*cmdptr
,
754 u8 cmd_action
, void *pdata_buf
)
756 struct lbs_offset_value
*offval
;
758 lbs_deb_enter(LBS_DEB_CMD
);
760 offval
= (struct lbs_offset_value
*)pdata_buf
;
762 switch (le16_to_cpu(cmdptr
->command
)) {
763 case CMD_MAC_REG_ACCESS
:
765 struct cmd_ds_mac_reg_access
*macreg
;
768 cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access
)
771 (struct cmd_ds_mac_reg_access
*)&cmdptr
->params
.
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
);
781 case CMD_BBP_REG_ACCESS
:
783 struct cmd_ds_bbp_reg_access
*bbpreg
;
787 (struct cmd_ds_bbp_reg_access
)
790 (struct cmd_ds_bbp_reg_access
*)&cmdptr
->params
.
793 bbpreg
->action
= cpu_to_le16(cmd_action
);
794 bbpreg
->offset
= cpu_to_le16((u16
) offval
->offset
);
795 bbpreg
->value
= (u8
) offval
->value
;
800 case CMD_RF_REG_ACCESS
:
802 struct cmd_ds_rf_reg_access
*rfreg
;
806 (struct cmd_ds_rf_reg_access
) +
809 (struct cmd_ds_rf_reg_access
*)&cmdptr
->params
.
812 rfreg
->action
= cpu_to_le16(cmd_action
);
813 rfreg
->offset
= cpu_to_le16((u16
) offval
->offset
);
814 rfreg
->value
= (u8
) offval
->value
;
823 lbs_deb_leave(LBS_DEB_CMD
);
827 static int lbs_cmd_802_11_mac_address(struct lbs_private
*priv
,
828 struct cmd_ds_command
*cmd
,
831 struct lbs_adapter
*adapter
= priv
->adapter
;
833 lbs_deb_enter(LBS_DEB_CMD
);
834 cmd
->command
= cpu_to_le16(CMD_802_11_MAC_ADDRESS
);
835 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address
) +
839 cmd
->params
.macadd
.action
= cpu_to_le16(cmd_action
);
841 if (cmd_action
== CMD_ACT_SET
) {
842 memcpy(cmd
->params
.macadd
.macadd
,
843 adapter
->current_addr
, ETH_ALEN
);
844 lbs_deb_hex(LBS_DEB_CMD
, "SET_CMD: MAC addr", adapter
->current_addr
, 6);
847 lbs_deb_leave(LBS_DEB_CMD
);
851 static int lbs_cmd_802_11_eeprom_access(struct lbs_private
*priv
,
852 struct cmd_ds_command
*cmd
,
853 int cmd_action
, void *pdata_buf
)
855 struct lbs_ioctl_regrdwr
*ea
= pdata_buf
;
857 lbs_deb_enter(LBS_DEB_CMD
);
859 cmd
->command
= cpu_to_le16(CMD_802_11_EEPROM_ACCESS
);
860 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access
) +
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;
869 lbs_deb_leave(LBS_DEB_CMD
);
873 static int lbs_cmd_bt_access(struct lbs_private
*priv
,
874 struct cmd_ds_command
*cmd
,
875 u16 cmd_action
, void *pdata_buf
)
877 struct cmd_ds_bt_access
*bt_access
= &cmd
->params
.bt
;
878 lbs_deb_enter_args(LBS_DEB_CMD
, "action %d", cmd_action
);
880 cmd
->command
= cpu_to_le16(CMD_BT_ACCESS
);
881 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_bt_access
) + S_DS_GEN
);
883 bt_access
->action
= cpu_to_le16(cmd_action
);
885 switch (cmd_action
) {
886 case CMD_ACT_BT_ACCESS_ADD
:
887 memcpy(bt_access
->addr1
, pdata_buf
, 2 * ETH_ALEN
);
888 lbs_deb_hex(LBS_DEB_MESH
, "BT_ADD: blinded MAC addr", bt_access
->addr1
, 6);
890 case CMD_ACT_BT_ACCESS_DEL
:
891 memcpy(bt_access
->addr1
, pdata_buf
, 1 * ETH_ALEN
);
892 lbs_deb_hex(LBS_DEB_MESH
, "BT_DEL: blinded MAC addr", bt_access
->addr1
, 6);
894 case CMD_ACT_BT_ACCESS_LIST
:
895 bt_access
->id
= cpu_to_le32(*(u32
*) pdata_buf
);
897 case CMD_ACT_BT_ACCESS_RESET
:
899 case CMD_ACT_BT_ACCESS_SET_INVERT
:
900 bt_access
->id
= cpu_to_le32(*(u32
*) pdata_buf
);
902 case CMD_ACT_BT_ACCESS_GET_INVERT
:
907 lbs_deb_leave(LBS_DEB_CMD
);
911 static int lbs_cmd_fwt_access(struct lbs_private
*priv
,
912 struct cmd_ds_command
*cmd
,
913 u16 cmd_action
, void *pdata_buf
)
915 struct cmd_ds_fwt_access
*fwt_access
= &cmd
->params
.fwt
;
916 lbs_deb_enter_args(LBS_DEB_CMD
, "action %d", cmd_action
);
918 cmd
->command
= cpu_to_le16(CMD_FWT_ACCESS
);
919 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_fwt_access
) + S_DS_GEN
);
923 memcpy(fwt_access
, pdata_buf
, sizeof(*fwt_access
));
925 memset(fwt_access
, 0, sizeof(*fwt_access
));
927 fwt_access
->action
= cpu_to_le16(cmd_action
);
929 lbs_deb_leave(LBS_DEB_CMD
);
933 static int lbs_cmd_mesh_access(struct lbs_private
*priv
,
934 struct cmd_ds_command
*cmd
,
935 u16 cmd_action
, void *pdata_buf
)
937 struct cmd_ds_mesh_access
*mesh_access
= &cmd
->params
.mesh
;
938 lbs_deb_enter_args(LBS_DEB_CMD
, "action %d", cmd_action
);
940 cmd
->command
= cpu_to_le16(CMD_MESH_ACCESS
);
941 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_mesh_access
) + S_DS_GEN
);
945 memcpy(mesh_access
, pdata_buf
, sizeof(*mesh_access
));
947 memset(mesh_access
, 0, sizeof(*mesh_access
));
949 mesh_access
->action
= cpu_to_le16(cmd_action
);
951 lbs_deb_leave(LBS_DEB_CMD
);
955 static int lbs_cmd_bcn_ctrl(struct lbs_private
* priv
,
956 struct cmd_ds_command
*cmd
,
959 struct cmd_ds_802_11_beacon_control
960 *bcn_ctrl
= &cmd
->params
.bcn_ctrl
;
961 struct lbs_adapter
*adapter
= priv
->adapter
;
963 lbs_deb_enter(LBS_DEB_CMD
);
965 cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control
)
967 cmd
->command
= cpu_to_le16(CMD_802_11_BEACON_CTRL
);
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
);
973 lbs_deb_leave(LBS_DEB_CMD
);
978 * Note: NEVER use lbs_queue_cmd() with addtail==0 other than for
979 * the command timer, because it does not account for queued commands.
981 void lbs_queue_cmd(struct lbs_adapter
*adapter
,
982 struct cmd_ctrl_node
*cmdnode
,
986 struct cmd_ds_command
*cmdptr
;
988 lbs_deb_enter(LBS_DEB_HOST
);
991 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
995 cmdptr
= (struct cmd_ds_command
*)cmdnode
->bufvirtualaddr
;
997 lbs_deb_host("QUEUE_CMD: cmdptr is NULL\n");
1001 /* Exit_PS command needs to be queued in the header always. */
1002 if (le16_to_cpu(cmdptr
->command
) == CMD_802_11_PS_MODE
) {
1003 struct cmd_ds_802_11_ps_mode
*psm
= &cmdptr
->params
.psmode
;
1004 if (psm
->action
== cpu_to_le16(CMD_SUBCMD_EXIT_PS
)) {
1005 if (adapter
->psstate
!= PS_STATE_FULL_POWER
)
1010 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1013 list_add_tail(&cmdnode
->list
, &adapter
->cmdpendingq
);
1014 adapter
->nr_cmd_pending
++;
1016 list_add(&cmdnode
->list
, &adapter
->cmdpendingq
);
1018 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1020 lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
1021 le16_to_cpu(((struct cmd_ds_gen
*)cmdnode
->bufvirtualaddr
)->command
));
1024 lbs_deb_leave(LBS_DEB_HOST
);
1028 * TODO: Fix the issue when DownloadcommandToStation is being called the
1029 * second time when the command times out. All the cmdptr->xxx are in little
1030 * endian and therefore all the comparissions will fail.
1031 * For now - we are not performing the endian conversion the second time - but
1032 * for PS and DEEP_SLEEP we need to worry
1034 static int DownloadcommandToStation(struct lbs_private
*priv
,
1035 struct cmd_ctrl_node
*cmdnode
)
1037 unsigned long flags
;
1038 struct cmd_ds_command
*cmdptr
;
1039 struct lbs_adapter
*adapter
= priv
->adapter
;
1044 lbs_deb_enter(LBS_DEB_HOST
);
1046 if (!adapter
|| !cmdnode
) {
1047 lbs_deb_host("DNLD_CMD: adapter or cmdmode is NULL\n");
1051 cmdptr
= (struct cmd_ds_command
*)cmdnode
->bufvirtualaddr
;
1053 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1054 if (!cmdptr
|| !cmdptr
->size
) {
1055 lbs_deb_host("DNLD_CMD: cmdptr is NULL or zero\n");
1056 __lbs_cleanup_and_insert_cmd(priv
, cmdnode
);
1057 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1061 adapter
->cur_cmd
= cmdnode
;
1062 adapter
->cur_cmd_retcode
= 0;
1063 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1065 cmdsize
= le16_to_cpu(cmdptr
->size
);
1066 command
= le16_to_cpu(cmdptr
->command
);
1068 lbs_deb_host("DNLD_CMD: command 0x%04x, size %d, jiffies %lu\n",
1069 command
, cmdsize
, jiffies
);
1070 lbs_deb_hex(LBS_DEB_HOST
, "DNLD_CMD", cmdnode
->bufvirtualaddr
, cmdsize
);
1072 cmdnode
->cmdwaitqwoken
= 0;
1074 ret
= priv
->hw_host_to_card(priv
, MVMS_CMD
, (u8
*) cmdptr
, cmdsize
);
1077 lbs_deb_host("DNLD_CMD: hw_host_to_card failed\n");
1078 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1079 adapter
->cur_cmd_retcode
= ret
;
1080 __lbs_cleanup_and_insert_cmd(priv
, adapter
->cur_cmd
);
1081 adapter
->nr_cmd_pending
--;
1082 adapter
->cur_cmd
= NULL
;
1083 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1087 lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", command
, jiffies
);
1089 /* Setup the timer after transmit command */
1090 if (command
== CMD_802_11_SCAN
|| command
== CMD_802_11_AUTHENTICATE
1091 || command
== CMD_802_11_ASSOCIATE
)
1092 mod_timer(&adapter
->command_timer
, jiffies
+ (10*HZ
));
1094 mod_timer(&adapter
->command_timer
, jiffies
+ (5*HZ
));
1099 lbs_deb_leave_args(LBS_DEB_HOST
, "ret %d", ret
);
1103 static int lbs_cmd_mac_control(struct lbs_private
*priv
,
1104 struct cmd_ds_command
*cmd
)
1106 struct cmd_ds_mac_control
*mac
= &cmd
->params
.macctrl
;
1108 lbs_deb_enter(LBS_DEB_CMD
);
1110 cmd
->command
= cpu_to_le16(CMD_MAC_CONTROL
);
1111 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_mac_control
) + S_DS_GEN
);
1112 mac
->action
= cpu_to_le16(priv
->adapter
->currentpacketfilter
);
1114 lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
1115 le16_to_cpu(mac
->action
), le16_to_cpu(cmd
->size
));
1117 lbs_deb_leave(LBS_DEB_CMD
);
1122 * This function inserts command node to cmdfreeq
1123 * after cleans it. Requires adapter->driver_lock held.
1125 void __lbs_cleanup_and_insert_cmd(struct lbs_private
*priv
,
1126 struct cmd_ctrl_node
*ptempcmd
)
1128 struct lbs_adapter
*adapter
= priv
->adapter
;
1133 cleanup_cmdnode(ptempcmd
);
1134 list_add_tail(&ptempcmd
->list
, &adapter
->cmdfreeq
);
1137 static void lbs_cleanup_and_insert_cmd(struct lbs_private
*priv
,
1138 struct cmd_ctrl_node
*ptempcmd
)
1140 unsigned long flags
;
1142 spin_lock_irqsave(&priv
->adapter
->driver_lock
, flags
);
1143 __lbs_cleanup_and_insert_cmd(priv
, ptempcmd
);
1144 spin_unlock_irqrestore(&priv
->adapter
->driver_lock
, flags
);
1147 int lbs_set_radio_control(struct lbs_private
*priv
)
1151 lbs_deb_enter(LBS_DEB_CMD
);
1153 ret
= lbs_prepare_and_send_command(priv
,
1154 CMD_802_11_RADIO_CONTROL
,
1156 CMD_OPTION_WAITFORRSP
, 0, NULL
);
1158 lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n",
1159 priv
->adapter
->radioon
, priv
->adapter
->preamble
);
1161 lbs_deb_leave_args(LBS_DEB_CMD
, "ret %d", ret
);
1165 int lbs_set_mac_packet_filter(struct lbs_private
*priv
)
1169 lbs_deb_enter(LBS_DEB_CMD
);
1171 /* Send MAC control command to station */
1172 ret
= lbs_prepare_and_send_command(priv
,
1173 CMD_MAC_CONTROL
, 0, 0, 0, NULL
);
1175 lbs_deb_leave_args(LBS_DEB_CMD
, "ret %d", ret
);
1180 * @brief This function prepare the command before send to firmware.
1182 * @param priv A pointer to struct lbs_private structure
1183 * @param cmd_no command number
1184 * @param cmd_action command action: GET or SET
1185 * @param wait_option wait option: wait response or not
1186 * @param cmd_oid cmd oid: treated as sub command
1187 * @param pdata_buf A pointer to informaion buffer
1190 int lbs_prepare_and_send_command(struct lbs_private
*priv
,
1193 u16 wait_option
, u32 cmd_oid
, void *pdata_buf
)
1196 struct lbs_adapter
*adapter
= priv
->adapter
;
1197 struct cmd_ctrl_node
*cmdnode
;
1198 struct cmd_ds_command
*cmdptr
;
1199 unsigned long flags
;
1201 lbs_deb_enter(LBS_DEB_HOST
);
1204 lbs_deb_host("PREP_CMD: adapter is NULL\n");
1209 if (adapter
->surpriseremoved
) {
1210 lbs_deb_host("PREP_CMD: card removed\n");
1215 cmdnode
= lbs_get_cmd_ctrl_node(priv
);
1217 if (cmdnode
== NULL
) {
1218 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1220 /* Wake up main thread to execute next command */
1221 wake_up_interruptible(&priv
->waitq
);
1226 lbs_set_cmd_ctrl_node(priv
, cmdnode
, wait_option
, pdata_buf
);
1228 cmdptr
= (struct cmd_ds_command
*)cmdnode
->bufvirtualaddr
;
1230 lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no
);
1233 lbs_deb_host("PREP_CMD: cmdptr is NULL\n");
1234 lbs_cleanup_and_insert_cmd(priv
, cmdnode
);
1239 /* Set sequence number, command and INT option */
1241 cmdptr
->seqnum
= cpu_to_le16(adapter
->seqnum
);
1243 cmdptr
->command
= cpu_to_le16(cmd_no
);
1247 case CMD_GET_HW_SPEC
:
1248 ret
= lbs_cmd_hw_spec(priv
, cmdptr
);
1250 case CMD_802_11_PS_MODE
:
1251 ret
= lbs_cmd_802_11_ps_mode(priv
, cmdptr
, cmd_action
);
1254 case CMD_802_11_SCAN
:
1255 ret
= lbs_cmd_80211_scan(priv
, cmdptr
, pdata_buf
);
1258 case CMD_MAC_CONTROL
:
1259 ret
= lbs_cmd_mac_control(priv
, cmdptr
);
1262 case CMD_802_11_ASSOCIATE
:
1263 case CMD_802_11_REASSOCIATE
:
1264 ret
= lbs_cmd_80211_associate(priv
, cmdptr
, pdata_buf
);
1267 case CMD_802_11_DEAUTHENTICATE
:
1268 ret
= lbs_cmd_80211_deauthenticate(priv
, cmdptr
);
1271 case CMD_802_11_SET_WEP
:
1272 ret
= lbs_cmd_802_11_set_wep(priv
, cmdptr
, cmd_action
, pdata_buf
);
1275 case CMD_802_11_AD_HOC_START
:
1276 ret
= lbs_cmd_80211_ad_hoc_start(priv
, cmdptr
, pdata_buf
);
1281 case CMD_802_11_RESET
:
1282 ret
= lbs_cmd_802_11_reset(priv
, cmdptr
, cmd_action
);
1285 case CMD_802_11_GET_LOG
:
1286 ret
= lbs_cmd_802_11_get_log(priv
, cmdptr
);
1289 case CMD_802_11_AUTHENTICATE
:
1290 ret
= lbs_cmd_80211_authenticate(priv
, cmdptr
, pdata_buf
);
1293 case CMD_802_11_GET_STAT
:
1294 ret
= lbs_cmd_802_11_get_stat(priv
, cmdptr
);
1297 case CMD_802_11_SNMP_MIB
:
1298 ret
= lbs_cmd_802_11_snmp_mib(priv
, cmdptr
,
1299 cmd_action
, cmd_oid
, pdata_buf
);
1302 case CMD_MAC_REG_ACCESS
:
1303 case CMD_BBP_REG_ACCESS
:
1304 case CMD_RF_REG_ACCESS
:
1305 ret
= lbs_cmd_reg_access(priv
, cmdptr
, cmd_action
, pdata_buf
);
1308 case CMD_802_11_RF_CHANNEL
:
1309 ret
= lbs_cmd_802_11_rf_channel(priv
, cmdptr
,
1310 cmd_action
, pdata_buf
);
1313 case CMD_802_11_RF_TX_POWER
:
1314 ret
= lbs_cmd_802_11_rf_tx_power(priv
, cmdptr
,
1315 cmd_action
, pdata_buf
);
1318 case CMD_802_11_RADIO_CONTROL
:
1319 ret
= lbs_cmd_802_11_radio_control(priv
, cmdptr
, cmd_action
);
1322 case CMD_802_11_DATA_RATE
:
1323 ret
= lbs_cmd_802_11_data_rate(priv
, cmdptr
, cmd_action
);
1325 case CMD_802_11_RATE_ADAPT_RATESET
:
1326 ret
= lbs_cmd_802_11_rate_adapt_rateset(priv
,
1327 cmdptr
, cmd_action
);
1330 case CMD_MAC_MULTICAST_ADR
:
1331 ret
= lbs_cmd_mac_multicast_adr(priv
, cmdptr
, cmd_action
);
1334 case CMD_802_11_MONITOR_MODE
:
1335 ret
= lbs_cmd_802_11_monitor_mode(priv
, cmdptr
,
1336 cmd_action
, pdata_buf
);
1339 case CMD_802_11_AD_HOC_JOIN
:
1340 ret
= lbs_cmd_80211_ad_hoc_join(priv
, cmdptr
, pdata_buf
);
1343 case CMD_802_11_RSSI
:
1344 ret
= lbs_cmd_802_11_rssi(priv
, cmdptr
);
1347 case CMD_802_11_AD_HOC_STOP
:
1348 ret
= lbs_cmd_80211_ad_hoc_stop(priv
, cmdptr
);
1351 case CMD_802_11_ENABLE_RSN
:
1352 ret
= lbs_cmd_802_11_enable_rsn(priv
, cmdptr
, cmd_action
,
1356 case CMD_802_11_KEY_MATERIAL
:
1357 ret
= lbs_cmd_802_11_key_material(priv
, cmdptr
, cmd_action
,
1358 cmd_oid
, pdata_buf
);
1361 case CMD_802_11_PAIRWISE_TSC
:
1363 case CMD_802_11_GROUP_TSC
:
1366 case CMD_802_11_MAC_ADDRESS
:
1367 ret
= lbs_cmd_802_11_mac_address(priv
, cmdptr
, cmd_action
);
1370 case CMD_802_11_EEPROM_ACCESS
:
1371 ret
= lbs_cmd_802_11_eeprom_access(priv
, cmdptr
,
1372 cmd_action
, pdata_buf
);
1375 case CMD_802_11_SET_AFC
:
1376 case CMD_802_11_GET_AFC
:
1378 cmdptr
->command
= cpu_to_le16(cmd_no
);
1379 cmdptr
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_afc
) +
1382 memmove(&cmdptr
->params
.afc
,
1383 pdata_buf
, sizeof(struct cmd_ds_802_11_afc
));
1388 case CMD_802_11D_DOMAIN_INFO
:
1389 ret
= lbs_cmd_802_11d_domain_info(priv
, cmdptr
,
1390 cmd_no
, cmd_action
);
1393 case CMD_802_11_SLEEP_PARAMS
:
1394 ret
= lbs_cmd_802_11_sleep_params(priv
, cmdptr
, cmd_action
);
1396 case CMD_802_11_INACTIVITY_TIMEOUT
:
1397 ret
= lbs_cmd_802_11_inactivity_timeout(priv
, cmdptr
,
1398 cmd_action
, pdata_buf
);
1399 lbs_set_cmd_ctrl_node(priv
, cmdnode
, 0, pdata_buf
);
1402 case CMD_802_11_TPC_CFG
:
1403 cmdptr
->command
= cpu_to_le16(CMD_802_11_TPC_CFG
);
1405 cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg
) +
1408 memmove(&cmdptr
->params
.tpccfg
,
1409 pdata_buf
, sizeof(struct cmd_ds_802_11_tpc_cfg
));
1413 case CMD_802_11_LED_GPIO_CTRL
:
1415 struct mrvlietypes_ledgpio
*gpio
=
1416 (struct mrvlietypes_ledgpio
*)
1417 cmdptr
->params
.ledgpio
.data
;
1419 memmove(&cmdptr
->params
.ledgpio
,
1421 sizeof(struct cmd_ds_802_11_led_ctrl
));
1424 cpu_to_le16(CMD_802_11_LED_GPIO_CTRL
);
1426 #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
1428 cpu_to_le16(le16_to_cpu(gpio
->header
.len
)
1430 + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN
);
1431 gpio
->header
.len
= gpio
->header
.len
;
1436 case CMD_802_11_SUBSCRIBE_EVENT
:
1437 lbs_cmd_802_11_subscribe_event(priv
, cmdptr
,
1438 cmd_action
, pdata_buf
);
1440 case CMD_802_11_PWR_CFG
:
1441 cmdptr
->command
= cpu_to_le16(CMD_802_11_PWR_CFG
);
1443 cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg
) +
1445 memmove(&cmdptr
->params
.pwrcfg
, pdata_buf
,
1446 sizeof(struct cmd_ds_802_11_pwr_cfg
));
1451 ret
= lbs_cmd_bt_access(priv
, cmdptr
, cmd_action
, pdata_buf
);
1454 case CMD_FWT_ACCESS
:
1455 ret
= lbs_cmd_fwt_access(priv
, cmdptr
, cmd_action
, pdata_buf
);
1458 case CMD_MESH_ACCESS
:
1459 ret
= lbs_cmd_mesh_access(priv
, cmdptr
, cmd_action
, pdata_buf
);
1463 cmdptr
->command
= cpu_to_le16(CMD_GET_TSF
);
1464 cmdptr
->size
= cpu_to_le16(sizeof(struct cmd_ds_get_tsf
) +
1468 case CMD_802_11_BEACON_CTRL
:
1469 ret
= lbs_cmd_bcn_ctrl(priv
, cmdptr
, cmd_action
);
1472 lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no
);
1477 /* return error, since the command preparation failed */
1479 lbs_deb_host("PREP_CMD: command preparation failed\n");
1480 lbs_cleanup_and_insert_cmd(priv
, cmdnode
);
1485 cmdnode
->cmdwaitqwoken
= 0;
1487 lbs_queue_cmd(adapter
, cmdnode
, 1);
1488 wake_up_interruptible(&priv
->waitq
);
1490 if (wait_option
& CMD_OPTION_WAITFORRSP
) {
1491 lbs_deb_host("PREP_CMD: wait for response\n");
1493 wait_event_interruptible(cmdnode
->cmdwait_q
,
1494 cmdnode
->cmdwaitqwoken
);
1497 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1498 if (adapter
->cur_cmd_retcode
) {
1499 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
1500 adapter
->cur_cmd_retcode
);
1501 adapter
->cur_cmd_retcode
= 0;
1504 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1507 lbs_deb_leave_args(LBS_DEB_HOST
, "ret %d", ret
);
1510 EXPORT_SYMBOL_GPL(lbs_prepare_and_send_command
);
1513 * @brief This function allocates the command buffer and link
1514 * it to command free queue.
1516 * @param priv A pointer to struct lbs_private structure
1519 int lbs_allocate_cmd_buffer(struct lbs_private
*priv
)
1524 struct cmd_ctrl_node
*tempcmd_array
;
1525 u8
*ptempvirtualaddr
;
1526 struct lbs_adapter
*adapter
= priv
->adapter
;
1528 lbs_deb_enter(LBS_DEB_HOST
);
1530 /* Allocate and initialize cmdCtrlNode */
1531 ulbufsize
= sizeof(struct cmd_ctrl_node
) * MRVDRV_NUM_OF_CMD_BUFFER
;
1533 if (!(tempcmd_array
= kzalloc(ulbufsize
, GFP_KERNEL
))) {
1534 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
1538 adapter
->cmd_array
= tempcmd_array
;
1540 /* Allocate and initialize command buffers */
1541 ulbufsize
= MRVDRV_SIZE_OF_CMD_BUFFER
;
1542 for (i
= 0; i
< MRVDRV_NUM_OF_CMD_BUFFER
; i
++) {
1543 if (!(ptempvirtualaddr
= kzalloc(ulbufsize
, GFP_KERNEL
))) {
1544 lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
1549 /* Update command buffer virtual */
1550 tempcmd_array
[i
].bufvirtualaddr
= ptempvirtualaddr
;
1553 for (i
= 0; i
< MRVDRV_NUM_OF_CMD_BUFFER
; i
++) {
1554 init_waitqueue_head(&tempcmd_array
[i
].cmdwait_q
);
1555 lbs_cleanup_and_insert_cmd(priv
, &tempcmd_array
[i
]);
1561 lbs_deb_leave_args(LBS_DEB_HOST
, "ret %d", ret
);
1566 * @brief This function frees the command buffer.
1568 * @param priv A pointer to struct lbs_private structure
1571 int lbs_free_cmd_buffer(struct lbs_private
*priv
)
1573 u32 ulbufsize
; /* Someone needs to die for this. Slowly and painfully */
1575 struct cmd_ctrl_node
*tempcmd_array
;
1576 struct lbs_adapter
*adapter
= priv
->adapter
;
1578 lbs_deb_enter(LBS_DEB_HOST
);
1580 /* need to check if cmd array is allocated or not */
1581 if (adapter
->cmd_array
== NULL
) {
1582 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
1586 tempcmd_array
= adapter
->cmd_array
;
1588 /* Release shared memory buffers */
1589 ulbufsize
= MRVDRV_SIZE_OF_CMD_BUFFER
;
1590 for (i
= 0; i
< MRVDRV_NUM_OF_CMD_BUFFER
; i
++) {
1591 if (tempcmd_array
[i
].bufvirtualaddr
) {
1592 kfree(tempcmd_array
[i
].bufvirtualaddr
);
1593 tempcmd_array
[i
].bufvirtualaddr
= NULL
;
1597 /* Release cmd_ctrl_node */
1598 if (adapter
->cmd_array
) {
1599 kfree(adapter
->cmd_array
);
1600 adapter
->cmd_array
= NULL
;
1604 lbs_deb_leave(LBS_DEB_HOST
);
1609 * @brief This function gets a free command node if available in
1610 * command free queue.
1612 * @param priv A pointer to struct lbs_private structure
1613 * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1615 struct cmd_ctrl_node
*lbs_get_cmd_ctrl_node(struct lbs_private
*priv
)
1617 struct cmd_ctrl_node
*tempnode
;
1618 struct lbs_adapter
*adapter
= priv
->adapter
;
1619 unsigned long flags
;
1621 lbs_deb_enter(LBS_DEB_HOST
);
1626 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1628 if (!list_empty(&adapter
->cmdfreeq
)) {
1629 tempnode
= list_first_entry(&adapter
->cmdfreeq
,
1630 struct cmd_ctrl_node
, list
);
1631 list_del(&tempnode
->list
);
1633 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
1637 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1640 cleanup_cmdnode(tempnode
);
1642 lbs_deb_leave(LBS_DEB_HOST
);
1647 * @brief This function cleans command node.
1649 * @param ptempnode A pointer to cmdCtrlNode structure
1652 static void cleanup_cmdnode(struct cmd_ctrl_node
*ptempnode
)
1654 lbs_deb_enter(LBS_DEB_HOST
);
1658 ptempnode
->cmdwaitqwoken
= 1;
1659 wake_up_interruptible(&ptempnode
->cmdwait_q
);
1660 ptempnode
->wait_option
= 0;
1661 ptempnode
->pdata_buf
= NULL
;
1662 ptempnode
->pdata_size
= NULL
;
1663 ptempnode
->callback
= NULL
;
1665 if (ptempnode
->bufvirtualaddr
!= NULL
)
1666 memset(ptempnode
->bufvirtualaddr
, 0, MRVDRV_SIZE_OF_CMD_BUFFER
);
1668 lbs_deb_leave(LBS_DEB_HOST
);
1672 * @brief This function initializes the command node.
1674 * @param priv A pointer to struct lbs_private structure
1675 * @param ptempnode A pointer to cmd_ctrl_node structure
1676 * @param wait_option wait option: wait response or not
1677 * @param pdata_buf A pointer to informaion buffer
1680 void lbs_set_cmd_ctrl_node(struct lbs_private
*priv
,
1681 struct cmd_ctrl_node
*ptempnode
,
1682 u16 wait_option
, void *pdata_buf
)
1684 lbs_deb_enter(LBS_DEB_HOST
);
1689 ptempnode
->wait_option
= wait_option
;
1690 ptempnode
->pdata_buf
= pdata_buf
;
1691 ptempnode
->pdata_size
= NULL
;
1692 ptempnode
->callback
= NULL
;
1694 lbs_deb_leave(LBS_DEB_HOST
);
1698 * @brief This function executes next command in command
1699 * pending queue. It will put fimware back to PS mode
1702 * @param priv A pointer to struct lbs_private structure
1705 int lbs_execute_next_command(struct lbs_private
*priv
)
1707 struct lbs_adapter
*adapter
= priv
->adapter
;
1708 struct cmd_ctrl_node
*cmdnode
= NULL
;
1709 struct cmd_ds_command
*cmdptr
;
1710 unsigned long flags
;
1713 // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
1714 // only caller to us is lbs_thread() and we get even when a
1715 // data packet is received
1716 lbs_deb_enter(LBS_DEB_THREAD
);
1718 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1720 if (adapter
->cur_cmd
) {
1721 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
1722 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1727 if (!list_empty(&adapter
->cmdpendingq
)) {
1728 cmdnode
= list_first_entry(&adapter
->cmdpendingq
,
1729 struct cmd_ctrl_node
, list
);
1732 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1735 cmdptr
= (struct cmd_ds_command
*)cmdnode
->bufvirtualaddr
;
1737 if (is_command_allowed_in_ps(cmdptr
->command
)) {
1738 if ((adapter
->psstate
== PS_STATE_SLEEP
) ||
1739 (adapter
->psstate
== PS_STATE_PRE_SLEEP
)) {
1741 "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
1742 le16_to_cpu(cmdptr
->command
),
1747 lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1748 "0x%04x in psstate %d\n",
1749 le16_to_cpu(cmdptr
->command
),
1751 } else if (adapter
->psstate
!= PS_STATE_FULL_POWER
) {
1753 * 1. Non-PS command:
1754 * Queue it. set needtowakeup to TRUE if current state
1755 * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
1756 * 2. PS command but not Exit_PS:
1758 * 3. PS command Exit_PS:
1759 * Set needtowakeup to TRUE if current state is SLEEP,
1760 * otherwise send this command down to firmware
1763 if (cmdptr
->command
!=
1764 cpu_to_le16(CMD_802_11_PS_MODE
)) {
1765 /* Prepare to send Exit PS,
1766 * this non PS command will be sent later */
1767 if ((adapter
->psstate
== PS_STATE_SLEEP
)
1768 || (adapter
->psstate
== PS_STATE_PRE_SLEEP
)
1770 /* w/ new scheme, it will not reach here.
1771 since it is blocked in main_thread. */
1772 adapter
->needtowakeup
= 1;
1774 lbs_ps_wakeup(priv
, 0);
1780 * PS command. Ignore it if it is not Exit_PS.
1781 * otherwise send it down immediately.
1783 struct cmd_ds_802_11_ps_mode
*psm
=
1784 &cmdptr
->params
.psmode
;
1787 "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
1790 cpu_to_le16(CMD_SUBCMD_EXIT_PS
)) {
1792 "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
1793 list_del(&cmdnode
->list
);
1794 lbs_cleanup_and_insert_cmd(priv
, cmdnode
);
1800 if ((adapter
->psstate
== PS_STATE_SLEEP
) ||
1801 (adapter
->psstate
== PS_STATE_PRE_SLEEP
)) {
1803 "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
1804 list_del(&cmdnode
->list
);
1805 lbs_cleanup_and_insert_cmd(priv
, cmdnode
);
1806 adapter
->needtowakeup
= 1;
1813 "EXEC_NEXT_CMD: sending EXIT_PS\n");
1816 list_del(&cmdnode
->list
);
1817 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
1818 le16_to_cpu(cmdptr
->command
));
1819 DownloadcommandToStation(priv
, cmdnode
);
1822 * check if in power save mode, if yes, put the device back
1825 if ((adapter
->psmode
!= LBS802_11POWERMODECAM
) &&
1826 (adapter
->psstate
== PS_STATE_FULL_POWER
) &&
1827 ((adapter
->connect_status
== LBS_CONNECTED
) ||
1828 (adapter
->mesh_connect_status
== LBS_CONNECTED
))) {
1829 if (adapter
->secinfo
.WPAenabled
||
1830 adapter
->secinfo
.WPA2enabled
) {
1831 /* check for valid WPA group keys */
1832 if (adapter
->wpa_mcast_key
.len
||
1833 adapter
->wpa_unicast_key
.len
) {
1835 "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1836 " go back to PS_SLEEP");
1837 lbs_ps_sleep(priv
, 0);
1841 "EXEC_NEXT_CMD: cmdpendingq empty, "
1842 "go back to PS_SLEEP");
1843 lbs_ps_sleep(priv
, 0);
1850 lbs_deb_leave(LBS_DEB_THREAD
);
1854 void lbs_send_iwevcustom_event(struct lbs_private
*priv
, s8
*str
)
1856 union iwreq_data iwrq
;
1859 lbs_deb_enter(LBS_DEB_WEXT
);
1861 memset(&iwrq
, 0, sizeof(union iwreq_data
));
1862 memset(buf
, 0, sizeof(buf
));
1864 snprintf(buf
, sizeof(buf
) - 1, "%s", str
);
1866 iwrq
.data
.length
= strlen(buf
) + 1 + IW_EV_LCP_LEN
;
1868 /* Send Event to upper layer */
1869 lbs_deb_wext("event indication string %s\n", (char *)buf
);
1870 lbs_deb_wext("event indication length %d\n", iwrq
.data
.length
);
1871 lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str
);
1873 wireless_send_event(priv
->dev
, IWEVCUSTOM
, &iwrq
, buf
);
1875 lbs_deb_leave(LBS_DEB_WEXT
);
1878 static int sendconfirmsleep(struct lbs_private
*priv
, u8
*cmdptr
, u16 size
)
1880 unsigned long flags
;
1881 struct lbs_adapter
*adapter
= priv
->adapter
;
1884 lbs_deb_enter(LBS_DEB_HOST
);
1886 lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
1889 lbs_deb_hex(LBS_DEB_HOST
, "sleep confirm command", cmdptr
, size
);
1891 ret
= priv
->hw_host_to_card(priv
, MVMS_CMD
, cmdptr
, size
);
1892 priv
->dnld_sent
= DNLD_RES_RECEIVED
;
1894 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1895 if (adapter
->intcounter
|| adapter
->currenttxskb
)
1896 lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
1897 adapter
->intcounter
, adapter
->currenttxskb
);
1898 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1902 "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
1904 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1905 if (!adapter
->intcounter
) {
1906 adapter
->psstate
= PS_STATE_SLEEP
;
1908 lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
1909 adapter
->intcounter
);
1911 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1913 lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
1916 lbs_deb_leave_args(LBS_DEB_HOST
, "ret %d", ret
);
1920 void lbs_ps_sleep(struct lbs_private
*priv
, int wait_option
)
1922 lbs_deb_enter(LBS_DEB_HOST
);
1925 * PS is currently supported only in Infrastructure mode
1926 * Remove this check if it is to be supported in IBSS mode also
1929 lbs_prepare_and_send_command(priv
, CMD_802_11_PS_MODE
,
1930 CMD_SUBCMD_ENTER_PS
, wait_option
, 0, NULL
);
1932 lbs_deb_leave(LBS_DEB_HOST
);
1936 * @brief This function sends Exit_PS command to firmware.
1938 * @param priv A pointer to struct lbs_private structure
1939 * @param wait_option wait response or not
1942 void lbs_ps_wakeup(struct lbs_private
*priv
, int wait_option
)
1946 lbs_deb_enter(LBS_DEB_HOST
);
1948 Localpsmode
= cpu_to_le32(LBS802_11POWERMODECAM
);
1950 lbs_prepare_and_send_command(priv
, CMD_802_11_PS_MODE
,
1952 wait_option
, 0, &Localpsmode
);
1954 lbs_deb_leave(LBS_DEB_HOST
);
1958 * @brief This function checks condition and prepares to
1959 * send sleep confirm command to firmware if ok.
1961 * @param priv A pointer to struct lbs_private structure
1962 * @param psmode Power Saving mode
1965 void lbs_ps_confirm_sleep(struct lbs_private
*priv
, u16 psmode
)
1967 unsigned long flags
=0;
1968 struct lbs_adapter
*adapter
= priv
->adapter
;
1971 lbs_deb_enter(LBS_DEB_HOST
);
1973 if (priv
->dnld_sent
) {
1975 lbs_deb_host("dnld_sent was set");
1978 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
1979 if (adapter
->cur_cmd
) {
1981 lbs_deb_host("cur_cmd was set");
1983 if (adapter
->intcounter
> 0) {
1985 lbs_deb_host("intcounter %d", adapter
->intcounter
);
1987 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
1990 lbs_deb_host("sending lbs_ps_confirm_sleep\n");
1991 sendconfirmsleep(priv
, (u8
*) & adapter
->lbs_ps_confirm_sleep
,
1992 sizeof(struct PS_CMD_ConfirmSleep
));
1994 lbs_deb_host("sleep confirm has been delayed\n");
1997 lbs_deb_leave(LBS_DEB_HOST
);
2002 * @brief Simple way to call firmware functions
2004 * @param priv A pointer to struct lbs_private structure
2005 * @param psmode one of the many CMD_802_11_xxxx
2006 * @param cmd pointer to the parameters structure for above command
2007 * (this should not include the command, size, sequence
2008 * and result fields from struct cmd_ds_gen)
2009 * @param cmd_size size structure pointed to by cmd
2010 * @param rsp pointer to an area where the result should be placed
2011 * @param rsp_size pointer to the size of the rsp area. If the firmware
2012 * returns fewer bytes, then this *rsp_size will be
2013 * changed to the actual size.
2014 * @return -1 in case of a higher level error, otherwise
2015 * the result code from the firmware
2018 static int lbs_cmd_callback(uint16_t respcmd
, struct cmd_ds_command
*resp
, struct lbs_private
*priv
)
2020 struct cmd_ds_gen
*r
= (struct cmd_ds_gen
*)resp
;
2021 struct lbs_adapter
*adapter
= priv
->adapter
;
2022 u16 sz
= le16_to_cpu(resp
->size
) - S_DS_GEN
;
2024 if (sz
> *adapter
->cur_cmd
->pdata_size
) {
2025 lbs_pr_err("response 0x%04x doesn't fit into buffer (%d > %d)\n",
2026 respcmd
, sz
, *adapter
->cur_cmd
->pdata_size
);
2027 sz
= *adapter
->cur_cmd
->pdata_size
;
2029 memcpy(adapter
->cur_cmd
->pdata_buf
, r
->cmdresp
, sz
);
2030 *adapter
->cur_cmd
->pdata_size
= sz
;
2035 int lbs_cmd(struct lbs_private
*priv
, u16 command
, void *cmd
, int cmd_size
,
2036 void *rsp
, int *rsp_size
)
2038 struct lbs_adapter
*adapter
= priv
->adapter
;
2039 struct cmd_ctrl_node
*cmdnode
;
2040 struct cmd_ds_gen
*cmdptr
;
2041 unsigned long flags
;
2044 lbs_deb_enter(LBS_DEB_HOST
);
2045 lbs_deb_host("rsp at %p, rsp_size at %p\n", rsp
, rsp_size
);
2047 if (!adapter
|| !rsp_size
) {
2048 lbs_deb_host("PREP_CMD: adapter is NULL\n");
2053 if (adapter
->surpriseremoved
) {
2054 lbs_deb_host("PREP_CMD: card removed\n");
2059 cmdnode
= lbs_get_cmd_ctrl_node(priv
);
2061 if (cmdnode
== NULL
) {
2062 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
2064 /* Wake up main thread to execute next command */
2065 wake_up_interruptible(&priv
->waitq
);
2070 cmdptr
= (struct cmd_ds_gen
*)cmdnode
->bufvirtualaddr
;
2071 cmdnode
->wait_option
= CMD_OPTION_WAITFORRSP
;
2072 cmdnode
->pdata_buf
= rsp
;
2073 cmdnode
->pdata_size
= rsp_size
;
2074 cmdnode
->callback
= lbs_cmd_callback
;
2076 /* Set sequence number, clean result, move to buffer */
2078 cmdptr
->command
= cpu_to_le16(command
);
2079 cmdptr
->size
= cpu_to_le16(cmd_size
+ S_DS_GEN
);
2080 cmdptr
->seqnum
= cpu_to_le16(adapter
->seqnum
);
2082 memcpy(cmdptr
->cmdresp
, cmd
, cmd_size
);
2084 lbs_deb_host("PREP_CMD: command 0x%04x\n", command
);
2086 /* here was the big old switch() statement, which is now obsolete,
2087 * because the caller of lbs_cmd() sets up all of *cmd for us. */
2089 cmdnode
->cmdwaitqwoken
= 0;
2090 lbs_queue_cmd(adapter
, cmdnode
, 1);
2091 wake_up_interruptible(&priv
->waitq
);
2094 wait_event_interruptible(cmdnode
->cmdwait_q
, cmdnode
->cmdwaitqwoken
);
2096 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
2097 if (adapter
->cur_cmd_retcode
) {
2098 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
2099 adapter
->cur_cmd_retcode
);
2100 adapter
->cur_cmd_retcode
= 0;
2103 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
2106 lbs_deb_leave_args(LBS_DEB_HOST
, "ret %d", ret
);
2109 EXPORT_SYMBOL_GPL(lbs_cmd
);