2007-02-10 12:25:27 -02:00
/**
* This file contains the handling of command
* responses as well as events generated by firmware .
*/
# include <linux/delay.h>
2009-10-12 05:27:48 +00:00
# include <linux/sched.h>
2007-02-10 12:25:27 -02:00
# include <linux/if_arp.h>
# include <linux/netdevice.h>
2009-05-27 14:03:09 -04:00
# include <asm/unaligned.h>
2007-02-10 12:25:27 -02:00
# include <net/iw_handler.h>
# include "host.h"
# include "decl.h"
# include "defs.h"
# include "dev.h"
2008-04-02 16:27:10 +02:00
# include "assoc.h"
2007-02-10 12:25:27 -02:00
# include "wext.h"
/**
* @ brief This function handles disconnect event . it
* reports disconnect to upper layer , clean tx / rx packets ,
* reset link state etc .
*
2007-11-23 15:43:44 +01:00
* @ param priv A pointer to struct lbs_private structure
2007-02-10 12:25:27 -02:00
* @ return n / a
*/
2007-11-23 15:43:44 +01:00
void lbs_mac_event_disconnected ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
union iwreq_data wrqu ;
2007-12-08 20:04:36 +00:00
if ( priv - > connect_status ! = LBS_CONNECTED )
2007-02-10 12:25:27 -02:00
return ;
2007-11-28 14:05:02 +01:00
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
memset ( wrqu . ap_addr . sa_data , 0x00 , ETH_ALEN ) ;
wrqu . ap_addr . sa_family = ARPHRD_ETHER ;
/*
* Cisco AP sends EAP failure and de - auth in less than 0.5 ms .
* It causes problem in the Supplicant
*/
msleep_interruptible ( 1000 ) ;
2007-05-25 13:05:16 -04:00
wireless_send_event ( priv - > dev , SIOCGIWAP , & wrqu , NULL ) ;
2007-02-10 12:25:27 -02:00
/* report disconnect to upper layer */
2007-05-25 13:05:16 -04:00
netif_stop_queue ( priv - > dev ) ;
netif_carrier_off ( priv - > dev ) ;
2007-02-10 12:25:27 -02:00
2007-12-12 00:41:51 -05:00
/* Free Tx and Rx packets */
kfree_skb ( priv - > currenttxskb ) ;
priv - > currenttxskb = NULL ;
priv - > tx_pending_len = 0 ;
2007-02-10 12:25:27 -02:00
/* reset SNR/NF/RSSI values */
2007-12-08 20:04:36 +00:00
memset ( priv - > SNR , 0x00 , sizeof ( priv - > SNR ) ) ;
memset ( priv - > NF , 0x00 , sizeof ( priv - > NF ) ) ;
memset ( priv - > RSSI , 0x00 , sizeof ( priv - > RSSI ) ) ;
memset ( priv - > rawSNR , 0x00 , sizeof ( priv - > rawSNR ) ) ;
memset ( priv - > rawNF , 0x00 , sizeof ( priv - > rawNF ) ) ;
priv - > nextSNRNF = 0 ;
priv - > numSNRNF = 0 ;
priv - > connect_status = LBS_DISCONNECTED ;
2007-02-10 12:25:27 -02:00
2007-05-25 17:09:41 -04:00
/* Clear out associated SSID and BSSID since connection is
* no longer valid .
*/
2007-12-08 20:04:36 +00:00
memset ( & priv - > curbssparams . bssid , 0 , ETH_ALEN ) ;
memset ( & priv - > curbssparams . ssid , 0 , IW_ESSID_MAX_SIZE ) ;
priv - > curbssparams . ssid_len = 0 ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( priv - > psstate ! = PS_STATE_FULL_POWER ) {
2007-02-10 12:25:27 -02:00
/* make firmware to exit PS mode */
2007-08-02 11:54:10 -04:00
lbs_deb_cmd ( " disconnected, so exit PS mode \n " ) ;
2007-11-15 18:05:47 -05:00
lbs_ps_wakeup ( priv , 0 ) ;
2007-02-10 12:25:27 -02:00
}
2008-01-28 17:25:53 +01:00
lbs_deb_leave ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
}
/**
* @ brief This function handles MIC failure event .
*
2007-11-23 15:43:44 +01:00
* @ param priv A pointer to struct lbs_private structure
2007-02-10 12:25:27 -02:00
* @ para event the event id
* @ return n / a
*/
2007-11-23 15:43:44 +01:00
static void handle_mic_failureevent ( struct lbs_private * priv , u32 event )
2007-02-10 12:25:27 -02:00
{
char buf [ 50 ] ;
2007-08-02 11:54:10 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
memset ( buf , 0 , sizeof ( buf ) ) ;
sprintf ( buf , " %s " , " MLME-MICHAELMICFAILURE.indication " ) ;
if ( event = = MACREG_INT_CODE_MIC_ERR_UNICAST ) {
strcat ( buf , " unicast " ) ;
} else {
strcat ( buf , " multicast " ) ;
}
2007-11-15 18:05:47 -05:00
lbs_send_iwevcustom_event ( priv , buf ) ;
2007-08-02 11:54:10 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
}
2007-11-23 15:43:44 +01:00
static int lbs_ret_reg_access ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
u16 type , struct cmd_ds_command * resp )
{
2007-05-25 11:27:16 -04:00
int ret = 0 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
switch ( type ) {
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_MAC_REG_ACCESS ) :
2007-02-10 12:25:27 -02:00
{
2007-05-25 23:36:54 -04:00
struct cmd_ds_mac_reg_access * reg = & resp - > params . macreg ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
priv - > offsetvalue . offset = ( u32 ) le16_to_cpu ( reg - > offset ) ;
priv - > offsetvalue . value = le32_to_cpu ( reg - > value ) ;
2007-02-10 12:25:27 -02:00
break ;
}
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_BBP_REG_ACCESS ) :
2007-02-10 12:25:27 -02:00
{
2007-05-25 23:36:54 -04:00
struct cmd_ds_bbp_reg_access * reg = & resp - > params . bbpreg ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
priv - > offsetvalue . offset = ( u32 ) le16_to_cpu ( reg - > offset ) ;
priv - > offsetvalue . value = reg - > value ;
2007-02-10 12:25:27 -02:00
break ;
}
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_RF_REG_ACCESS ) :
2007-02-10 12:25:27 -02:00
{
2007-05-25 23:36:54 -04:00
struct cmd_ds_rf_reg_access * reg = & resp - > params . rfreg ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
priv - > offsetvalue . offset = ( u32 ) le16_to_cpu ( reg - > offset ) ;
priv - > offsetvalue . value = reg - > value ;
2007-02-10 12:25:27 -02:00
break ;
}
default :
2007-05-25 11:27:16 -04:00
ret = - 1 ;
2007-02-10 12:25:27 -02:00
}
2007-10-08 11:09:30 +02:00
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
2007-05-25 11:27:16 -04:00
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-23 15:43:44 +01:00
static int lbs_ret_802_11_rssi ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * resp )
{
struct cmd_ds_802_11_rssi_rsp * rssirsp = & resp - > params . rssirsp ;
2007-08-02 11:54:10 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
/* store the non average value */
2009-05-27 14:03:09 -04:00
priv - > SNR [ TYPE_BEACON ] [ TYPE_NOAVG ] = get_unaligned_le16 ( & rssirsp - > SNR ) ;
priv - > NF [ TYPE_BEACON ] [ TYPE_NOAVG ] = get_unaligned_le16 ( & rssirsp - > noisefloor ) ;
2007-02-10 12:25:27 -02:00
2009-05-27 14:03:09 -04:00
priv - > SNR [ TYPE_BEACON ] [ TYPE_AVG ] = get_unaligned_le16 ( & rssirsp - > avgSNR ) ;
priv - > NF [ TYPE_BEACON ] [ TYPE_AVG ] = get_unaligned_le16 ( & rssirsp - > avgnoisefloor ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
priv - > RSSI [ TYPE_BEACON ] [ TYPE_NOAVG ] =
CAL_RSSI ( priv - > SNR [ TYPE_BEACON ] [ TYPE_NOAVG ] ,
priv - > NF [ TYPE_BEACON ] [ TYPE_NOAVG ] ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
priv - > RSSI [ TYPE_BEACON ] [ TYPE_AVG ] =
CAL_RSSI ( priv - > SNR [ TYPE_BEACON ] [ TYPE_AVG ] / AVG_SCALE ,
priv - > NF [ TYPE_BEACON ] [ TYPE_AVG ] / AVG_SCALE ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:10 -04:00
lbs_deb_cmd ( " RSSI: beacon %d, avg %d \n " ,
2007-12-08 20:04:36 +00:00
priv - > RSSI [ TYPE_BEACON ] [ TYPE_NOAVG ] ,
priv - > RSSI [ TYPE_BEACON ] [ TYPE_AVG ] ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:10 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-20 17:44:28 -05:00
static int lbs_ret_802_11_bcn_ctrl ( struct lbs_private * priv ,
struct cmd_ds_command * resp )
{
struct cmd_ds_802_11_beacon_control * bcn_ctrl =
& resp - > params . bcn_ctrl ;
lbs_deb_enter ( LBS_DEB_CMD ) ;
if ( bcn_ctrl - > action = = CMD_ACT_GET ) {
2007-12-08 20:04:36 +00:00
priv - > beacon_enable = ( u8 ) le16_to_cpu ( bcn_ctrl - > beacon_enable ) ;
priv - > beacon_period = le16_to_cpu ( bcn_ctrl - > beacon_period ) ;
2007-11-20 17:44:28 -05:00
}
lbs_deb_enter ( LBS_DEB_CMD ) ;
return 0 ;
}
2007-12-10 13:36:10 -05:00
static inline int handle_cmd_response ( struct lbs_private * priv ,
2007-12-11 13:49:39 -05:00
struct cmd_header * cmd_response )
2007-02-10 12:25:27 -02:00
{
2007-12-11 13:49:39 -05:00
struct cmd_ds_command * resp = ( struct cmd_ds_command * ) cmd_response ;
2007-02-10 12:25:27 -02:00
int ret = 0 ;
unsigned long flags ;
2007-12-10 13:36:10 -05:00
uint16_t respcmd = le16_to_cpu ( resp - > command ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:10 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
switch ( respcmd ) {
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_MAC_REG_ACCESS ) :
case CMD_RET ( CMD_BBP_REG_ACCESS ) :
case CMD_RET ( CMD_RF_REG_ACCESS ) :
2007-11-15 18:05:47 -05:00
ret = lbs_ret_reg_access ( priv , respcmd , resp ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_802_11_SET_AFC ) :
case CMD_RET ( CMD_802_11_GET_AFC ) :
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-12-15 02:38:17 -05:00
memmove ( ( void * ) priv - > cur_cmd - > callback_arg , & resp - > params . afc ,
2007-02-10 12:25:27 -02:00
sizeof ( struct cmd_ds_802_11_afc ) ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_802_11_BEACON_STOP ) :
2007-06-18 12:01:12 -04:00
break ;
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_802_11_RSSI ) :
2007-11-15 18:05:47 -05:00
ret = lbs_ret_802_11_rssi ( priv , resp ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_802_11D_DOMAIN_INFO ) :
2008-03-19 14:25:58 +01:00
ret = lbs_ret_802_11d_domain_info ( resp ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_802_11_TPC_CFG ) :
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-12-15 02:38:17 -05:00
memmove ( ( void * ) priv - > cur_cmd - > callback_arg , & resp - > params . tpccfg ,
2007-02-10 12:25:27 -02:00
sizeof ( struct cmd_ds_802_11_tpc_cfg ) ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_802_11_LED_GPIO_CTRL ) :
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-12-15 02:38:17 -05:00
memmove ( ( void * ) priv - > cur_cmd - > callback_arg , & resp - > params . ledgpio ,
2007-02-10 12:25:27 -02:00
sizeof ( struct cmd_ds_802_11_led_ctrl ) ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-11-26 10:07:14 +01:00
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_GET_TSF ) :
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-12-15 02:38:17 -05:00
memcpy ( ( void * ) priv - > cur_cmd - > callback_arg ,
2007-02-10 12:25:27 -02:00
& resp - > params . gettsf . tsfvalue , sizeof ( u64 ) ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_BT_ACCESS ) :
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-12-15 02:38:17 -05:00
if ( priv - > cur_cmd - > callback_arg )
memcpy ( ( void * ) priv - > cur_cmd - > callback_arg ,
2007-02-10 12:25:27 -02:00
& resp - > params . bt . addr1 , 2 * ETH_ALEN ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_FWT_ACCESS ) :
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-12-15 02:38:17 -05:00
if ( priv - > cur_cmd - > callback_arg )
memcpy ( ( void * ) priv - > cur_cmd - > callback_arg , & resp - > params . fwt ,
2007-05-25 23:36:54 -04:00
sizeof ( resp - > params . fwt ) ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-11-20 17:44:28 -05:00
case CMD_RET ( CMD_802_11_BEACON_CTRL ) :
ret = lbs_ret_802_11_bcn_ctrl ( priv , resp ) ;
break ;
2007-02-10 12:25:27 -02:00
default :
2008-05-20 11:47:16 +01:00
lbs_pr_err ( " CMD_RESP: unknown cmd response 0x%04x \n " ,
le16_to_cpu ( resp - > command ) ) ;
2007-02-10 12:25:27 -02:00
break ;
}
2007-08-02 11:54:10 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2008-04-01 14:50:43 +02:00
int lbs_process_command_response ( struct lbs_private * priv , u8 * data , u32 len )
2007-02-10 12:25:27 -02:00
{
2007-12-11 23:42:49 -05:00
uint16_t respcmd , curcmd ;
2007-12-11 13:49:39 -05:00
struct cmd_header * resp ;
2007-02-10 12:25:27 -02:00
int ret = 0 ;
2007-12-11 23:42:49 -05:00
unsigned long flags ;
uint16_t result ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:10 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( ! priv - > cur_cmd ) {
2007-08-02 11:54:10 -04:00
lbs_deb_host ( " CMD_RESP: cur_cmd is NULL \n " ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
goto done ;
}
2007-12-11 23:42:49 -05:00
2008-04-01 14:50:43 +02:00
resp = ( void * ) data ;
2008-03-04 18:22:27 +01:00
curcmd = le16_to_cpu ( priv - > cur_cmd - > cmdbuf - > command ) ;
2007-02-10 12:25:27 -02:00
respcmd = le16_to_cpu ( resp - > command ) ;
result = le16_to_cpu ( resp - > result ) ;
2008-03-26 10:04:44 +01:00
lbs_deb_cmd ( " CMD_RESP: response 0x%04x, seq %d, size %d \n " ,
2008-04-01 14:50:43 +02:00
respcmd , le16_to_cpu ( resp - > seqnum ) , len ) ;
lbs_deb_hex ( LBS_DEB_CMD , " CMD_RESP " , ( void * ) resp , len ) ;
2007-02-10 12:25:27 -02:00
2008-03-03 12:20:12 +01:00
if ( resp - > seqnum ! = priv - > cur_cmd - > cmdbuf - > seqnum ) {
2007-12-11 23:42:49 -05:00
lbs_pr_info ( " Received CMD_RESP with invalid sequence %d (expected %d) \n " ,
2008-03-03 12:20:12 +01:00
le16_to_cpu ( resp - > seqnum ) , le16_to_cpu ( priv - > cur_cmd - > cmdbuf - > seqnum ) ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
2007-12-11 23:42:49 -05:00
if ( respcmd ! = CMD_RET ( curcmd ) & &
2008-03-06 10:30:21 +01:00
respcmd ! = CMD_RET_802_11_ASSOCIATE & & curcmd ! = CMD_802_11_ASSOCIATE ) {
2007-12-11 23:42:49 -05:00
lbs_pr_info ( " Invalid CMD_RESP %x to command %x! \n " , respcmd , curcmd ) ;
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
ret = - 1 ;
goto done ;
}
2007-12-17 15:41:30 -05:00
if ( resp - > result = = cpu_to_le16 ( 0x0004 ) ) {
/* 0x0004 means -EAGAIN. Drop the response, let it time out
and be resubmitted */
lbs_pr_info ( " Firmware returns DEFER to command %x. Will let it time out... \n " ,
le16_to_cpu ( resp - > command ) ) ;
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
ret = - 1 ;
goto done ;
}
2007-12-11 23:42:49 -05:00
/* Now we got response from FW, cancel the command timer */
del_timer ( & priv - > command_timer ) ;
2007-12-15 19:33:43 -05:00
priv - > cmd_timed_out = 0 ;
if ( priv - > nr_retries ) {
lbs_pr_info ( " Received result %x to command %x after %d retries \n " ,
result , curcmd , priv - > nr_retries ) ;
priv - > nr_retries = 0 ;
}
2007-02-10 12:25:27 -02:00
/* Store the response code to cur_cmd_retcode. */
2007-12-08 20:04:36 +00:00
priv - > cur_cmd_retcode = result ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:53:36 -04:00
if ( respcmd = = CMD_RET ( CMD_802_11_PS_MODE ) ) {
2007-12-16 23:26:54 -05:00
struct cmd_ds_802_11_ps_mode * psmode = ( void * ) & resp [ 1 ] ;
2007-05-25 23:36:54 -04:00
u16 action = le16_to_cpu ( psmode - > action ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:10 -04:00
lbs_deb_host (
" CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x \n " ,
2007-05-25 23:36:54 -04:00
result , action ) ;
2007-02-10 12:25:27 -02:00
if ( result ) {
2007-08-02 11:54:10 -04:00
lbs_deb_host ( " CMD_RESP: PS command failed with 0x%x \n " ,
2007-05-25 23:36:54 -04:00
result ) ;
/*
* We should not re - try enter - ps command in
* ad - hoc mode . It takes place in
2007-11-15 18:05:47 -05:00
* lbs_execute_next_command ( ) .
2007-05-25 23:36:54 -04:00
*/
2007-12-08 20:04:36 +00:00
if ( priv - > mode = = IW_MODE_ADHOC & &
2007-08-02 11:31:18 -04:00
action = = CMD_SUBCMD_ENTER_PS )
2007-12-08 20:04:36 +00:00
priv - > psmode = LBS802_11POWERMODECAM ;
2007-08-02 11:31:18 -04:00
} else if ( action = = CMD_SUBCMD_ENTER_PS ) {
2007-12-08 20:04:36 +00:00
priv - > needtowakeup = 0 ;
priv - > psstate = PS_STATE_AWAKE ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:10 -04:00
lbs_deb_host ( " CMD_RESP: ENTER_PS command response \n " ) ;
2007-12-08 20:04:36 +00:00
if ( priv - > connect_status ! = LBS_CONNECTED ) {
2007-02-10 12:25:27 -02:00
/*
* When Deauth Event received before Enter_PS command
* response , We need to wake up the firmware .
*/
2007-08-02 11:54:10 -04:00
lbs_deb_host (
2007-11-15 18:05:47 -05:00
" disconnected, invoking lbs_ps_wakeup \n " ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
mutex_unlock ( & priv - > lock ) ;
2007-11-15 18:05:47 -05:00
lbs_ps_wakeup ( priv , 0 ) ;
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
}
2007-08-02 11:31:18 -04:00
} else if ( action = = CMD_SUBCMD_EXIT_PS ) {
2007-12-08 20:04:36 +00:00
priv - > needtowakeup = 0 ;
priv - > psstate = PS_STATE_FULL_POWER ;
2007-08-02 11:54:10 -04:00
lbs_deb_host ( " CMD_RESP: EXIT_PS command response \n " ) ;
2007-02-10 12:25:27 -02:00
} else {
2007-08-02 11:54:10 -04:00
lbs_deb_host ( " CMD_RESP: PS action 0x%X \n " , action ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-15 01:52:54 -05:00
lbs_complete_command ( priv , priv - > cur_cmd , result ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
goto done ;
}
/* If the command is not successful, cleanup and return failure */
if ( ( result ! = 0 | | ! ( respcmd & 0x8000 ) ) ) {
2007-08-02 11:54:10 -04:00
lbs_deb_host ( " CMD_RESP: error 0x%04x in command reply 0x%04x \n " ,
result , respcmd ) ;
2007-02-10 12:25:27 -02:00
/*
* Handling errors here
*/
switch ( respcmd ) {
2007-08-02 11:53:36 -04:00
case CMD_RET ( CMD_GET_HW_SPEC ) :
case CMD_RET ( CMD_802_11_RESET ) :
2007-08-02 11:54:10 -04:00
lbs_deb_host ( " CMD_RESP: reset failed \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
}
2007-12-15 01:52:54 -05:00
lbs_complete_command ( priv , priv - > cur_cmd , result ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-12-07 15:13:05 +00:00
2007-12-11 12:33:30 -05:00
if ( priv - > cur_cmd & & priv - > cur_cmd - > callback ) {
ret = priv - > cur_cmd - > callback ( priv , priv - > cur_cmd - > callback_arg ,
2007-12-11 13:49:39 -05:00
resp ) ;
2007-12-11 12:33:30 -05:00
} else
2008-03-19 14:25:58 +01:00
ret = handle_cmd_response ( priv , resp ) ;
2007-12-07 15:13:05 +00:00
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-12-07 15:13:05 +00:00
2007-12-08 20:04:36 +00:00
if ( priv - > cur_cmd ) {
2007-02-10 12:25:27 -02:00
/* Clean up and Put current command back to cmdfreeq */
2007-12-15 01:52:54 -05:00
lbs_complete_command ( priv , priv - > cur_cmd , result ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
done :
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-08-02 11:54:10 -04:00
lbs_deb_leave_args ( LBS_DEB_HOST , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-12-17 13:26:42 -05:00
static int lbs_send_confirmwake ( struct lbs_private * priv )
{
2008-03-26 13:22:11 +01:00
struct cmd_header cmd ;
2007-12-17 13:26:42 -05:00
int ret = 0 ;
lbs_deb_enter ( LBS_DEB_HOST ) ;
2008-03-26 13:22:11 +01:00
cmd . command = cpu_to_le16 ( CMD_802_11_WAKEUP_CONFIRM ) ;
cmd . size = cpu_to_le16 ( sizeof ( cmd ) ) ;
cmd . seqnum = cpu_to_le16 ( + + priv - > seqnum ) ;
cmd . result = 0 ;
2007-12-17 13:26:42 -05:00
2008-03-26 13:22:11 +01:00
lbs_deb_hex ( LBS_DEB_HOST , " wake confirm " , ( u8 * ) & cmd ,
sizeof ( cmd ) ) ;
2007-12-17 13:26:42 -05:00
2008-03-26 13:22:11 +01:00
ret = priv - > hw_host_to_card ( priv , MVMS_CMD , ( u8 * ) & cmd , sizeof ( cmd ) ) ;
2007-12-17 13:26:42 -05:00
if ( ret )
lbs_pr_alert ( " SEND_WAKEC_CMD: Host to Card failed for Confirm Wake \n " ) ;
lbs_deb_leave_args ( LBS_DEB_HOST , " ret %d " , ret ) ;
return ret ;
}
2008-04-01 14:50:43 +02:00
int lbs_process_event ( struct lbs_private * priv , u32 event )
2007-02-10 12:25:27 -02:00
{
int ret = 0 ;
2007-08-02 13:14:07 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2008-04-01 14:50:43 +02:00
switch ( event ) {
2007-02-10 12:25:27 -02:00
case MACREG_INT_CODE_LINK_SENSED :
2008-03-19 14:25:18 +01:00
lbs_deb_cmd ( " EVENT: link sensed \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_DEAUTHENTICATED :
2007-08-02 11:54:10 -04:00
lbs_deb_cmd ( " EVENT: deauthenticated \n " ) ;
2007-11-15 18:05:47 -05:00
lbs_mac_event_disconnected ( priv ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_DISASSOCIATED :
2007-08-02 11:54:10 -04:00
lbs_deb_cmd ( " EVENT: disassociated \n " ) ;
2007-11-15 18:05:47 -05:00
lbs_mac_event_disconnected ( priv ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-11-28 09:15:11 +01:00
case MACREG_INT_CODE_LINK_LOST_NO_SCAN :
2007-08-02 11:54:10 -04:00
lbs_deb_cmd ( " EVENT: link lost \n " ) ;
2007-11-15 18:05:47 -05:00
lbs_mac_event_disconnected ( priv ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_PS_SLEEP :
2008-03-19 14:25:18 +01:00
lbs_deb_cmd ( " EVENT: ps sleep \n " ) ;
2007-02-10 12:25:27 -02:00
/* handle unexpected PS SLEEP event */
2007-12-08 20:04:36 +00:00
if ( priv - > psstate = = PS_STATE_FULL_POWER ) {
2007-05-25 11:27:16 -04:00
lbs_deb_cmd (
2007-08-02 11:54:10 -04:00
" EVENT: in FULL POWER mode, ignoreing PS_SLEEP \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
}
2007-12-08 20:04:36 +00:00
priv - > psstate = PS_STATE_PRE_SLEEP ;
2007-02-10 12:25:27 -02:00
2008-03-19 14:25:18 +01:00
lbs_ps_confirm_sleep ( priv ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-12-17 13:26:42 -05:00
case MACREG_INT_CODE_HOST_AWAKE :
2008-03-19 14:25:18 +01:00
lbs_deb_cmd ( " EVENT: host awake \n " ) ;
2009-09-30 20:04:38 -07:00
if ( priv - > reset_deep_sleep_wakeup )
priv - > reset_deep_sleep_wakeup ( priv ) ;
priv - > is_deep_sleep = 0 ;
2007-12-17 13:26:42 -05:00
lbs_send_confirmwake ( priv ) ;
break ;
2009-09-30 20:04:38 -07:00
case MACREG_INT_CODE_DEEP_SLEEP_AWAKE :
if ( priv - > reset_deep_sleep_wakeup )
priv - > reset_deep_sleep_wakeup ( priv ) ;
lbs_deb_cmd ( " EVENT: ds awake \n " ) ;
priv - > is_deep_sleep = 0 ;
priv - > wakeup_dev_required = 0 ;
wake_up_interruptible ( & priv - > ds_awake_q ) ;
break ;
2007-02-10 12:25:27 -02:00
case MACREG_INT_CODE_PS_AWAKE :
2008-03-19 14:25:18 +01:00
lbs_deb_cmd ( " EVENT: ps awake \n " ) ;
2007-02-10 12:25:27 -02:00
/* handle unexpected PS AWAKE event */
2007-12-08 20:04:36 +00:00
if ( priv - > psstate = = PS_STATE_FULL_POWER ) {
2007-05-25 11:27:16 -04:00
lbs_deb_cmd (
2007-02-10 12:25:27 -02:00
" EVENT: In FULL POWER mode - ignore PS AWAKE \n " ) ;
break ;
}
2007-12-08 20:04:36 +00:00
priv - > psstate = PS_STATE_AWAKE ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( priv - > needtowakeup ) {
2007-02-10 12:25:27 -02:00
/*
* wait for the command processing to finish
* before resuming sending
2007-12-08 20:04:36 +00:00
* priv - > needtowakeup will be set to FALSE
2007-11-15 18:05:47 -05:00
* in lbs_ps_wakeup ( )
2007-02-10 12:25:27 -02:00
*/
2007-08-02 11:54:10 -04:00
lbs_deb_cmd ( " waking up ... \n " ) ;
2007-11-15 18:05:47 -05:00
lbs_ps_wakeup ( priv , 0 ) ;
2007-02-10 12:25:27 -02:00
}
break ;
case MACREG_INT_CODE_MIC_ERR_UNICAST :
2007-05-25 11:27:16 -04:00
lbs_deb_cmd ( " EVENT: UNICAST MIC ERROR \n " ) ;
2007-02-10 12:25:27 -02:00
handle_mic_failureevent ( priv , MACREG_INT_CODE_MIC_ERR_UNICAST ) ;
break ;
case MACREG_INT_CODE_MIC_ERR_MULTICAST :
2007-05-25 11:27:16 -04:00
lbs_deb_cmd ( " EVENT: MULTICAST MIC ERROR \n " ) ;
2007-02-10 12:25:27 -02:00
handle_mic_failureevent ( priv , MACREG_INT_CODE_MIC_ERR_MULTICAST ) ;
break ;
2008-03-19 14:25:18 +01:00
2007-02-10 12:25:27 -02:00
case MACREG_INT_CODE_MIB_CHANGED :
2008-03-19 14:25:18 +01:00
lbs_deb_cmd ( " EVENT: MIB CHANGED \n " ) ;
break ;
2007-02-10 12:25:27 -02:00
case MACREG_INT_CODE_INIT_DONE :
2008-03-19 14:25:18 +01:00
lbs_deb_cmd ( " EVENT: INIT DONE \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_ADHOC_BCN_LOST :
2007-08-02 11:54:10 -04:00
lbs_deb_cmd ( " EVENT: ADHOC beacon lost \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_RSSI_LOW :
2007-08-02 11:54:10 -04:00
lbs_pr_alert ( " EVENT: rssi low \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_SNR_LOW :
2007-08-02 11:54:10 -04:00
lbs_pr_alert ( " EVENT: snr low \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_MAX_FAIL :
2007-08-02 11:54:10 -04:00
lbs_pr_alert ( " EVENT: max fail \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_RSSI_HIGH :
2007-08-02 11:54:10 -04:00
lbs_pr_alert ( " EVENT: rssi high \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
case MACREG_INT_CODE_SNR_HIGH :
2007-08-02 11:54:10 -04:00
lbs_pr_alert ( " EVENT: snr high \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-05-25 23:12:19 -04:00
case MACREG_INT_CODE_MESH_AUTO_STARTED :
2007-08-02 13:20:12 -04:00
/* Ignore spurious autostart events if autostart is disabled */
if ( ! priv - > mesh_autostart_enabled ) {
lbs_pr_info ( " EVENT: MESH_AUTO_STARTED (ignoring) \n " ) ;
break ;
}
2007-08-02 11:55:22 -04:00
lbs_pr_info ( " EVENT: MESH_AUTO_STARTED \n " ) ;
2007-12-08 20:04:36 +00:00
priv - > mesh_connect_status = LBS_CONNECTED ;
2007-12-12 00:41:51 -05:00
if ( priv - > mesh_open ) {
2007-08-02 11:55:22 -04:00
netif_carrier_on ( priv - > mesh_dev ) ;
2007-12-12 00:41:51 -05:00
if ( ! priv - > tx_pending_len )
netif_wake_queue ( priv - > mesh_dev ) ;
2007-05-25 23:12:19 -04:00
}
2007-12-08 20:04:36 +00:00
priv - > mode = IW_MODE_ADHOC ;
2007-05-30 12:14:34 -04:00
schedule_work ( & priv - > sync_channel ) ;
2007-05-25 23:12:19 -04:00
break ;
2007-02-10 12:25:27 -02:00
default :
2008-04-01 14:50:43 +02:00
lbs_pr_alert ( " EVENT: unknown event id %d \n " , event ) ;
2007-02-10 12:25:27 -02:00
break ;
}
2007-08-02 13:14:07 -04:00
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}