2 * This file contains the handling of command
3 * responses as well as events generated by firmware.
5 #include <linux/delay.h>
6 #include <linux/if_arp.h>
7 #include <linux/netdevice.h>
9 #include <net/iw_handler.h>
19 * @brief This function handles disconnect event. it
20 * reports disconnect to upper layer, clean tx/rx packets,
21 * reset link state etc.
23 * @param priv A pointer to struct lbs_private structure
26 void lbs_mac_event_disconnected(struct lbs_private
*priv
)
28 struct lbs_adapter
*adapter
= priv
->adapter
;
29 union iwreq_data wrqu
;
31 if (adapter
->connect_status
!= LBS_CONNECTED
)
34 lbs_deb_enter(LBS_DEB_ASSOC
);
36 memset(wrqu
.ap_addr
.sa_data
, 0x00, ETH_ALEN
);
37 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
40 * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
41 * It causes problem in the Supplicant
44 msleep_interruptible(1000);
45 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
47 /* Free Tx and Rx packets */
48 kfree_skb(priv
->adapter
->currenttxskb
);
49 priv
->adapter
->currenttxskb
= NULL
;
51 /* report disconnect to upper layer */
52 netif_stop_queue(priv
->dev
);
53 netif_carrier_off(priv
->dev
);
55 /* reset SNR/NF/RSSI values */
56 memset(adapter
->SNR
, 0x00, sizeof(adapter
->SNR
));
57 memset(adapter
->NF
, 0x00, sizeof(adapter
->NF
));
58 memset(adapter
->RSSI
, 0x00, sizeof(adapter
->RSSI
));
59 memset(adapter
->rawSNR
, 0x00, sizeof(adapter
->rawSNR
));
60 memset(adapter
->rawNF
, 0x00, sizeof(adapter
->rawNF
));
61 adapter
->nextSNRNF
= 0;
62 adapter
->numSNRNF
= 0;
63 adapter
->connect_status
= LBS_DISCONNECTED
;
65 /* Clear out associated SSID and BSSID since connection is
68 memset(&adapter
->curbssparams
.bssid
, 0, ETH_ALEN
);
69 memset(&adapter
->curbssparams
.ssid
, 0, IW_ESSID_MAX_SIZE
);
70 adapter
->curbssparams
.ssid_len
= 0;
72 if (adapter
->psstate
!= PS_STATE_FULL_POWER
) {
73 /* make firmware to exit PS mode */
74 lbs_deb_cmd("disconnected, so exit PS mode\n");
75 lbs_ps_wakeup(priv
, 0);
77 lbs_deb_leave(LBS_DEB_CMD
);
81 * @brief This function handles MIC failure event.
83 * @param priv A pointer to struct lbs_private structure
84 * @para event the event id
87 static void handle_mic_failureevent(struct lbs_private
*priv
, u32 event
)
91 lbs_deb_enter(LBS_DEB_CMD
);
92 memset(buf
, 0, sizeof(buf
));
94 sprintf(buf
, "%s", "MLME-MICHAELMICFAILURE.indication ");
96 if (event
== MACREG_INT_CODE_MIC_ERR_UNICAST
) {
97 strcat(buf
, "unicast ");
99 strcat(buf
, "multicast ");
102 lbs_send_iwevcustom_event(priv
, buf
);
103 lbs_deb_leave(LBS_DEB_CMD
);
106 static int lbs_ret_reg_access(struct lbs_private
*priv
,
107 u16 type
, struct cmd_ds_command
*resp
)
110 struct lbs_adapter
*adapter
= priv
->adapter
;
112 lbs_deb_enter(LBS_DEB_CMD
);
115 case CMD_RET(CMD_MAC_REG_ACCESS
):
117 struct cmd_ds_mac_reg_access
*reg
= &resp
->params
.macreg
;
119 adapter
->offsetvalue
.offset
= (u32
)le16_to_cpu(reg
->offset
);
120 adapter
->offsetvalue
.value
= le32_to_cpu(reg
->value
);
124 case CMD_RET(CMD_BBP_REG_ACCESS
):
126 struct cmd_ds_bbp_reg_access
*reg
= &resp
->params
.bbpreg
;
128 adapter
->offsetvalue
.offset
= (u32
)le16_to_cpu(reg
->offset
);
129 adapter
->offsetvalue
.value
= reg
->value
;
133 case CMD_RET(CMD_RF_REG_ACCESS
):
135 struct cmd_ds_rf_reg_access
*reg
= &resp
->params
.rfreg
;
137 adapter
->offsetvalue
.offset
= (u32
)le16_to_cpu(reg
->offset
);
138 adapter
->offsetvalue
.value
= reg
->value
;
146 lbs_deb_leave_args(LBS_DEB_CMD
, "ret %d", ret
);
150 static int lbs_ret_get_hw_spec(struct lbs_private
*priv
,
151 struct cmd_ds_command
*resp
)
154 struct cmd_ds_get_hw_spec
*hwspec
= &resp
->params
.hwspec
;
155 struct lbs_adapter
*adapter
= priv
->adapter
;
157 DECLARE_MAC_BUF(mac
);
159 lbs_deb_enter(LBS_DEB_CMD
);
161 adapter
->fwcapinfo
= le32_to_cpu(hwspec
->fwcapinfo
);
163 memcpy(adapter
->fwreleasenumber
, hwspec
->fwreleasenumber
, 4);
165 lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n",
166 adapter
->fwreleasenumber
[2], adapter
->fwreleasenumber
[1],
167 adapter
->fwreleasenumber
[0], adapter
->fwreleasenumber
[3]);
168 lbs_deb_cmd("GET_HW_SPEC: MAC addr %s\n",
169 print_mac(mac
, hwspec
->permanentaddr
));
170 lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
171 hwspec
->hwifversion
, hwspec
->version
);
173 /* Clamp region code to 8-bit since FW spec indicates that it should
174 * only ever be 8-bit, even though the field size is 16-bit. Some firmware
175 * returns non-zero high 8 bits here.
177 adapter
->regioncode
= le16_to_cpu(hwspec
->regioncode
) & 0xFF;
179 for (i
= 0; i
< MRVDRV_MAX_REGION_CODE
; i
++) {
180 /* use the region code to search for the index */
181 if (adapter
->regioncode
== lbs_region_code_to_index
[i
]) {
186 /* if it's unidentified region code, use the default (USA) */
187 if (i
>= MRVDRV_MAX_REGION_CODE
) {
188 adapter
->regioncode
= 0x10;
189 lbs_pr_info("unidentified region code; using the default (USA)\n");
192 if (adapter
->current_addr
[0] == 0xff)
193 memmove(adapter
->current_addr
, hwspec
->permanentaddr
, ETH_ALEN
);
195 memcpy(priv
->dev
->dev_addr
, adapter
->current_addr
, ETH_ALEN
);
197 memcpy(priv
->mesh_dev
->dev_addr
, adapter
->current_addr
, ETH_ALEN
);
199 if (lbs_set_regiontable(priv
, adapter
->regioncode
, 0)) {
204 if (lbs_set_universaltable(priv
, 0)) {
210 lbs_deb_enter_args(LBS_DEB_CMD
, "ret %d", ret
);
214 static int lbs_ret_802_11_sleep_params(struct lbs_private
*priv
,
215 struct cmd_ds_command
*resp
)
217 struct cmd_ds_802_11_sleep_params
*sp
= &resp
->params
.sleep_params
;
218 struct lbs_adapter
*adapter
= priv
->adapter
;
220 lbs_deb_enter(LBS_DEB_CMD
);
222 lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
223 "extsleepclk 0x%x\n", le16_to_cpu(sp
->error
),
224 le16_to_cpu(sp
->offset
), le16_to_cpu(sp
->stabletime
),
225 sp
->calcontrol
, sp
->externalsleepclk
);
227 adapter
->sp
.sp_error
= le16_to_cpu(sp
->error
);
228 adapter
->sp
.sp_offset
= le16_to_cpu(sp
->offset
);
229 adapter
->sp
.sp_stabletime
= le16_to_cpu(sp
->stabletime
);
230 adapter
->sp
.sp_calcontrol
= sp
->calcontrol
;
231 adapter
->sp
.sp_extsleepclk
= sp
->externalsleepclk
;
232 adapter
->sp
.sp_reserved
= le16_to_cpu(sp
->reserved
);
234 lbs_deb_enter(LBS_DEB_CMD
);
238 static int lbs_ret_802_11_stat(struct lbs_private
*priv
,
239 struct cmd_ds_command
*resp
)
241 lbs_deb_enter(LBS_DEB_CMD
);
242 /* currently adapter->wlan802_11Stat is unused
244 struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
245 struct lbs_adapter *adapter = priv->adapter;
247 // TODO Convert it to Big endian befor copy
248 memcpy(&adapter->wlan802_11Stat,
249 p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
251 lbs_deb_leave(LBS_DEB_CMD
);
255 static int lbs_ret_802_11_snmp_mib(struct lbs_private
*priv
,
256 struct cmd_ds_command
*resp
)
258 struct cmd_ds_802_11_snmp_mib
*smib
= &resp
->params
.smib
;
259 u16 oid
= le16_to_cpu(smib
->oid
);
260 u16 querytype
= le16_to_cpu(smib
->querytype
);
262 lbs_deb_enter(LBS_DEB_CMD
);
264 lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid
,
266 lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib
->bufsize
));
268 if (querytype
== CMD_ACT_GET
) {
271 priv
->adapter
->fragthsd
=
272 le16_to_cpu(*((__le16
*)(smib
->value
)));
273 lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
274 priv
->adapter
->fragthsd
);
277 priv
->adapter
->rtsthsd
=
278 le16_to_cpu(*((__le16
*)(smib
->value
)));
279 lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
280 priv
->adapter
->rtsthsd
);
282 case SHORT_RETRYLIM_I
:
283 priv
->adapter
->txretrycount
=
284 le16_to_cpu(*((__le16
*)(smib
->value
)));
285 lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
286 priv
->adapter
->rtsthsd
);
293 lbs_deb_enter(LBS_DEB_CMD
);
297 static int lbs_ret_802_11_key_material(struct lbs_private
*priv
,
298 struct cmd_ds_command
*resp
)
300 struct cmd_ds_802_11_key_material
*pkeymaterial
=
301 &resp
->params
.keymaterial
;
302 struct lbs_adapter
*adapter
= priv
->adapter
;
303 u16 action
= le16_to_cpu(pkeymaterial
->action
);
305 lbs_deb_enter(LBS_DEB_CMD
);
307 /* Copy the returned key to driver private data */
308 if (action
== CMD_ACT_GET
) {
309 u8
* buf_ptr
= (u8
*) &pkeymaterial
->keyParamSet
;
310 u8
* resp_end
= (u8
*) (resp
+ le16_to_cpu(resp
->size
));
312 while (buf_ptr
< resp_end
) {
313 struct MrvlIEtype_keyParamSet
* pkeyparamset
=
314 (struct MrvlIEtype_keyParamSet
*) buf_ptr
;
315 struct enc_key
* pkey
;
316 u16 param_set_len
= le16_to_cpu(pkeyparamset
->length
);
317 u16 key_len
= le16_to_cpu(pkeyparamset
->keylen
);
318 u16 key_flags
= le16_to_cpu(pkeyparamset
->keyinfo
);
319 u16 key_type
= le16_to_cpu(pkeyparamset
->keytypeid
);
322 end
= (u8
*) pkeyparamset
+ sizeof (pkeyparamset
->type
)
323 + sizeof (pkeyparamset
->length
)
325 /* Make sure we don't access past the end of the IEs */
329 if (key_flags
& KEY_INFO_WPA_UNICAST
)
330 pkey
= &adapter
->wpa_unicast_key
;
331 else if (key_flags
& KEY_INFO_WPA_MCAST
)
332 pkey
= &adapter
->wpa_mcast_key
;
336 /* Copy returned key into driver */
337 memset(pkey
, 0, sizeof(struct enc_key
));
338 if (key_len
> sizeof(pkey
->key
))
340 pkey
->type
= key_type
;
341 pkey
->flags
= key_flags
;
343 memcpy(pkey
->key
, pkeyparamset
->key
, pkey
->len
);
349 lbs_deb_enter(LBS_DEB_CMD
);
353 static int lbs_ret_802_11_mac_address(struct lbs_private
*priv
,
354 struct cmd_ds_command
*resp
)
356 struct cmd_ds_802_11_mac_address
*macadd
= &resp
->params
.macadd
;
357 struct lbs_adapter
*adapter
= priv
->adapter
;
359 lbs_deb_enter(LBS_DEB_CMD
);
361 memcpy(adapter
->current_addr
, macadd
->macadd
, ETH_ALEN
);
363 lbs_deb_enter(LBS_DEB_CMD
);
367 static int lbs_ret_802_11_rf_tx_power(struct lbs_private
*priv
,
368 struct cmd_ds_command
*resp
)
370 struct cmd_ds_802_11_rf_tx_power
*rtp
= &resp
->params
.txp
;
371 struct lbs_adapter
*adapter
= priv
->adapter
;
373 lbs_deb_enter(LBS_DEB_CMD
);
375 adapter
->txpowerlevel
= le16_to_cpu(rtp
->currentlevel
);
377 lbs_deb_cmd("TX power currently %d\n", adapter
->txpowerlevel
);
379 lbs_deb_leave(LBS_DEB_CMD
);
383 static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private
*priv
,
384 struct cmd_ds_command
*resp
)
386 struct cmd_ds_802_11_rate_adapt_rateset
*rates
= &resp
->params
.rateset
;
387 struct lbs_adapter
*adapter
= priv
->adapter
;
389 lbs_deb_enter(LBS_DEB_CMD
);
391 if (rates
->action
== CMD_ACT_GET
) {
392 adapter
->enablehwauto
= le16_to_cpu(rates
->enablehwauto
);
393 adapter
->ratebitmap
= le16_to_cpu(rates
->bitmap
);
396 lbs_deb_leave(LBS_DEB_CMD
);
400 static int lbs_ret_802_11_data_rate(struct lbs_private
*priv
,
401 struct cmd_ds_command
*resp
)
403 struct cmd_ds_802_11_data_rate
*pdatarate
= &resp
->params
.drate
;
404 struct lbs_adapter
*adapter
= priv
->adapter
;
406 lbs_deb_enter(LBS_DEB_CMD
);
408 lbs_deb_hex(LBS_DEB_CMD
, "DATA_RATE_RESP", (u8
*) pdatarate
,
409 sizeof(struct cmd_ds_802_11_data_rate
));
411 /* FIXME: get actual rates FW can do if this command actually returns
412 * all data rates supported.
414 adapter
->cur_rate
= lbs_fw_index_to_data_rate(pdatarate
->rates
[0]);
415 lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", adapter
->cur_rate
);
417 lbs_deb_leave(LBS_DEB_CMD
);
421 static int lbs_ret_802_11_rf_channel(struct lbs_private
*priv
,
422 struct cmd_ds_command
*resp
)
424 struct cmd_ds_802_11_rf_channel
*rfchannel
= &resp
->params
.rfchannel
;
425 struct lbs_adapter
*adapter
= priv
->adapter
;
426 u16 action
= le16_to_cpu(rfchannel
->action
);
427 u16 newchannel
= le16_to_cpu(rfchannel
->currentchannel
);
429 lbs_deb_enter(LBS_DEB_CMD
);
431 if (action
== CMD_OPT_802_11_RF_CHANNEL_GET
432 && adapter
->curbssparams
.channel
!= newchannel
) {
433 lbs_deb_cmd("channel switch from %d to %d\n",
434 adapter
->curbssparams
.channel
, newchannel
);
436 /* Update the channel again */
437 adapter
->curbssparams
.channel
= newchannel
;
440 lbs_deb_enter(LBS_DEB_CMD
);
444 static int lbs_ret_802_11_rssi(struct lbs_private
*priv
,
445 struct cmd_ds_command
*resp
)
447 struct cmd_ds_802_11_rssi_rsp
*rssirsp
= &resp
->params
.rssirsp
;
448 struct lbs_adapter
*adapter
= priv
->adapter
;
450 lbs_deb_enter(LBS_DEB_CMD
);
452 /* store the non average value */
453 adapter
->SNR
[TYPE_BEACON
][TYPE_NOAVG
] = le16_to_cpu(rssirsp
->SNR
);
454 adapter
->NF
[TYPE_BEACON
][TYPE_NOAVG
] = le16_to_cpu(rssirsp
->noisefloor
);
456 adapter
->SNR
[TYPE_BEACON
][TYPE_AVG
] = le16_to_cpu(rssirsp
->avgSNR
);
457 adapter
->NF
[TYPE_BEACON
][TYPE_AVG
] = le16_to_cpu(rssirsp
->avgnoisefloor
);
459 adapter
->RSSI
[TYPE_BEACON
][TYPE_NOAVG
] =
460 CAL_RSSI(adapter
->SNR
[TYPE_BEACON
][TYPE_NOAVG
],
461 adapter
->NF
[TYPE_BEACON
][TYPE_NOAVG
]);
463 adapter
->RSSI
[TYPE_BEACON
][TYPE_AVG
] =
464 CAL_RSSI(adapter
->SNR
[TYPE_BEACON
][TYPE_AVG
] / AVG_SCALE
,
465 adapter
->NF
[TYPE_BEACON
][TYPE_AVG
] / AVG_SCALE
);
467 lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
468 adapter
->RSSI
[TYPE_BEACON
][TYPE_NOAVG
],
469 adapter
->RSSI
[TYPE_BEACON
][TYPE_AVG
]);
471 lbs_deb_leave(LBS_DEB_CMD
);
475 static int lbs_ret_802_11_eeprom_access(struct lbs_private
*priv
,
476 struct cmd_ds_command
*resp
)
478 struct lbs_adapter
*adapter
= priv
->adapter
;
479 struct lbs_ioctl_regrdwr
*pbuf
;
480 pbuf
= (struct lbs_ioctl_regrdwr
*) adapter
->prdeeprom
;
482 lbs_deb_enter_args(LBS_DEB_CMD
, "len %d",
483 le16_to_cpu(resp
->params
.rdeeprom
.bytecount
));
484 if (pbuf
->NOB
< le16_to_cpu(resp
->params
.rdeeprom
.bytecount
)) {
486 lbs_deb_cmd("EEPROM read length too big\n");
489 pbuf
->NOB
= le16_to_cpu(resp
->params
.rdeeprom
.bytecount
);
492 memcpy(&pbuf
->value
, (u8
*) & resp
->params
.rdeeprom
.value
,
493 le16_to_cpu(resp
->params
.rdeeprom
.bytecount
));
494 lbs_deb_hex(LBS_DEB_CMD
, "EEPROM", (char *)&pbuf
->value
,
495 le16_to_cpu(resp
->params
.rdeeprom
.bytecount
));
497 lbs_deb_leave(LBS_DEB_CMD
);
501 static int lbs_ret_get_log(struct lbs_private
*priv
,
502 struct cmd_ds_command
*resp
)
504 struct cmd_ds_802_11_get_log
*logmessage
= &resp
->params
.glog
;
505 struct lbs_adapter
*adapter
= priv
->adapter
;
507 lbs_deb_enter(LBS_DEB_CMD
);
509 /* Stored little-endian */
510 memcpy(&adapter
->logmsg
, logmessage
, sizeof(struct cmd_ds_802_11_get_log
));
512 lbs_deb_leave(LBS_DEB_CMD
);
516 static int lbs_ret_802_11_enable_rsn(struct lbs_private
*priv
,
517 struct cmd_ds_command
*resp
)
519 struct cmd_ds_802_11_enable_rsn
*enable_rsn
= &resp
->params
.enbrsn
;
520 struct lbs_adapter
*adapter
= priv
->adapter
;
521 u32
* pdata_buf
= adapter
->cur_cmd
->pdata_buf
;
523 lbs_deb_enter(LBS_DEB_CMD
);
525 if (enable_rsn
->action
== cpu_to_le16(CMD_ACT_GET
)) {
527 *pdata_buf
= (u32
) le16_to_cpu(enable_rsn
->enable
);
530 lbs_deb_leave(LBS_DEB_CMD
);
534 static int lbs_ret_802_11_bcn_ctrl(struct lbs_private
* priv
,
535 struct cmd_ds_command
*resp
)
537 struct cmd_ds_802_11_beacon_control
*bcn_ctrl
=
538 &resp
->params
.bcn_ctrl
;
539 struct lbs_adapter
*adapter
= priv
->adapter
;
541 lbs_deb_enter(LBS_DEB_CMD
);
543 if (bcn_ctrl
->action
== CMD_ACT_GET
) {
544 adapter
->beacon_enable
= (u8
) le16_to_cpu(bcn_ctrl
->beacon_enable
);
545 adapter
->beacon_period
= le16_to_cpu(bcn_ctrl
->beacon_period
);
548 lbs_deb_enter(LBS_DEB_CMD
);
552 static int lbs_ret_802_11_subscribe_event(struct lbs_private
*priv
,
553 struct cmd_ds_command
*resp
)
555 struct lbs_adapter
*adapter
= priv
->adapter
;
556 struct cmd_ds_802_11_subscribe_event
*cmd_event
=
557 &resp
->params
.subscribe_event
;
558 struct cmd_ds_802_11_subscribe_event
*dst_event
=
559 adapter
->cur_cmd
->pdata_buf
;
561 lbs_deb_enter(LBS_DEB_CMD
);
563 if (dst_event
->action
== cpu_to_le16(CMD_ACT_GET
)) {
564 dst_event
->events
= le16_to_cpu(cmd_event
->events
);
565 memcpy(dst_event
->tlv
, cmd_event
->tlv
, sizeof(dst_event
->tlv
));
568 lbs_deb_leave(LBS_DEB_CMD
);
572 static inline int handle_cmd_response(u16 respcmd
,
573 struct cmd_ds_command
*resp
,
574 struct lbs_private
*priv
)
578 struct lbs_adapter
*adapter
= priv
->adapter
;
580 lbs_deb_enter(LBS_DEB_HOST
);
583 case CMD_RET(CMD_MAC_REG_ACCESS
):
584 case CMD_RET(CMD_BBP_REG_ACCESS
):
585 case CMD_RET(CMD_RF_REG_ACCESS
):
586 ret
= lbs_ret_reg_access(priv
, respcmd
, resp
);
589 case CMD_RET(CMD_GET_HW_SPEC
):
590 ret
= lbs_ret_get_hw_spec(priv
, resp
);
593 case CMD_RET(CMD_802_11_SCAN
):
594 ret
= lbs_ret_80211_scan(priv
, resp
);
597 case CMD_RET(CMD_802_11_GET_LOG
):
598 ret
= lbs_ret_get_log(priv
, resp
);
601 case CMD_RET_802_11_ASSOCIATE
:
602 case CMD_RET(CMD_802_11_ASSOCIATE
):
603 case CMD_RET(CMD_802_11_REASSOCIATE
):
604 ret
= lbs_ret_80211_associate(priv
, resp
);
607 case CMD_RET(CMD_802_11_DISASSOCIATE
):
608 case CMD_RET(CMD_802_11_DEAUTHENTICATE
):
609 ret
= lbs_ret_80211_disassociate(priv
, resp
);
612 case CMD_RET(CMD_802_11_AD_HOC_START
):
613 case CMD_RET(CMD_802_11_AD_HOC_JOIN
):
614 ret
= lbs_ret_80211_ad_hoc_start(priv
, resp
);
617 case CMD_RET(CMD_802_11_GET_STAT
):
618 ret
= lbs_ret_802_11_stat(priv
, resp
);
621 case CMD_RET(CMD_802_11_SNMP_MIB
):
622 ret
= lbs_ret_802_11_snmp_mib(priv
, resp
);
625 case CMD_RET(CMD_802_11_RF_TX_POWER
):
626 ret
= lbs_ret_802_11_rf_tx_power(priv
, resp
);
629 case CMD_RET(CMD_802_11_SET_AFC
):
630 case CMD_RET(CMD_802_11_GET_AFC
):
631 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
632 memmove(adapter
->cur_cmd
->pdata_buf
, &resp
->params
.afc
,
633 sizeof(struct cmd_ds_802_11_afc
));
634 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
638 case CMD_RET(CMD_MAC_MULTICAST_ADR
):
639 case CMD_RET(CMD_MAC_CONTROL
):
640 case CMD_RET(CMD_802_11_SET_WEP
):
641 case CMD_RET(CMD_802_11_RESET
):
642 case CMD_RET(CMD_802_11_AUTHENTICATE
):
643 case CMD_RET(CMD_802_11_RADIO_CONTROL
):
644 case CMD_RET(CMD_802_11_BEACON_STOP
):
647 case CMD_RET(CMD_802_11_ENABLE_RSN
):
648 ret
= lbs_ret_802_11_enable_rsn(priv
, resp
);
651 case CMD_RET(CMD_802_11_DATA_RATE
):
652 ret
= lbs_ret_802_11_data_rate(priv
, resp
);
654 case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET
):
655 ret
= lbs_ret_802_11_rate_adapt_rateset(priv
, resp
);
657 case CMD_RET(CMD_802_11_RF_CHANNEL
):
658 ret
= lbs_ret_802_11_rf_channel(priv
, resp
);
661 case CMD_RET(CMD_802_11_RSSI
):
662 ret
= lbs_ret_802_11_rssi(priv
, resp
);
665 case CMD_RET(CMD_802_11_MAC_ADDRESS
):
666 ret
= lbs_ret_802_11_mac_address(priv
, resp
);
669 case CMD_RET(CMD_802_11_AD_HOC_STOP
):
670 ret
= lbs_ret_80211_ad_hoc_stop(priv
, resp
);
673 case CMD_RET(CMD_802_11_KEY_MATERIAL
):
674 ret
= lbs_ret_802_11_key_material(priv
, resp
);
677 case CMD_RET(CMD_802_11_EEPROM_ACCESS
):
678 ret
= lbs_ret_802_11_eeprom_access(priv
, resp
);
681 case CMD_RET(CMD_802_11D_DOMAIN_INFO
):
682 ret
= lbs_ret_802_11d_domain_info(priv
, resp
);
685 case CMD_RET(CMD_802_11_SLEEP_PARAMS
):
686 ret
= lbs_ret_802_11_sleep_params(priv
, resp
);
688 case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT
):
689 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
690 *((u16
*) adapter
->cur_cmd
->pdata_buf
) =
691 le16_to_cpu(resp
->params
.inactivity_timeout
.timeout
);
692 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
695 case CMD_RET(CMD_802_11_TPC_CFG
):
696 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
697 memmove(adapter
->cur_cmd
->pdata_buf
, &resp
->params
.tpccfg
,
698 sizeof(struct cmd_ds_802_11_tpc_cfg
));
699 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
701 case CMD_RET(CMD_802_11_LED_GPIO_CTRL
):
702 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
703 memmove(adapter
->cur_cmd
->pdata_buf
, &resp
->params
.ledgpio
,
704 sizeof(struct cmd_ds_802_11_led_ctrl
));
705 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
707 case CMD_RET(CMD_802_11_SUBSCRIBE_EVENT
):
708 ret
= lbs_ret_802_11_subscribe_event(priv
, resp
);
711 case CMD_RET(CMD_802_11_PWR_CFG
):
712 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
713 memmove(adapter
->cur_cmd
->pdata_buf
, &resp
->params
.pwrcfg
,
714 sizeof(struct cmd_ds_802_11_pwr_cfg
));
715 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
719 case CMD_RET(CMD_GET_TSF
):
720 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
721 memcpy(priv
->adapter
->cur_cmd
->pdata_buf
,
722 &resp
->params
.gettsf
.tsfvalue
, sizeof(u64
));
723 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
725 case CMD_RET(CMD_BT_ACCESS
):
726 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
727 if (adapter
->cur_cmd
->pdata_buf
)
728 memcpy(adapter
->cur_cmd
->pdata_buf
,
729 &resp
->params
.bt
.addr1
, 2 * ETH_ALEN
);
730 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
732 case CMD_RET(CMD_FWT_ACCESS
):
733 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
734 if (adapter
->cur_cmd
->pdata_buf
)
735 memcpy(adapter
->cur_cmd
->pdata_buf
, &resp
->params
.fwt
,
736 sizeof(resp
->params
.fwt
));
737 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
739 case CMD_RET(CMD_MESH_ACCESS
):
740 if (adapter
->cur_cmd
->pdata_buf
)
741 memcpy(adapter
->cur_cmd
->pdata_buf
, &resp
->params
.mesh
,
742 sizeof(resp
->params
.mesh
));
744 case CMD_RET(CMD_802_11_BEACON_CTRL
):
745 ret
= lbs_ret_802_11_bcn_ctrl(priv
, resp
);
749 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
753 lbs_deb_leave(LBS_DEB_HOST
);
757 int lbs_process_rx_command(struct lbs_private
*priv
)
760 struct cmd_ds_command
*resp
;
761 struct lbs_adapter
*adapter
= priv
->adapter
;
766 lbs_deb_enter(LBS_DEB_HOST
);
768 /* Now we got response from FW, cancel the command timer */
769 del_timer(&adapter
->command_timer
);
771 mutex_lock(&adapter
->lock
);
772 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
774 if (!adapter
->cur_cmd
) {
775 lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
777 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
780 resp
= (struct cmd_ds_command
*)(adapter
->cur_cmd
->bufvirtualaddr
);
782 respcmd
= le16_to_cpu(resp
->command
);
783 result
= le16_to_cpu(resp
->result
);
785 lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
786 respcmd
, priv
->upld_len
, jiffies
);
787 lbs_deb_hex(LBS_DEB_HOST
, "CMD_RESP", adapter
->cur_cmd
->bufvirtualaddr
,
790 if (!(respcmd
& 0x8000)) {
791 lbs_deb_host("invalid response!\n");
792 adapter
->cur_cmd_retcode
= -1;
793 __lbs_cleanup_and_insert_cmd(priv
, adapter
->cur_cmd
);
794 adapter
->nr_cmd_pending
--;
795 adapter
->cur_cmd
= NULL
;
796 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
801 /* Store the response code to cur_cmd_retcode. */
802 adapter
->cur_cmd_retcode
= result
;;
804 if (respcmd
== CMD_RET(CMD_802_11_PS_MODE
)) {
805 struct cmd_ds_802_11_ps_mode
*psmode
= &resp
->params
.psmode
;
806 u16 action
= le16_to_cpu(psmode
->action
);
809 "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
813 lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
816 * We should not re-try enter-ps command in
817 * ad-hoc mode. It takes place in
818 * lbs_execute_next_command().
820 if (adapter
->mode
== IW_MODE_ADHOC
&&
821 action
== CMD_SUBCMD_ENTER_PS
)
822 adapter
->psmode
= LBS802_11POWERMODECAM
;
823 } else if (action
== CMD_SUBCMD_ENTER_PS
) {
824 adapter
->needtowakeup
= 0;
825 adapter
->psstate
= PS_STATE_AWAKE
;
827 lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
828 if (adapter
->connect_status
!= LBS_CONNECTED
) {
830 * When Deauth Event received before Enter_PS command
831 * response, We need to wake up the firmware.
834 "disconnected, invoking lbs_ps_wakeup\n");
836 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
837 mutex_unlock(&adapter
->lock
);
838 lbs_ps_wakeup(priv
, 0);
839 mutex_lock(&adapter
->lock
);
840 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
842 } else if (action
== CMD_SUBCMD_EXIT_PS
) {
843 adapter
->needtowakeup
= 0;
844 adapter
->psstate
= PS_STATE_FULL_POWER
;
845 lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
847 lbs_deb_host("CMD_RESP: PS action 0x%X\n", action
);
850 __lbs_cleanup_and_insert_cmd(priv
, adapter
->cur_cmd
);
851 adapter
->nr_cmd_pending
--;
852 adapter
->cur_cmd
= NULL
;
853 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
859 /* If the command is not successful, cleanup and return failure */
860 if ((result
!= 0 || !(respcmd
& 0x8000))) {
861 lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
864 * Handling errors here
867 case CMD_RET(CMD_GET_HW_SPEC
):
868 case CMD_RET(CMD_802_11_RESET
):
869 lbs_deb_host("CMD_RESP: reset failed\n");
874 __lbs_cleanup_and_insert_cmd(priv
, adapter
->cur_cmd
);
875 adapter
->nr_cmd_pending
--;
876 adapter
->cur_cmd
= NULL
;
877 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
883 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
885 ret
= handle_cmd_response(respcmd
, resp
, priv
);
887 spin_lock_irqsave(&adapter
->driver_lock
, flags
);
888 if (adapter
->cur_cmd
) {
889 /* Clean up and Put current command back to cmdfreeq */
890 __lbs_cleanup_and_insert_cmd(priv
, adapter
->cur_cmd
);
891 adapter
->nr_cmd_pending
--;
892 WARN_ON(adapter
->nr_cmd_pending
> 128);
893 adapter
->cur_cmd
= NULL
;
895 spin_unlock_irqrestore(&adapter
->driver_lock
, flags
);
898 mutex_unlock(&adapter
->lock
);
899 lbs_deb_leave_args(LBS_DEB_HOST
, "ret %d", ret
);
903 int lbs_process_event(struct lbs_private
*priv
)
906 struct lbs_adapter
*adapter
= priv
->adapter
;
909 lbs_deb_enter(LBS_DEB_CMD
);
911 spin_lock_irq(&adapter
->driver_lock
);
912 eventcause
= adapter
->eventcause
>> SBI_EVENT_CAUSE_SHIFT
;
913 spin_unlock_irq(&adapter
->driver_lock
);
915 lbs_deb_cmd("event cause %d\n", eventcause
);
917 switch (eventcause
) {
918 case MACREG_INT_CODE_LINK_SENSED
:
919 lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
922 case MACREG_INT_CODE_DEAUTHENTICATED
:
923 lbs_deb_cmd("EVENT: deauthenticated\n");
924 lbs_mac_event_disconnected(priv
);
927 case MACREG_INT_CODE_DISASSOCIATED
:
928 lbs_deb_cmd("EVENT: disassociated\n");
929 lbs_mac_event_disconnected(priv
);
932 case MACREG_INT_CODE_LINK_LOST_NO_SCAN
:
933 lbs_deb_cmd("EVENT: link lost\n");
934 lbs_mac_event_disconnected(priv
);
937 case MACREG_INT_CODE_PS_SLEEP
:
938 lbs_deb_cmd("EVENT: sleep\n");
940 /* handle unexpected PS SLEEP event */
941 if (adapter
->psstate
== PS_STATE_FULL_POWER
) {
943 "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
946 adapter
->psstate
= PS_STATE_PRE_SLEEP
;
948 lbs_ps_confirm_sleep(priv
, (u16
) adapter
->psmode
);
952 case MACREG_INT_CODE_PS_AWAKE
:
953 lbs_deb_cmd("EVENT: awake\n");
955 /* handle unexpected PS AWAKE event */
956 if (adapter
->psstate
== PS_STATE_FULL_POWER
) {
958 "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
962 adapter
->psstate
= PS_STATE_AWAKE
;
964 if (adapter
->needtowakeup
) {
966 * wait for the command processing to finish
967 * before resuming sending
968 * adapter->needtowakeup will be set to FALSE
971 lbs_deb_cmd("waking up ...\n");
972 lbs_ps_wakeup(priv
, 0);
976 case MACREG_INT_CODE_MIC_ERR_UNICAST
:
977 lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
978 handle_mic_failureevent(priv
, MACREG_INT_CODE_MIC_ERR_UNICAST
);
981 case MACREG_INT_CODE_MIC_ERR_MULTICAST
:
982 lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
983 handle_mic_failureevent(priv
, MACREG_INT_CODE_MIC_ERR_MULTICAST
);
985 case MACREG_INT_CODE_MIB_CHANGED
:
986 case MACREG_INT_CODE_INIT_DONE
:
989 case MACREG_INT_CODE_ADHOC_BCN_LOST
:
990 lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
993 case MACREG_INT_CODE_RSSI_LOW
:
994 lbs_pr_alert("EVENT: rssi low\n");
996 case MACREG_INT_CODE_SNR_LOW
:
997 lbs_pr_alert("EVENT: snr low\n");
999 case MACREG_INT_CODE_MAX_FAIL
:
1000 lbs_pr_alert("EVENT: max fail\n");
1002 case MACREG_INT_CODE_RSSI_HIGH
:
1003 lbs_pr_alert("EVENT: rssi high\n");
1005 case MACREG_INT_CODE_SNR_HIGH
:
1006 lbs_pr_alert("EVENT: snr high\n");
1009 case MACREG_INT_CODE_MESH_AUTO_STARTED
:
1010 /* Ignore spurious autostart events if autostart is disabled */
1011 if (!priv
->mesh_autostart_enabled
) {
1012 lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
1015 lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
1016 adapter
->mesh_connect_status
= LBS_CONNECTED
;
1017 if (priv
->mesh_open
== 1) {
1018 netif_wake_queue(priv
->mesh_dev
);
1019 netif_carrier_on(priv
->mesh_dev
);
1021 adapter
->mode
= IW_MODE_ADHOC
;
1022 schedule_work(&priv
->sync_channel
);
1026 lbs_pr_alert("EVENT: unknown event id %d\n", eventcause
);
1030 spin_lock_irq(&adapter
->driver_lock
);
1031 adapter
->eventcause
= 0;
1032 spin_unlock_irq(&adapter
->driver_lock
);
1034 lbs_deb_leave_args(LBS_DEB_CMD
, "ret %d", ret
);