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 union iwreq_data wrqu
;
30 if (priv
->connect_status
!= LBS_CONNECTED
)
33 lbs_deb_enter(LBS_DEB_ASSOC
);
35 memset(wrqu
.ap_addr
.sa_data
, 0x00, ETH_ALEN
);
36 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
39 * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
40 * It causes problem in the Supplicant
43 msleep_interruptible(1000);
44 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
46 /* Free Tx and Rx packets */
47 kfree_skb(priv
->currenttxskb
);
48 priv
->currenttxskb
= NULL
;
50 /* report disconnect to upper layer */
51 netif_stop_queue(priv
->dev
);
52 netif_carrier_off(priv
->dev
);
54 /* reset SNR/NF/RSSI values */
55 memset(priv
->SNR
, 0x00, sizeof(priv
->SNR
));
56 memset(priv
->NF
, 0x00, sizeof(priv
->NF
));
57 memset(priv
->RSSI
, 0x00, sizeof(priv
->RSSI
));
58 memset(priv
->rawSNR
, 0x00, sizeof(priv
->rawSNR
));
59 memset(priv
->rawNF
, 0x00, sizeof(priv
->rawNF
));
62 priv
->connect_status
= LBS_DISCONNECTED
;
64 /* Clear out associated SSID and BSSID since connection is
67 memset(&priv
->curbssparams
.bssid
, 0, ETH_ALEN
);
68 memset(&priv
->curbssparams
.ssid
, 0, IW_ESSID_MAX_SIZE
);
69 priv
->curbssparams
.ssid_len
= 0;
71 if (priv
->psstate
!= PS_STATE_FULL_POWER
) {
72 /* make firmware to exit PS mode */
73 lbs_deb_cmd("disconnected, so exit PS mode\n");
74 lbs_ps_wakeup(priv
, 0);
76 lbs_deb_leave(LBS_DEB_CMD
);
80 * @brief This function handles MIC failure event.
82 * @param priv A pointer to struct lbs_private structure
83 * @para event the event id
86 static void handle_mic_failureevent(struct lbs_private
*priv
, u32 event
)
90 lbs_deb_enter(LBS_DEB_CMD
);
91 memset(buf
, 0, sizeof(buf
));
93 sprintf(buf
, "%s", "MLME-MICHAELMICFAILURE.indication ");
95 if (event
== MACREG_INT_CODE_MIC_ERR_UNICAST
) {
96 strcat(buf
, "unicast ");
98 strcat(buf
, "multicast ");
101 lbs_send_iwevcustom_event(priv
, buf
);
102 lbs_deb_leave(LBS_DEB_CMD
);
105 static int lbs_ret_reg_access(struct lbs_private
*priv
,
106 u16 type
, struct cmd_ds_command
*resp
)
110 lbs_deb_enter(LBS_DEB_CMD
);
113 case CMD_RET(CMD_MAC_REG_ACCESS
):
115 struct cmd_ds_mac_reg_access
*reg
= &resp
->params
.macreg
;
117 priv
->offsetvalue
.offset
= (u32
)le16_to_cpu(reg
->offset
);
118 priv
->offsetvalue
.value
= le32_to_cpu(reg
->value
);
122 case CMD_RET(CMD_BBP_REG_ACCESS
):
124 struct cmd_ds_bbp_reg_access
*reg
= &resp
->params
.bbpreg
;
126 priv
->offsetvalue
.offset
= (u32
)le16_to_cpu(reg
->offset
);
127 priv
->offsetvalue
.value
= reg
->value
;
131 case CMD_RET(CMD_RF_REG_ACCESS
):
133 struct cmd_ds_rf_reg_access
*reg
= &resp
->params
.rfreg
;
135 priv
->offsetvalue
.offset
= (u32
)le16_to_cpu(reg
->offset
);
136 priv
->offsetvalue
.value
= reg
->value
;
144 lbs_deb_leave_args(LBS_DEB_CMD
, "ret %d", ret
);
148 static int lbs_ret_get_hw_spec(struct lbs_private
*priv
,
149 struct cmd_ds_command
*resp
)
152 struct cmd_ds_get_hw_spec
*hwspec
= &resp
->params
.hwspec
;
154 DECLARE_MAC_BUF(mac
);
156 lbs_deb_enter(LBS_DEB_CMD
);
158 priv
->fwcapinfo
= le32_to_cpu(hwspec
->fwcapinfo
);
160 memcpy(priv
->fwreleasenumber
, hwspec
->fwreleasenumber
, 4);
162 lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n",
163 priv
->fwreleasenumber
[2], priv
->fwreleasenumber
[1],
164 priv
->fwreleasenumber
[0], priv
->fwreleasenumber
[3]);
165 lbs_deb_cmd("GET_HW_SPEC: MAC addr %s\n",
166 print_mac(mac
, hwspec
->permanentaddr
));
167 lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
168 hwspec
->hwifversion
, hwspec
->version
);
170 /* Clamp region code to 8-bit since FW spec indicates that it should
171 * only ever be 8-bit, even though the field size is 16-bit. Some firmware
172 * returns non-zero high 8 bits here.
174 priv
->regioncode
= le16_to_cpu(hwspec
->regioncode
) & 0xFF;
176 for (i
= 0; i
< MRVDRV_MAX_REGION_CODE
; i
++) {
177 /* use the region code to search for the index */
178 if (priv
->regioncode
== lbs_region_code_to_index
[i
]) {
183 /* if it's unidentified region code, use the default (USA) */
184 if (i
>= MRVDRV_MAX_REGION_CODE
) {
185 priv
->regioncode
= 0x10;
186 lbs_pr_info("unidentified region code; using the default (USA)\n");
189 if (priv
->current_addr
[0] == 0xff)
190 memmove(priv
->current_addr
, hwspec
->permanentaddr
, ETH_ALEN
);
192 memcpy(priv
->dev
->dev_addr
, priv
->current_addr
, ETH_ALEN
);
194 memcpy(priv
->mesh_dev
->dev_addr
, priv
->current_addr
, ETH_ALEN
);
196 if (lbs_set_regiontable(priv
, priv
->regioncode
, 0)) {
201 if (lbs_set_universaltable(priv
, 0)) {
207 lbs_deb_enter_args(LBS_DEB_CMD
, "ret %d", ret
);
211 static int lbs_ret_802_11_sleep_params(struct lbs_private
*priv
,
212 struct cmd_ds_command
*resp
)
214 struct cmd_ds_802_11_sleep_params
*sp
= &resp
->params
.sleep_params
;
216 lbs_deb_enter(LBS_DEB_CMD
);
218 lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
219 "extsleepclk 0x%x\n", le16_to_cpu(sp
->error
),
220 le16_to_cpu(sp
->offset
), le16_to_cpu(sp
->stabletime
),
221 sp
->calcontrol
, sp
->externalsleepclk
);
223 priv
->sp
.sp_error
= le16_to_cpu(sp
->error
);
224 priv
->sp
.sp_offset
= le16_to_cpu(sp
->offset
);
225 priv
->sp
.sp_stabletime
= le16_to_cpu(sp
->stabletime
);
226 priv
->sp
.sp_calcontrol
= sp
->calcontrol
;
227 priv
->sp
.sp_extsleepclk
= sp
->externalsleepclk
;
228 priv
->sp
.sp_reserved
= le16_to_cpu(sp
->reserved
);
230 lbs_deb_enter(LBS_DEB_CMD
);
234 static int lbs_ret_802_11_stat(struct lbs_private
*priv
,
235 struct cmd_ds_command
*resp
)
237 lbs_deb_enter(LBS_DEB_CMD
);
238 /* currently priv->wlan802_11Stat is unused
240 struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
242 // TODO Convert it to Big endian befor copy
243 memcpy(&priv->wlan802_11Stat,
244 p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
246 lbs_deb_leave(LBS_DEB_CMD
);
250 static int lbs_ret_802_11_snmp_mib(struct lbs_private
*priv
,
251 struct cmd_ds_command
*resp
)
253 struct cmd_ds_802_11_snmp_mib
*smib
= &resp
->params
.smib
;
254 u16 oid
= le16_to_cpu(smib
->oid
);
255 u16 querytype
= le16_to_cpu(smib
->querytype
);
257 lbs_deb_enter(LBS_DEB_CMD
);
259 lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid
,
261 lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib
->bufsize
));
263 if (querytype
== CMD_ACT_GET
) {
267 le16_to_cpu(*((__le16
*)(smib
->value
)));
268 lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
273 le16_to_cpu(*((__le16
*)(smib
->value
)));
274 lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
277 case SHORT_RETRYLIM_I
:
279 le16_to_cpu(*((__le16
*)(smib
->value
)));
280 lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
288 lbs_deb_enter(LBS_DEB_CMD
);
292 static int lbs_ret_802_11_key_material(struct lbs_private
*priv
,
293 struct cmd_ds_command
*resp
)
295 struct cmd_ds_802_11_key_material
*pkeymaterial
=
296 &resp
->params
.keymaterial
;
297 u16 action
= le16_to_cpu(pkeymaterial
->action
);
299 lbs_deb_enter(LBS_DEB_CMD
);
301 /* Copy the returned key to driver private data */
302 if (action
== CMD_ACT_GET
) {
303 u8
* buf_ptr
= (u8
*) &pkeymaterial
->keyParamSet
;
304 u8
* resp_end
= (u8
*) (resp
+ le16_to_cpu(resp
->size
));
306 while (buf_ptr
< resp_end
) {
307 struct MrvlIEtype_keyParamSet
* pkeyparamset
=
308 (struct MrvlIEtype_keyParamSet
*) buf_ptr
;
309 struct enc_key
* pkey
;
310 u16 param_set_len
= le16_to_cpu(pkeyparamset
->length
);
311 u16 key_len
= le16_to_cpu(pkeyparamset
->keylen
);
312 u16 key_flags
= le16_to_cpu(pkeyparamset
->keyinfo
);
313 u16 key_type
= le16_to_cpu(pkeyparamset
->keytypeid
);
316 end
= (u8
*) pkeyparamset
+ sizeof (pkeyparamset
->type
)
317 + sizeof (pkeyparamset
->length
)
319 /* Make sure we don't access past the end of the IEs */
323 if (key_flags
& KEY_INFO_WPA_UNICAST
)
324 pkey
= &priv
->wpa_unicast_key
;
325 else if (key_flags
& KEY_INFO_WPA_MCAST
)
326 pkey
= &priv
->wpa_mcast_key
;
330 /* Copy returned key into driver */
331 memset(pkey
, 0, sizeof(struct enc_key
));
332 if (key_len
> sizeof(pkey
->key
))
334 pkey
->type
= key_type
;
335 pkey
->flags
= key_flags
;
337 memcpy(pkey
->key
, pkeyparamset
->key
, pkey
->len
);
343 lbs_deb_enter(LBS_DEB_CMD
);
347 static int lbs_ret_802_11_mac_address(struct lbs_private
*priv
,
348 struct cmd_ds_command
*resp
)
350 struct cmd_ds_802_11_mac_address
*macadd
= &resp
->params
.macadd
;
352 lbs_deb_enter(LBS_DEB_CMD
);
354 memcpy(priv
->current_addr
, macadd
->macadd
, ETH_ALEN
);
356 lbs_deb_enter(LBS_DEB_CMD
);
360 static int lbs_ret_802_11_rf_tx_power(struct lbs_private
*priv
,
361 struct cmd_ds_command
*resp
)
363 struct cmd_ds_802_11_rf_tx_power
*rtp
= &resp
->params
.txp
;
365 lbs_deb_enter(LBS_DEB_CMD
);
367 priv
->txpowerlevel
= le16_to_cpu(rtp
->currentlevel
);
369 lbs_deb_cmd("TX power currently %d\n", priv
->txpowerlevel
);
371 lbs_deb_leave(LBS_DEB_CMD
);
375 static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private
*priv
,
376 struct cmd_ds_command
*resp
)
378 struct cmd_ds_802_11_rate_adapt_rateset
*rates
= &resp
->params
.rateset
;
380 lbs_deb_enter(LBS_DEB_CMD
);
382 if (rates
->action
== CMD_ACT_GET
) {
383 priv
->enablehwauto
= le16_to_cpu(rates
->enablehwauto
);
384 priv
->ratebitmap
= le16_to_cpu(rates
->bitmap
);
387 lbs_deb_leave(LBS_DEB_CMD
);
391 static int lbs_ret_802_11_data_rate(struct lbs_private
*priv
,
392 struct cmd_ds_command
*resp
)
394 struct cmd_ds_802_11_data_rate
*pdatarate
= &resp
->params
.drate
;
396 lbs_deb_enter(LBS_DEB_CMD
);
398 lbs_deb_hex(LBS_DEB_CMD
, "DATA_RATE_RESP", (u8
*) pdatarate
,
399 sizeof(struct cmd_ds_802_11_data_rate
));
401 /* FIXME: get actual rates FW can do if this command actually returns
402 * all data rates supported.
404 priv
->cur_rate
= lbs_fw_index_to_data_rate(pdatarate
->rates
[0]);
405 lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", priv
->cur_rate
);
407 lbs_deb_leave(LBS_DEB_CMD
);
411 static int lbs_ret_802_11_rf_channel(struct lbs_private
*priv
,
412 struct cmd_ds_command
*resp
)
414 struct cmd_ds_802_11_rf_channel
*rfchannel
= &resp
->params
.rfchannel
;
415 u16 action
= le16_to_cpu(rfchannel
->action
);
416 u16 newchannel
= le16_to_cpu(rfchannel
->currentchannel
);
418 lbs_deb_enter(LBS_DEB_CMD
);
420 if (action
== CMD_OPT_802_11_RF_CHANNEL_GET
421 && priv
->curbssparams
.channel
!= newchannel
) {
422 lbs_deb_cmd("channel switch from %d to %d\n",
423 priv
->curbssparams
.channel
, newchannel
);
425 /* Update the channel again */
426 priv
->curbssparams
.channel
= newchannel
;
429 lbs_deb_enter(LBS_DEB_CMD
);
433 static int lbs_ret_802_11_rssi(struct lbs_private
*priv
,
434 struct cmd_ds_command
*resp
)
436 struct cmd_ds_802_11_rssi_rsp
*rssirsp
= &resp
->params
.rssirsp
;
438 lbs_deb_enter(LBS_DEB_CMD
);
440 /* store the non average value */
441 priv
->SNR
[TYPE_BEACON
][TYPE_NOAVG
] = le16_to_cpu(rssirsp
->SNR
);
442 priv
->NF
[TYPE_BEACON
][TYPE_NOAVG
] = le16_to_cpu(rssirsp
->noisefloor
);
444 priv
->SNR
[TYPE_BEACON
][TYPE_AVG
] = le16_to_cpu(rssirsp
->avgSNR
);
445 priv
->NF
[TYPE_BEACON
][TYPE_AVG
] = le16_to_cpu(rssirsp
->avgnoisefloor
);
447 priv
->RSSI
[TYPE_BEACON
][TYPE_NOAVG
] =
448 CAL_RSSI(priv
->SNR
[TYPE_BEACON
][TYPE_NOAVG
],
449 priv
->NF
[TYPE_BEACON
][TYPE_NOAVG
]);
451 priv
->RSSI
[TYPE_BEACON
][TYPE_AVG
] =
452 CAL_RSSI(priv
->SNR
[TYPE_BEACON
][TYPE_AVG
] / AVG_SCALE
,
453 priv
->NF
[TYPE_BEACON
][TYPE_AVG
] / AVG_SCALE
);
455 lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
456 priv
->RSSI
[TYPE_BEACON
][TYPE_NOAVG
],
457 priv
->RSSI
[TYPE_BEACON
][TYPE_AVG
]);
459 lbs_deb_leave(LBS_DEB_CMD
);
463 static int lbs_ret_802_11_eeprom_access(struct lbs_private
*priv
,
464 struct cmd_ds_command
*resp
)
466 struct lbs_ioctl_regrdwr
*pbuf
;
467 pbuf
= (struct lbs_ioctl_regrdwr
*) priv
->prdeeprom
;
469 lbs_deb_enter_args(LBS_DEB_CMD
, "len %d",
470 le16_to_cpu(resp
->params
.rdeeprom
.bytecount
));
471 if (pbuf
->NOB
< le16_to_cpu(resp
->params
.rdeeprom
.bytecount
)) {
473 lbs_deb_cmd("EEPROM read length too big\n");
476 pbuf
->NOB
= le16_to_cpu(resp
->params
.rdeeprom
.bytecount
);
479 memcpy(&pbuf
->value
, (u8
*) & resp
->params
.rdeeprom
.value
,
480 le16_to_cpu(resp
->params
.rdeeprom
.bytecount
));
481 lbs_deb_hex(LBS_DEB_CMD
, "EEPROM", (char *)&pbuf
->value
,
482 le16_to_cpu(resp
->params
.rdeeprom
.bytecount
));
484 lbs_deb_leave(LBS_DEB_CMD
);
488 static int lbs_ret_get_log(struct lbs_private
*priv
,
489 struct cmd_ds_command
*resp
)
491 struct cmd_ds_802_11_get_log
*logmessage
= &resp
->params
.glog
;
493 lbs_deb_enter(LBS_DEB_CMD
);
495 /* Stored little-endian */
496 memcpy(&priv
->logmsg
, logmessage
, sizeof(struct cmd_ds_802_11_get_log
));
498 lbs_deb_leave(LBS_DEB_CMD
);
502 static int lbs_ret_802_11_enable_rsn(struct lbs_private
*priv
,
503 struct cmd_ds_command
*resp
)
505 struct cmd_ds_802_11_enable_rsn
*enable_rsn
= &resp
->params
.enbrsn
;
506 u32
* pdata_buf
= priv
->cur_cmd
->pdata_buf
;
508 lbs_deb_enter(LBS_DEB_CMD
);
510 if (enable_rsn
->action
== cpu_to_le16(CMD_ACT_GET
)) {
512 *pdata_buf
= (u32
) le16_to_cpu(enable_rsn
->enable
);
515 lbs_deb_leave(LBS_DEB_CMD
);
519 static int lbs_ret_802_11_bcn_ctrl(struct lbs_private
* priv
,
520 struct cmd_ds_command
*resp
)
522 struct cmd_ds_802_11_beacon_control
*bcn_ctrl
=
523 &resp
->params
.bcn_ctrl
;
525 lbs_deb_enter(LBS_DEB_CMD
);
527 if (bcn_ctrl
->action
== CMD_ACT_GET
) {
528 priv
->beacon_enable
= (u8
) le16_to_cpu(bcn_ctrl
->beacon_enable
);
529 priv
->beacon_period
= le16_to_cpu(bcn_ctrl
->beacon_period
);
532 lbs_deb_enter(LBS_DEB_CMD
);
536 static int lbs_ret_802_11_subscribe_event(struct lbs_private
*priv
,
537 struct cmd_ds_command
*resp
)
539 struct cmd_ds_802_11_subscribe_event
*cmd_event
=
540 &resp
->params
.subscribe_event
;
541 struct cmd_ds_802_11_subscribe_event
*dst_event
=
542 priv
->cur_cmd
->pdata_buf
;
544 lbs_deb_enter(LBS_DEB_CMD
);
546 if (dst_event
->action
== cpu_to_le16(CMD_ACT_GET
)) {
547 dst_event
->events
= cmd_event
->events
;
548 memcpy(dst_event
->tlv
, cmd_event
->tlv
, sizeof(dst_event
->tlv
));
551 lbs_deb_leave(LBS_DEB_CMD
);
555 static inline int handle_cmd_response(struct lbs_private
*priv
,
557 struct cmd_ds_command
*resp
)
561 uint16_t respcmd
= le16_to_cpu(resp
->command
);
563 lbs_deb_enter(LBS_DEB_HOST
);
566 case CMD_RET(CMD_MAC_REG_ACCESS
):
567 case CMD_RET(CMD_BBP_REG_ACCESS
):
568 case CMD_RET(CMD_RF_REG_ACCESS
):
569 ret
= lbs_ret_reg_access(priv
, respcmd
, resp
);
572 case CMD_RET(CMD_GET_HW_SPEC
):
573 ret
= lbs_ret_get_hw_spec(priv
, resp
);
576 case CMD_RET(CMD_802_11_SCAN
):
577 ret
= lbs_ret_80211_scan(priv
, resp
);
580 case CMD_RET(CMD_802_11_GET_LOG
):
581 ret
= lbs_ret_get_log(priv
, resp
);
584 case CMD_RET_802_11_ASSOCIATE
:
585 case CMD_RET(CMD_802_11_ASSOCIATE
):
586 case CMD_RET(CMD_802_11_REASSOCIATE
):
587 ret
= lbs_ret_80211_associate(priv
, resp
);
590 case CMD_RET(CMD_802_11_DISASSOCIATE
):
591 case CMD_RET(CMD_802_11_DEAUTHENTICATE
):
592 ret
= lbs_ret_80211_disassociate(priv
, resp
);
595 case CMD_RET(CMD_802_11_AD_HOC_START
):
596 case CMD_RET(CMD_802_11_AD_HOC_JOIN
):
597 ret
= lbs_ret_80211_ad_hoc_start(priv
, resp
);
600 case CMD_RET(CMD_802_11_GET_STAT
):
601 ret
= lbs_ret_802_11_stat(priv
, resp
);
604 case CMD_RET(CMD_802_11_SNMP_MIB
):
605 ret
= lbs_ret_802_11_snmp_mib(priv
, resp
);
608 case CMD_RET(CMD_802_11_RF_TX_POWER
):
609 ret
= lbs_ret_802_11_rf_tx_power(priv
, resp
);
612 case CMD_RET(CMD_802_11_SET_AFC
):
613 case CMD_RET(CMD_802_11_GET_AFC
):
614 spin_lock_irqsave(&priv
->driver_lock
, flags
);
615 memmove(priv
->cur_cmd
->pdata_buf
, &resp
->params
.afc
,
616 sizeof(struct cmd_ds_802_11_afc
));
617 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
621 case CMD_RET(CMD_MAC_MULTICAST_ADR
):
622 case CMD_RET(CMD_MAC_CONTROL
):
623 case CMD_RET(CMD_802_11_SET_WEP
):
624 case CMD_RET(CMD_802_11_RESET
):
625 case CMD_RET(CMD_802_11_AUTHENTICATE
):
626 case CMD_RET(CMD_802_11_RADIO_CONTROL
):
627 case CMD_RET(CMD_802_11_BEACON_STOP
):
630 case CMD_RET(CMD_802_11_ENABLE_RSN
):
631 ret
= lbs_ret_802_11_enable_rsn(priv
, resp
);
634 case CMD_RET(CMD_802_11_DATA_RATE
):
635 ret
= lbs_ret_802_11_data_rate(priv
, resp
);
637 case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET
):
638 ret
= lbs_ret_802_11_rate_adapt_rateset(priv
, resp
);
640 case CMD_RET(CMD_802_11_RF_CHANNEL
):
641 ret
= lbs_ret_802_11_rf_channel(priv
, resp
);
644 case CMD_RET(CMD_802_11_RSSI
):
645 ret
= lbs_ret_802_11_rssi(priv
, resp
);
648 case CMD_RET(CMD_802_11_MAC_ADDRESS
):
649 ret
= lbs_ret_802_11_mac_address(priv
, resp
);
652 case CMD_RET(CMD_802_11_AD_HOC_STOP
):
653 ret
= lbs_ret_80211_ad_hoc_stop(priv
, resp
);
656 case CMD_RET(CMD_802_11_KEY_MATERIAL
):
657 ret
= lbs_ret_802_11_key_material(priv
, resp
);
660 case CMD_RET(CMD_802_11_EEPROM_ACCESS
):
661 ret
= lbs_ret_802_11_eeprom_access(priv
, resp
);
664 case CMD_RET(CMD_802_11D_DOMAIN_INFO
):
665 ret
= lbs_ret_802_11d_domain_info(priv
, resp
);
668 case CMD_RET(CMD_802_11_SLEEP_PARAMS
):
669 ret
= lbs_ret_802_11_sleep_params(priv
, resp
);
671 case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT
):
672 spin_lock_irqsave(&priv
->driver_lock
, flags
);
673 *((u16
*) priv
->cur_cmd
->pdata_buf
) =
674 le16_to_cpu(resp
->params
.inactivity_timeout
.timeout
);
675 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
678 case CMD_RET(CMD_802_11_TPC_CFG
):
679 spin_lock_irqsave(&priv
->driver_lock
, flags
);
680 memmove(priv
->cur_cmd
->pdata_buf
, &resp
->params
.tpccfg
,
681 sizeof(struct cmd_ds_802_11_tpc_cfg
));
682 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
684 case CMD_RET(CMD_802_11_LED_GPIO_CTRL
):
685 spin_lock_irqsave(&priv
->driver_lock
, flags
);
686 memmove(priv
->cur_cmd
->pdata_buf
, &resp
->params
.ledgpio
,
687 sizeof(struct cmd_ds_802_11_led_ctrl
));
688 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
690 case CMD_RET(CMD_802_11_SUBSCRIBE_EVENT
):
691 ret
= lbs_ret_802_11_subscribe_event(priv
, resp
);
694 case CMD_RET(CMD_802_11_PWR_CFG
):
695 spin_lock_irqsave(&priv
->driver_lock
, flags
);
696 memmove(priv
->cur_cmd
->pdata_buf
, &resp
->params
.pwrcfg
,
697 sizeof(struct cmd_ds_802_11_pwr_cfg
));
698 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
702 case CMD_RET(CMD_GET_TSF
):
703 spin_lock_irqsave(&priv
->driver_lock
, flags
);
704 memcpy(priv
->cur_cmd
->pdata_buf
,
705 &resp
->params
.gettsf
.tsfvalue
, sizeof(u64
));
706 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
708 case CMD_RET(CMD_BT_ACCESS
):
709 spin_lock_irqsave(&priv
->driver_lock
, flags
);
710 if (priv
->cur_cmd
->pdata_buf
)
711 memcpy(priv
->cur_cmd
->pdata_buf
,
712 &resp
->params
.bt
.addr1
, 2 * ETH_ALEN
);
713 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
715 case CMD_RET(CMD_FWT_ACCESS
):
716 spin_lock_irqsave(&priv
->driver_lock
, flags
);
717 if (priv
->cur_cmd
->pdata_buf
)
718 memcpy(priv
->cur_cmd
->pdata_buf
, &resp
->params
.fwt
,
719 sizeof(resp
->params
.fwt
));
720 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
722 case CMD_RET(CMD_MESH_ACCESS
):
723 if (priv
->cur_cmd
->pdata_buf
)
724 memcpy(priv
->cur_cmd
->pdata_buf
, &resp
->params
.mesh
,
725 sizeof(resp
->params
.mesh
));
727 case CMD_RET(CMD_802_11_BEACON_CTRL
):
728 ret
= lbs_ret_802_11_bcn_ctrl(priv
, resp
);
732 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
736 lbs_deb_leave(LBS_DEB_HOST
);
740 int lbs_process_rx_command(struct lbs_private
*priv
)
743 struct cmd_ds_command
*resp
;
748 lbs_deb_enter(LBS_DEB_HOST
);
750 /* Now we got response from FW, cancel the command timer */
751 del_timer(&priv
->command_timer
);
753 mutex_lock(&priv
->lock
);
754 spin_lock_irqsave(&priv
->driver_lock
, flags
);
756 if (!priv
->cur_cmd
) {
757 lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
759 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
762 resp
= (struct cmd_ds_command
*)(priv
->cur_cmd
->bufvirtualaddr
);
764 respcmd
= le16_to_cpu(resp
->command
);
765 result
= le16_to_cpu(resp
->result
);
767 lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
768 respcmd
, priv
->upld_len
, jiffies
);
769 lbs_deb_hex(LBS_DEB_HOST
, "CMD_RESP", priv
->cur_cmd
->bufvirtualaddr
,
772 if (!(respcmd
& 0x8000)) {
773 lbs_deb_host("invalid response!\n");
774 priv
->cur_cmd_retcode
= -1;
775 __lbs_cleanup_and_insert_cmd(priv
, priv
->cur_cmd
);
776 priv
->cur_cmd
= NULL
;
777 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
782 /* Store the response code to cur_cmd_retcode. */
783 priv
->cur_cmd_retcode
= result
;
785 if (respcmd
== CMD_RET(CMD_802_11_PS_MODE
)) {
786 struct cmd_ds_802_11_ps_mode
*psmode
= &resp
->params
.psmode
;
787 u16 action
= le16_to_cpu(psmode
->action
);
790 "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
794 lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
797 * We should not re-try enter-ps command in
798 * ad-hoc mode. It takes place in
799 * lbs_execute_next_command().
801 if (priv
->mode
== IW_MODE_ADHOC
&&
802 action
== CMD_SUBCMD_ENTER_PS
)
803 priv
->psmode
= LBS802_11POWERMODECAM
;
804 } else if (action
== CMD_SUBCMD_ENTER_PS
) {
805 priv
->needtowakeup
= 0;
806 priv
->psstate
= PS_STATE_AWAKE
;
808 lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
809 if (priv
->connect_status
!= LBS_CONNECTED
) {
811 * When Deauth Event received before Enter_PS command
812 * response, We need to wake up the firmware.
815 "disconnected, invoking lbs_ps_wakeup\n");
817 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
818 mutex_unlock(&priv
->lock
);
819 lbs_ps_wakeup(priv
, 0);
820 mutex_lock(&priv
->lock
);
821 spin_lock_irqsave(&priv
->driver_lock
, flags
);
823 } else if (action
== CMD_SUBCMD_EXIT_PS
) {
824 priv
->needtowakeup
= 0;
825 priv
->psstate
= PS_STATE_FULL_POWER
;
826 lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
828 lbs_deb_host("CMD_RESP: PS action 0x%X\n", action
);
831 __lbs_cleanup_and_insert_cmd(priv
, priv
->cur_cmd
);
832 priv
->cur_cmd
= NULL
;
833 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
839 /* If the command is not successful, cleanup and return failure */
840 if ((result
!= 0 || !(respcmd
& 0x8000))) {
841 lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
844 * Handling errors here
847 case CMD_RET(CMD_GET_HW_SPEC
):
848 case CMD_RET(CMD_802_11_RESET
):
849 lbs_deb_host("CMD_RESP: reset failed\n");
854 __lbs_cleanup_and_insert_cmd(priv
, priv
->cur_cmd
);
855 priv
->cur_cmd
= NULL
;
856 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
862 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
864 if (priv
->cur_cmd
&& priv
->cur_cmd
->callback
) {
865 ret
= priv
->cur_cmd
->callback(priv
, priv
->cur_cmd
->callback_arg
,
866 (struct cmd_header
*) resp
);
868 ret
= handle_cmd_response(priv
, 0, resp
);
870 spin_lock_irqsave(&priv
->driver_lock
, flags
);
873 /* Clean up and Put current command back to cmdfreeq */
874 __lbs_cleanup_and_insert_cmd(priv
, priv
->cur_cmd
);
875 priv
->cur_cmd
= NULL
;
877 spin_unlock_irqrestore(&priv
->driver_lock
, flags
);
880 mutex_unlock(&priv
->lock
);
881 lbs_deb_leave_args(LBS_DEB_HOST
, "ret %d", ret
);
885 int lbs_process_event(struct lbs_private
*priv
)
890 lbs_deb_enter(LBS_DEB_CMD
);
892 spin_lock_irq(&priv
->driver_lock
);
893 eventcause
= priv
->eventcause
>> SBI_EVENT_CAUSE_SHIFT
;
894 spin_unlock_irq(&priv
->driver_lock
);
896 lbs_deb_cmd("event cause %d\n", eventcause
);
898 switch (eventcause
) {
899 case MACREG_INT_CODE_LINK_SENSED
:
900 lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
903 case MACREG_INT_CODE_DEAUTHENTICATED
:
904 lbs_deb_cmd("EVENT: deauthenticated\n");
905 lbs_mac_event_disconnected(priv
);
908 case MACREG_INT_CODE_DISASSOCIATED
:
909 lbs_deb_cmd("EVENT: disassociated\n");
910 lbs_mac_event_disconnected(priv
);
913 case MACREG_INT_CODE_LINK_LOST_NO_SCAN
:
914 lbs_deb_cmd("EVENT: link lost\n");
915 lbs_mac_event_disconnected(priv
);
918 case MACREG_INT_CODE_PS_SLEEP
:
919 lbs_deb_cmd("EVENT: sleep\n");
921 /* handle unexpected PS SLEEP event */
922 if (priv
->psstate
== PS_STATE_FULL_POWER
) {
924 "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
927 priv
->psstate
= PS_STATE_PRE_SLEEP
;
929 lbs_ps_confirm_sleep(priv
, (u16
) priv
->psmode
);
933 case MACREG_INT_CODE_PS_AWAKE
:
934 lbs_deb_cmd("EVENT: awake\n");
936 /* handle unexpected PS AWAKE event */
937 if (priv
->psstate
== PS_STATE_FULL_POWER
) {
939 "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
943 priv
->psstate
= PS_STATE_AWAKE
;
945 if (priv
->needtowakeup
) {
947 * wait for the command processing to finish
948 * before resuming sending
949 * priv->needtowakeup will be set to FALSE
952 lbs_deb_cmd("waking up ...\n");
953 lbs_ps_wakeup(priv
, 0);
957 case MACREG_INT_CODE_MIC_ERR_UNICAST
:
958 lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
959 handle_mic_failureevent(priv
, MACREG_INT_CODE_MIC_ERR_UNICAST
);
962 case MACREG_INT_CODE_MIC_ERR_MULTICAST
:
963 lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
964 handle_mic_failureevent(priv
, MACREG_INT_CODE_MIC_ERR_MULTICAST
);
966 case MACREG_INT_CODE_MIB_CHANGED
:
967 case MACREG_INT_CODE_INIT_DONE
:
970 case MACREG_INT_CODE_ADHOC_BCN_LOST
:
971 lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
974 case MACREG_INT_CODE_RSSI_LOW
:
975 lbs_pr_alert("EVENT: rssi low\n");
977 case MACREG_INT_CODE_SNR_LOW
:
978 lbs_pr_alert("EVENT: snr low\n");
980 case MACREG_INT_CODE_MAX_FAIL
:
981 lbs_pr_alert("EVENT: max fail\n");
983 case MACREG_INT_CODE_RSSI_HIGH
:
984 lbs_pr_alert("EVENT: rssi high\n");
986 case MACREG_INT_CODE_SNR_HIGH
:
987 lbs_pr_alert("EVENT: snr high\n");
990 case MACREG_INT_CODE_MESH_AUTO_STARTED
:
991 /* Ignore spurious autostart events if autostart is disabled */
992 if (!priv
->mesh_autostart_enabled
) {
993 lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
996 lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
997 priv
->mesh_connect_status
= LBS_CONNECTED
;
998 if (priv
->mesh_open
== 1) {
999 netif_wake_queue(priv
->mesh_dev
);
1000 netif_carrier_on(priv
->mesh_dev
);
1002 priv
->mode
= IW_MODE_ADHOC
;
1003 schedule_work(&priv
->sync_channel
);
1007 lbs_pr_alert("EVENT: unknown event id %d\n", eventcause
);
1011 spin_lock_irq(&priv
->driver_lock
);
1012 priv
->eventcause
= 0;
1013 spin_unlock_irq(&priv
->driver_lock
);
1015 lbs_deb_leave_args(LBS_DEB_CMD
, "ret %d", ret
);