2007-02-10 12:25:27 -02:00
/**
* This file contains the handling of command .
* It prepares command and sends it to firmware when it is ready .
*/
# include <net/iw_handler.h>
# include "host.h"
# include "hostcmd.h"
# include "decl.h"
# include "defs.h"
# include "dev.h"
# include "join.h"
# include "wext.h"
2007-12-11 12:42:16 -05:00
# include "cmd.h"
2007-02-10 12:25:27 -02:00
static void cleanup_cmdnode ( struct cmd_ctrl_node * ptempnode ) ;
2007-12-11 17:44:10 -05:00
static struct cmd_ctrl_node * lbs_get_cmd_ctrl_node ( struct lbs_private * priv ) ;
static void lbs_set_cmd_ctrl_node ( struct lbs_private * priv ,
2007-12-05 17:58:06 +01:00
struct cmd_ctrl_node * ptempnode ,
2007-12-14 23:08:13 -05:00
void * pdata_buf ) ;
2007-12-05 17:58:06 +01:00
2007-02-10 12:25:27 -02:00
/**
2007-12-10 15:24:47 -05:00
* @ brief Checks whether a command is allowed in Power Save mode
2007-02-10 12:25:27 -02:00
*
* @ param command the command ID
2007-12-10 15:24:47 -05:00
* @ return 1 if allowed , 0 if not allowed
2007-02-10 12:25:27 -02:00
*/
2007-12-10 15:24:47 -05:00
static u8 is_command_allowed_in_ps ( u16 cmd )
2007-02-10 12:25:27 -02:00
{
2007-12-10 15:24:47 -05:00
switch ( cmd ) {
case CMD_802_11_RSSI :
return 1 ;
default :
break ;
2007-02-10 12:25:27 -02:00
}
return 0 ;
}
2007-12-11 12:42:16 -05:00
/**
* @ brief Updates the hardware details like MAC address and regulatory region
*
* @ param priv A pointer to struct lbs_private structure
*
* @ return 0 on success , error on failure
*/
int lbs_update_hw_spec ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
2007-12-11 12:42:16 -05:00
struct cmd_ds_get_hw_spec cmd ;
int ret = - 1 ;
u32 i ;
DECLARE_MAC_BUF ( mac ) ;
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
2007-12-11 12:42:16 -05:00
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
cmd . hdr . size = cpu_to_le16 ( sizeof ( cmd ) ) ;
memcpy ( cmd . permanentaddr , priv - > current_addr , ETH_ALEN ) ;
2007-12-12 16:00:42 -05:00
ret = lbs_cmd_with_response ( priv , CMD_GET_HW_SPEC , & cmd ) ;
2007-12-11 12:42:16 -05:00
if ( ret )
goto out ;
priv - > fwcapinfo = le32_to_cpu ( cmd . fwcapinfo ) ;
memcpy ( priv - > fwreleasenumber , cmd . fwreleasenumber , 4 ) ;
lbs_deb_cmd ( " GET_HW_SPEC: firmware release %u.%u.%up%u \n " ,
priv - > fwreleasenumber [ 2 ] , priv - > fwreleasenumber [ 1 ] ,
priv - > fwreleasenumber [ 0 ] , priv - > fwreleasenumber [ 3 ] ) ;
lbs_deb_cmd ( " GET_HW_SPEC: MAC addr %s \n " ,
print_mac ( mac , cmd . permanentaddr ) ) ;
lbs_deb_cmd ( " GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x \n " ,
cmd . hwifversion , cmd . version ) ;
/* Clamp region code to 8-bit since FW spec indicates that it should
* only ever be 8 - bit , even though the field size is 16 - bit . Some firmware
* returns non - zero high 8 bits here .
*/
priv - > regioncode = le16_to_cpu ( cmd . regioncode ) & 0xFF ;
for ( i = 0 ; i < MRVDRV_MAX_REGION_CODE ; i + + ) {
/* use the region code to search for the index */
if ( priv - > regioncode = = lbs_region_code_to_index [ i ] )
break ;
}
/* if it's unidentified region code, use the default (USA) */
if ( i > = MRVDRV_MAX_REGION_CODE ) {
priv - > regioncode = 0x10 ;
lbs_pr_info ( " unidentified region code; using the default (USA) \n " ) ;
}
if ( priv - > current_addr [ 0 ] = = 0xff )
memmove ( priv - > current_addr , cmd . permanentaddr , ETH_ALEN ) ;
2007-02-10 12:25:27 -02:00
2007-12-11 12:42:16 -05:00
memcpy ( priv - > dev - > dev_addr , priv - > current_addr , ETH_ALEN ) ;
if ( priv - > mesh_dev )
memcpy ( priv - > mesh_dev - > dev_addr , priv - > current_addr , ETH_ALEN ) ;
if ( lbs_set_regiontable ( priv , priv - > regioncode , 0 ) ) {
ret = - 1 ;
goto out ;
}
if ( lbs_set_universaltable ( priv , 0 ) ) {
ret = - 1 ;
goto out ;
}
out :
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-12-11 12:42:16 -05:00
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-12-12 20:06:06 -05:00
int lbs_host_sleep_cfg ( struct lbs_private * priv , uint32_t criteria )
2007-12-12 15:19:29 -05:00
{
struct cmd_ds_host_sleep cmd_config ;
int ret ;
cmd_config . criteria = cpu_to_le32 ( criteria ) ;
2007-12-12 20:06:06 -05:00
cmd_config . gpio = priv - > wol_gpio ;
cmd_config . gap = priv - > wol_gap ;
2007-12-12 15:19:29 -05:00
2007-12-12 16:00:42 -05:00
ret = lbs_cmd_with_response ( priv , CMD_802_11_HOST_SLEEP_CFG , & cmd_config ) ;
2007-12-12 20:06:06 -05:00
if ( ! ret ) {
lbs_deb_cmd ( " Set WOL criteria to %x \n " , criteria ) ;
priv - > wol_criteria = criteria ;
} else {
2007-12-12 15:19:29 -05:00
lbs_pr_info ( " HOST_SLEEP_CFG failed %d \n " , ret ) ;
}
2007-12-12 20:06:06 -05:00
2007-12-12 15:19:29 -05:00
return ret ;
}
EXPORT_SYMBOL_GPL ( lbs_host_sleep_cfg ) ;
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_ps_mode ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action )
{
struct cmd_ds_802_11_ps_mode * psm = & cmd - > params . psmode ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_PS_MODE ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_ps_mode ) +
S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
psm - > action = cpu_to_le16 ( cmd_action ) ;
psm - > multipledtim = 0 ;
2007-05-25 23:36:54 -04:00
switch ( cmd_action ) {
2007-08-02 11:31:18 -04:00
case CMD_SUBCMD_ENTER_PS :
2007-05-25 11:27:16 -04:00
lbs_deb_cmd ( " PS command: " " SubCode- Enter PS \n " ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 13:09:34 -04:00
psm - > locallisteninterval = 0 ;
2007-08-02 13:09:15 -04:00
psm - > nullpktinterval = 0 ;
2007-02-10 12:25:27 -02:00
psm - > multipledtim =
2007-08-02 13:09:49 -04:00
cpu_to_le16 ( MRVDRV_DEFAULT_MULTIPLE_DTIM ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_SUBCMD_EXIT_PS :
2007-05-25 11:27:16 -04:00
lbs_deb_cmd ( " PS command: " " SubCode- Exit PS \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_SUBCMD_SLEEP_CONFIRMED :
2007-05-25 11:27:16 -04:00
lbs_deb_cmd ( " PS command: SubCode- sleep confirm \n " ) ;
2007-02-10 12:25:27 -02:00
break ;
default :
break ;
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_inactivity_timeout ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action , void * pdata_buf )
{
u16 * timeout = pdata_buf ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_INACTIVITY_TIMEOUT ) ;
2007-02-10 12:25:27 -02:00
cmd - > size =
cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_inactivity_timeout )
+ S_DS_GEN ) ;
cmd - > params . inactivity_timeout . action = cpu_to_le16 ( cmd_action ) ;
if ( cmd_action )
2007-05-25 23:36:54 -04:00
cmd - > params . inactivity_timeout . timeout = cpu_to_le16 ( * timeout ) ;
2007-02-10 12:25:27 -02:00
else
cmd - > params . inactivity_timeout . timeout = 0 ;
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_sleep_params ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action )
{
struct cmd_ds_802_11_sleep_params * sp = & cmd - > params . sleep_params ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( ( sizeof ( struct cmd_ds_802_11_sleep_params ) ) +
S_DS_GEN ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_SLEEP_PARAMS ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
if ( cmd_action = = CMD_ACT_GET ) {
2007-12-08 20:04:36 +00:00
memset ( & priv - > sp , 0 , sizeof ( struct sleep_params ) ) ;
2007-02-10 12:25:27 -02:00
memset ( sp , 0 , sizeof ( struct cmd_ds_802_11_sleep_params ) ) ;
sp - > action = cpu_to_le16 ( cmd_action ) ;
2007-08-02 11:31:18 -04:00
} else if ( cmd_action = = CMD_ACT_SET ) {
2007-02-10 12:25:27 -02:00
sp - > action = cpu_to_le16 ( cmd_action ) ;
2007-12-08 20:04:36 +00:00
sp - > error = cpu_to_le16 ( priv - > sp . sp_error ) ;
sp - > offset = cpu_to_le16 ( priv - > sp . sp_offset ) ;
sp - > stabletime = cpu_to_le16 ( priv - > sp . sp_stabletime ) ;
sp - > calcontrol = ( u8 ) priv - > sp . sp_calcontrol ;
sp - > externalsleepclk = ( u8 ) priv - > sp . sp_extsleepclk ;
sp - > reserved = cpu_to_le16 ( priv - > sp . sp_reserved ) ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_set_wep ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u32 cmd_act ,
void * pdata_buf )
{
struct cmd_ds_802_11_set_wep * wep = & cmd - > params . wep ;
int ret = 0 ;
struct assoc_request * assoc_req = pdata_buf ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_SET_WEP ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( * wep ) + S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
if ( cmd_act = = CMD_ACT_ADD ) {
2007-02-10 12:25:27 -02:00
int i ;
if ( ! assoc_req ) {
2007-12-12 00:14:21 -05:00
lbs_deb_cmd ( " Invalid association request! \n " ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
2007-08-02 11:31:18 -04:00
wep - > action = cpu_to_le16 ( CMD_ACT_ADD ) ;
2007-02-10 12:25:27 -02:00
/* default tx key index */
2007-05-25 23:36:54 -04:00
wep - > keyindex = cpu_to_le16 ( ( u16 ) ( assoc_req - > wep_tx_keyidx &
2007-08-02 11:31:18 -04:00
( u32 ) CMD_WEP_KEY_INDEX_MASK ) ) ;
2007-02-10 12:25:27 -02:00
/* Copy key types and material to host command structure */
for ( i = 0 ; i < 4 ; i + + ) {
2007-08-02 10:45:55 -04:00
struct enc_key * pkey = & assoc_req - > wep_keys [ i ] ;
2007-02-10 12:25:27 -02:00
switch ( pkey - > len ) {
case KEY_LEN_WEP_40 :
2007-10-08 11:07:27 +02:00
wep - > keytype [ i ] = CMD_TYPE_WEP_40_BIT ;
2007-02-10 12:25:27 -02:00
memmove ( & wep - > keymaterial [ i ] , pkey - > key ,
pkey - > len ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " SET_WEP: add key %d (40 bit) \n " , i ) ;
2007-02-10 12:25:27 -02:00
break ;
case KEY_LEN_WEP_104 :
2007-10-08 11:07:27 +02:00
wep - > keytype [ i ] = CMD_TYPE_WEP_104_BIT ;
2007-02-10 12:25:27 -02:00
memmove ( & wep - > keymaterial [ i ] , pkey - > key ,
pkey - > len ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " SET_WEP: add key %d (104 bit) \n " , i ) ;
2007-02-10 12:25:27 -02:00
break ;
case 0 :
break ;
default :
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " SET_WEP: invalid key %d, length %d \n " ,
2007-02-10 12:25:27 -02:00
i , pkey - > len ) ;
ret = - 1 ;
goto done ;
break ;
}
}
2007-08-02 11:31:18 -04:00
} else if ( cmd_act = = CMD_ACT_REMOVE ) {
2007-02-10 12:25:27 -02:00
/* ACT_REMOVE clears _all_ WEP keys */
2007-08-02 11:31:18 -04:00
wep - > action = cpu_to_le16 ( CMD_ACT_REMOVE ) ;
2007-02-10 12:25:27 -02:00
/* default tx key index */
2007-12-08 20:04:36 +00:00
wep - > keyindex = cpu_to_le16 ( ( u16 ) ( priv - > wep_tx_keyidx &
2007-08-02 11:31:18 -04:00
( u32 ) CMD_WEP_KEY_INDEX_MASK ) ) ;
2007-12-08 20:04:36 +00:00
lbs_deb_cmd ( " SET_WEP: remove key %d \n " , priv - > wep_tx_keyidx ) ;
2007-02-10 12:25:27 -02:00
}
ret = 0 ;
done :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_enable_rsn ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
2007-05-25 23:01:24 -04:00
u16 cmd_action ,
void * pdata_buf )
2007-02-10 12:25:27 -02:00
{
struct cmd_ds_802_11_enable_rsn * penableRSN = & cmd - > params . enbrsn ;
2007-06-18 12:01:12 -04:00
u32 * enable = pdata_buf ;
2007-05-25 23:01:24 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_ENABLE_RSN ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( * penableRSN ) + S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
penableRSN - > action = cpu_to_le16 ( cmd_action ) ;
2007-06-18 12:01:12 -04:00
2007-08-02 11:31:18 -04:00
if ( cmd_action = = CMD_ACT_SET ) {
2007-06-18 12:01:12 -04:00
if ( * enable )
2007-08-02 11:31:18 -04:00
penableRSN - > enable = cpu_to_le16 ( CMD_ENABLE_RSN ) ;
2007-06-18 12:01:12 -04:00
else
2007-08-02 11:31:18 -04:00
penableRSN - > enable = cpu_to_le16 ( CMD_DISABLE_RSN ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " ENABLE_RSN: %d \n " , * enable ) ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 23:01:24 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-26 10:07:14 +01:00
static ssize_t lbs_tlv_size ( const u8 * tlv , u16 size )
{
ssize_t pos = 0 ;
struct mrvlietypesheader * tlv_h ;
while ( pos < size ) {
u16 length ;
tlv_h = ( struct mrvlietypesheader * ) tlv ;
if ( tlv_h - > len = = 0 )
return pos ;
length = le16_to_cpu ( tlv_h - > len ) +
sizeof ( struct mrvlietypesheader ) ;
pos + = length ;
tlv + = length ;
}
return pos ;
}
static void lbs_cmd_802_11_subscribe_event ( struct lbs_private * priv ,
struct cmd_ds_command * cmd , u16 cmd_action ,
void * pdata_buf )
{
struct cmd_ds_802_11_subscribe_event * events =
( struct cmd_ds_802_11_subscribe_event * ) pdata_buf ;
/* pdata_buf points to a struct cmd_ds_802_11_subscribe_event and room
* for various Marvell TLVs */
lbs_deb_enter ( LBS_DEB_CMD ) ;
cmd - > size = cpu_to_le16 ( sizeof ( * events )
- sizeof ( events - > tlv )
+ S_DS_GEN ) ;
cmd - > params . subscribe_event . action = cpu_to_le16 ( cmd_action ) ;
if ( cmd_action = = CMD_ACT_GET ) {
cmd - > params . subscribe_event . events = 0 ;
} else {
ssize_t sz = lbs_tlv_size ( events - > tlv , sizeof ( events - > tlv ) ) ;
cmd - > size = cpu_to_le16 ( le16_to_cpu ( cmd - > size ) + sz ) ;
cmd - > params . subscribe_event . events = events - > events ;
memcpy ( cmd - > params . subscribe_event . tlv , events - > tlv , sz ) ;
}
lbs_deb_leave ( LBS_DEB_CMD ) ;
}
2007-02-10 12:25:27 -02:00
static void set_one_wpa_key ( struct MrvlIEtype_keyParamSet * pkeyparamset ,
2007-08-02 10:45:55 -04:00
struct enc_key * pkey )
2007-02-10 12:25:27 -02:00
{
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
if ( pkey - > flags & KEY_INFO_WPA_ENABLED ) {
2007-05-25 23:01:24 -04:00
pkeyparamset - > keyinfo | = cpu_to_le16 ( KEY_INFO_WPA_ENABLED ) ;
2007-02-10 12:25:27 -02:00
}
if ( pkey - > flags & KEY_INFO_WPA_UNICAST ) {
pkeyparamset - > keyinfo | = cpu_to_le16 ( KEY_INFO_WPA_UNICAST ) ;
2007-05-25 23:01:24 -04:00
}
if ( pkey - > flags & KEY_INFO_WPA_MCAST ) {
2007-02-10 12:25:27 -02:00
pkeyparamset - > keyinfo | = cpu_to_le16 ( KEY_INFO_WPA_MCAST ) ;
}
pkeyparamset - > type = cpu_to_le16 ( TLV_TYPE_KEY_MATERIAL ) ;
2007-08-02 10:45:55 -04:00
pkeyparamset - > keytypeid = cpu_to_le16 ( pkey - > type ) ;
2007-02-10 12:25:27 -02:00
pkeyparamset - > keylen = cpu_to_le16 ( pkey - > len ) ;
memcpy ( pkeyparamset - > key , pkey - > key , pkey - > len ) ;
pkeyparamset - > length = cpu_to_le16 ( sizeof ( pkeyparamset - > keytypeid )
+ sizeof ( pkeyparamset - > keyinfo )
+ sizeof ( pkeyparamset - > keylen )
+ sizeof ( pkeyparamset - > key ) ) ;
2007-08-02 11:54:31 -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_cmd_802_11_key_material ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action ,
u32 cmd_oid , void * pdata_buf )
{
struct cmd_ds_802_11_key_material * pkeymaterial =
& cmd - > params . keymaterial ;
2007-05-25 23:01:24 -04:00
struct assoc_request * assoc_req = pdata_buf ;
2007-02-10 12:25:27 -02:00
int ret = 0 ;
int index = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_KEY_MATERIAL ) ;
2007-02-10 12:25:27 -02:00
pkeymaterial - > action = cpu_to_le16 ( cmd_action ) ;
2007-08-02 11:31:18 -04:00
if ( cmd_action = = CMD_ACT_GET ) {
2007-05-25 23:01:24 -04:00
cmd - > size = cpu_to_le16 ( S_DS_GEN + sizeof ( pkeymaterial - > action ) ) ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
goto done ;
}
memset ( & pkeymaterial - > keyParamSet , 0 , sizeof ( pkeymaterial - > keyParamSet ) ) ;
2007-05-25 23:01:24 -04:00
if ( test_bit ( ASSOC_FLAG_WPA_UCAST_KEY , & assoc_req - > flags ) ) {
2007-02-10 12:25:27 -02:00
set_one_wpa_key ( & pkeymaterial - > keyParamSet [ index ] ,
2007-05-25 23:01:24 -04:00
& assoc_req - > wpa_unicast_key ) ;
2007-02-10 12:25:27 -02:00
index + + ;
}
2007-05-25 23:01:24 -04:00
if ( test_bit ( ASSOC_FLAG_WPA_MCAST_KEY , & assoc_req - > flags ) ) {
2007-02-10 12:25:27 -02:00
set_one_wpa_key ( & pkeymaterial - > keyParamSet [ index ] ,
2007-05-25 23:01:24 -04:00
& assoc_req - > wpa_mcast_key ) ;
2007-02-10 12:25:27 -02:00
index + + ;
}
cmd - > size = cpu_to_le16 ( S_DS_GEN
2007-05-25 23:01:24 -04:00
+ sizeof ( pkeymaterial - > action )
+ ( index * sizeof ( struct MrvlIEtype_keyParamSet ) ) ) ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
done :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_reset ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd , int cmd_action )
{
struct cmd_ds_802_11_reset * reset = & cmd - > params . reset ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_RESET ) ;
2007-02-10 12:25:27 -02:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_reset ) + S_DS_GEN ) ;
reset - > action = cpu_to_le16 ( cmd_action ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_get_log ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd )
{
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_GET_LOG ) ;
2007-02-10 12:25:27 -02:00
cmd - > size =
cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_get_log ) + S_DS_GEN ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_get_stat ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd )
{
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_GET_STAT ) ;
2007-02-10 12:25:27 -02:00
cmd - > size =
2007-05-25 23:36:54 -04:00
cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_get_stat ) + S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_snmp_mib ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
int cmd_action ,
int cmd_oid , void * pdata_buf )
{
struct cmd_ds_802_11_snmp_mib * pSNMPMIB = & cmd - > params . smib ;
u8 ucTemp ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_cmd ( " SNMP_CMD: cmd_oid = 0x%x \n " , cmd_oid ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_SNMP_MIB ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( * pSNMPMIB ) + S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
switch ( cmd_oid ) {
case OID_802_11_INFRASTRUCTURE_MODE :
{
2007-05-10 22:58:02 -04:00
u8 mode = ( u8 ) ( size_t ) pdata_buf ;
2007-08-02 11:31:18 -04:00
pSNMPMIB - > querytype = cpu_to_le16 ( CMD_ACT_SET ) ;
pSNMPMIB - > oid = cpu_to_le16 ( ( u16 ) DESIRED_BSSTYPE_I ) ;
2007-12-07 15:30:44 +00:00
pSNMPMIB - > bufsize = cpu_to_le16 ( sizeof ( u8 ) ) ;
2007-05-10 22:58:02 -04:00
if ( mode = = IW_MODE_ADHOC ) {
2007-02-10 12:25:27 -02:00
ucTemp = SNMP_MIB_VALUE_ADHOC ;
2007-05-10 22:58:02 -04:00
} else {
/* Infra and Auto modes */
ucTemp = SNMP_MIB_VALUE_INFRA ;
}
2007-02-10 12:25:27 -02:00
memmove ( pSNMPMIB - > value , & ucTemp , sizeof ( u8 ) ) ;
break ;
}
case OID_802_11D_ENABLE :
{
u32 ulTemp ;
2007-08-02 11:31:18 -04:00
pSNMPMIB - > oid = cpu_to_le16 ( ( u16 ) DOT11D_I ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
if ( cmd_action = = CMD_ACT_SET ) {
2007-12-07 15:30:44 +00:00
pSNMPMIB - > querytype = cpu_to_le16 ( CMD_ACT_SET ) ;
pSNMPMIB - > bufsize = cpu_to_le16 ( sizeof ( u16 ) ) ;
2007-02-10 12:25:27 -02:00
ulTemp = * ( u32 * ) pdata_buf ;
2007-05-25 23:36:54 -04:00
* ( ( __le16 * ) ( pSNMPMIB - > value ) ) =
2007-02-10 12:25:27 -02:00
cpu_to_le16 ( ( u16 ) ulTemp ) ;
}
break ;
}
case OID_802_11_FRAGMENTATION_THRESHOLD :
{
u32 ulTemp ;
2007-08-02 11:31:18 -04:00
pSNMPMIB - > oid = cpu_to_le16 ( ( u16 ) FRAGTHRESH_I ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
if ( cmd_action = = CMD_ACT_GET ) {
pSNMPMIB - > querytype = cpu_to_le16 ( CMD_ACT_GET ) ;
} else if ( cmd_action = = CMD_ACT_SET ) {
pSNMPMIB - > querytype = cpu_to_le16 ( CMD_ACT_SET ) ;
2007-05-25 23:36:54 -04:00
pSNMPMIB - > bufsize = cpu_to_le16 ( sizeof ( u16 ) ) ;
2007-02-10 12:25:27 -02:00
ulTemp = * ( ( u32 * ) pdata_buf ) ;
2007-05-25 23:36:54 -04:00
* ( ( __le16 * ) ( pSNMPMIB - > value ) ) =
2007-02-10 12:25:27 -02:00
cpu_to_le16 ( ( u16 ) ulTemp ) ;
}
break ;
}
case OID_802_11_RTS_THRESHOLD :
{
u32 ulTemp ;
2007-12-07 15:30:44 +00:00
pSNMPMIB - > oid = cpu_to_le16 ( RTSTHRESH_I ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
if ( cmd_action = = CMD_ACT_GET ) {
pSNMPMIB - > querytype = cpu_to_le16 ( CMD_ACT_GET ) ;
} else if ( cmd_action = = CMD_ACT_SET ) {
pSNMPMIB - > querytype = cpu_to_le16 ( CMD_ACT_SET ) ;
2007-05-25 23:36:54 -04:00
pSNMPMIB - > bufsize = cpu_to_le16 ( sizeof ( u16 ) ) ;
ulTemp = * ( ( u32 * ) pdata_buf ) ;
* ( __le16 * ) ( pSNMPMIB - > value ) =
2007-02-10 12:25:27 -02:00
cpu_to_le16 ( ( u16 ) ulTemp ) ;
}
break ;
}
case OID_802_11_TX_RETRYCOUNT :
2007-08-02 11:31:18 -04:00
pSNMPMIB - > oid = cpu_to_le16 ( ( u16 ) SHORT_RETRYLIM_I ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
if ( cmd_action = = CMD_ACT_GET ) {
pSNMPMIB - > querytype = cpu_to_le16 ( CMD_ACT_GET ) ;
} else if ( cmd_action = = CMD_ACT_SET ) {
pSNMPMIB - > querytype = cpu_to_le16 ( CMD_ACT_SET ) ;
2007-02-10 12:25:27 -02:00
pSNMPMIB - > bufsize = cpu_to_le16 ( sizeof ( u16 ) ) ;
2007-05-25 23:36:54 -04:00
* ( ( __le16 * ) ( pSNMPMIB - > value ) ) =
2007-12-08 20:04:36 +00:00
cpu_to_le16 ( ( u16 ) priv - > txretrycount ) ;
2007-02-10 12:25:27 -02:00
}
break ;
default :
break ;
}
2007-05-25 11:27:16 -04:00
lbs_deb_cmd (
2007-02-10 12:25:27 -02:00
" SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x \n " ,
2007-05-25 23:36:54 -04:00
le16_to_cpu ( cmd - > command ) , le16_to_cpu ( cmd - > size ) ,
le16_to_cpu ( cmd - > seqnum ) , le16_to_cpu ( cmd - > result ) ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_cmd (
2007-08-02 11:54:31 -04:00
" SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x \n " ,
2007-05-25 23:36:54 -04:00
le16_to_cpu ( pSNMPMIB - > querytype ) , le16_to_cpu ( pSNMPMIB - > oid ) ,
le16_to_cpu ( pSNMPMIB - > bufsize ) ,
le16_to_cpu ( * ( __le16 * ) pSNMPMIB - > value ) ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_radio_control ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
int cmd_action )
{
2007-05-25 23:36:54 -04:00
struct cmd_ds_802_11_radio_control * pradiocontrol = & cmd - > params . radio ;
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
cmd - > size =
cpu_to_le16 ( ( sizeof ( struct cmd_ds_802_11_radio_control ) ) +
S_DS_GEN ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_RADIO_CONTROL ) ;
2007-02-10 12:25:27 -02:00
pradiocontrol - > action = cpu_to_le16 ( cmd_action ) ;
2007-12-08 20:04:36 +00:00
switch ( priv - > preamble ) {
2007-08-02 11:31:18 -04:00
case CMD_TYPE_SHORT_PREAMBLE :
2007-02-10 12:25:27 -02:00
pradiocontrol - > control = cpu_to_le16 ( SET_SHORT_PREAMBLE ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_TYPE_LONG_PREAMBLE :
2007-02-10 12:25:27 -02:00
pradiocontrol - > control = cpu_to_le16 ( SET_LONG_PREAMBLE ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_TYPE_AUTO_PREAMBLE :
2007-02-10 12:25:27 -02:00
default :
pradiocontrol - > control = cpu_to_le16 ( SET_AUTO_PREAMBLE ) ;
break ;
}
2007-12-08 20:04:36 +00:00
if ( priv - > radioon )
2007-02-10 12:25:27 -02:00
pradiocontrol - > control | = cpu_to_le16 ( TURN_ON_RF ) ;
else
pradiocontrol - > control & = cpu_to_le16 ( ~ TURN_ON_RF ) ;
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_rf_tx_power ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action , void * pdata_buf )
{
struct cmd_ds_802_11_rf_tx_power * prtp = & cmd - > params . txp ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
cmd - > size =
2007-05-25 23:36:54 -04:00
cpu_to_le16 ( ( sizeof ( struct cmd_ds_802_11_rf_tx_power ) ) + S_DS_GEN ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_RF_TX_POWER ) ;
2007-05-25 23:36:54 -04:00
prtp - > action = cpu_to_le16 ( cmd_action ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 23:36:54 -04:00
lbs_deb_cmd ( " RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d \n " ,
le16_to_cpu ( cmd - > size ) , le16_to_cpu ( cmd - > command ) ,
le16_to_cpu ( prtp - > action ) ) ;
2007-02-10 12:25:27 -02:00
switch ( cmd_action ) {
2007-08-02 11:31:18 -04:00
case CMD_ACT_TX_POWER_OPT_GET :
prtp - > action = cpu_to_le16 ( CMD_ACT_GET ) ;
2007-02-10 12:25:27 -02:00
prtp - > currentlevel = 0 ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_ACT_TX_POWER_OPT_SET_HIGH :
prtp - > action = cpu_to_le16 ( CMD_ACT_SET ) ;
prtp - > currentlevel = cpu_to_le16 ( CMD_ACT_TX_POWER_INDEX_HIGH ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_ACT_TX_POWER_OPT_SET_MID :
prtp - > action = cpu_to_le16 ( CMD_ACT_SET ) ;
prtp - > currentlevel = cpu_to_le16 ( CMD_ACT_TX_POWER_INDEX_MID ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_ACT_TX_POWER_OPT_SET_LOW :
prtp - > action = cpu_to_le16 ( CMD_ACT_SET ) ;
2007-02-10 12:25:27 -02:00
prtp - > currentlevel = cpu_to_le16 ( * ( ( u16 * ) pdata_buf ) ) ;
break ;
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_monitor_mode ( struct lbs_private * priv ,
2007-08-02 13:16:55 -04:00
struct cmd_ds_command * cmd ,
u16 cmd_action , void * pdata_buf )
{
struct cmd_ds_802_11_monitor_mode * monitor = & cmd - > params . monitor ;
cmd - > command = cpu_to_le16 ( CMD_802_11_MONITOR_MODE ) ;
cmd - > size =
cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_monitor_mode ) +
S_DS_GEN ) ;
monitor - > action = cpu_to_le16 ( cmd_action ) ;
if ( cmd_action = = CMD_ACT_SET ) {
monitor - > mode =
cpu_to_le16 ( ( u16 ) ( * ( u32 * ) pdata_buf ) ) ;
}
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_rate_adapt_rateset ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action )
{
struct cmd_ds_802_11_rate_adapt_rateset
* rateadapt = & cmd - > params . rateset ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
cmd - > size =
cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_rate_adapt_rateset )
+ S_DS_GEN ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_RATE_ADAPT_RATESET ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 23:36:54 -04:00
rateadapt - > action = cpu_to_le16 ( cmd_action ) ;
2007-12-08 20:04:36 +00:00
rateadapt - > enablehwauto = cpu_to_le16 ( priv - > enablehwauto ) ;
rateadapt - > bitmap = cpu_to_le16 ( priv - > ratebitmap ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-12-11 15:50:59 -05:00
/**
* @ brief Get the current data rate
*
* @ param priv A pointer to struct lbs_private structure
*
* @ return The data rate on success , error on failure
*/
int lbs_get_data_rate ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
2007-12-11 15:50:59 -05:00
struct cmd_ds_802_11_data_rate cmd ;
int ret = - 1 ;
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
2007-12-11 15:50:59 -05:00
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
cmd . hdr . size = cpu_to_le16 ( sizeof ( cmd ) ) ;
cmd . action = cpu_to_le16 ( CMD_ACT_GET_TX_RATE ) ;
2007-12-12 16:00:42 -05:00
ret = lbs_cmd_with_response ( priv , CMD_802_11_DATA_RATE , & cmd ) ;
2007-12-11 15:50:59 -05:00
if ( ret )
goto out ;
lbs_deb_hex ( LBS_DEB_CMD , " DATA_RATE_RESP " , ( u8 * ) & cmd , sizeof ( cmd ) ) ;
ret = ( int ) lbs_fw_index_to_data_rate ( cmd . rates [ 0 ] ) ;
lbs_deb_cmd ( " DATA_RATE: current rate 0x%02x \n " , ret ) ;
out :
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
return ret ;
}
/**
* @ brief Set the data rate
*
* @ param priv A pointer to struct lbs_private structure
* @ param rate The desired data rate , or 0 to clear a locked rate
*
* @ return 0 on success , error on failure
*/
int lbs_set_data_rate ( struct lbs_private * priv , u8 rate )
{
struct cmd_ds_802_11_data_rate cmd ;
int ret = 0 ;
lbs_deb_enter ( LBS_DEB_CMD ) ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
cmd . hdr . size = cpu_to_le16 ( sizeof ( cmd ) ) ;
if ( rate > 0 ) {
cmd . action = cpu_to_le16 ( CMD_ACT_SET_TX_FIX_RATE ) ;
cmd . rates [ 0 ] = lbs_data_rate_to_fw_index ( rate ) ;
if ( cmd . rates [ 0 ] = = 0 ) {
lbs_deb_cmd ( " DATA_RATE: invalid requested rate of "
" 0x%02X \n " , rate ) ;
ret = 0 ;
goto out ;
}
lbs_deb_cmd ( " DATA_RATE: set fixed 0x%02X \n " , cmd . rates [ 0 ] ) ;
} else {
cmd . action = cpu_to_le16 ( CMD_ACT_SET_TX_AUTO ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " DATA_RATE: setting auto \n " ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-12 16:00:42 -05:00
ret = lbs_cmd_with_response ( priv , CMD_802_11_DATA_RATE , & cmd ) ;
2007-12-11 15:50:59 -05:00
if ( ret )
goto out ;
lbs_deb_hex ( LBS_DEB_CMD , " DATA_RATE_RESP " , ( u8 * ) & cmd , sizeof ( cmd ) ) ;
/* FIXME: get actual rates FW can do if this command actually returns
* all data rates supported .
*/
priv - > cur_rate = lbs_fw_index_to_data_rate ( cmd . rates [ 0 ] ) ;
lbs_deb_cmd ( " DATA_RATE: current rate is 0x%02x \n " , priv - > cur_rate ) ;
out :
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_mac_multicast_adr ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action )
{
struct cmd_ds_mac_multicast_adr * pMCastAdr = & cmd - > params . madr ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_mac_multicast_adr ) +
2007-02-10 12:25:27 -02:00
S_DS_GEN ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_MAC_MULTICAST_ADR ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " MULTICAST_ADR: setting %d addresses \n " , pMCastAdr - > nr_of_adrs ) ;
2007-02-10 12:25:27 -02:00
pMCastAdr - > action = cpu_to_le16 ( cmd_action ) ;
pMCastAdr - > nr_of_adrs =
2007-12-08 20:04:36 +00:00
cpu_to_le16 ( ( u16 ) priv - > nr_of_multicastmacaddr ) ;
memcpy ( pMCastAdr - > maclist , priv - > multicastlist ,
priv - > nr_of_multicastmacaddr * ETH_ALEN ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-12-11 16:54:15 -05:00
/**
* @ brief Get the radio channel
*
* @ param priv A pointer to struct lbs_private structure
*
* @ return The channel on success , error on failure
*/
int lbs_get_channel ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
2007-12-11 16:54:15 -05:00
struct cmd_ds_802_11_rf_channel cmd ;
int ret = 0 ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-12-11 16:54:15 -05:00
cmd . hdr . size = cpu_to_le16 ( sizeof ( cmd ) ) ;
cmd . action = cpu_to_le16 ( CMD_OPT_802_11_RF_CHANNEL_GET ) ;
2007-02-10 12:25:27 -02:00
2007-12-12 16:00:42 -05:00
ret = lbs_cmd_with_response ( priv , CMD_802_11_RF_CHANNEL , & cmd ) ;
2007-12-11 16:54:15 -05:00
if ( ret )
goto out ;
2007-02-10 12:25:27 -02:00
2007-12-11 17:35:51 -05:00
ret = le16_to_cpu ( cmd . channel ) ;
lbs_deb_cmd ( " current radio channel is %d \n " , ret ) ;
2007-12-11 16:54:15 -05:00
out :
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
return ret ;
}
/**
* @ brief Set the radio channel
*
* @ param priv A pointer to struct lbs_private structure
* @ param channel The desired channel , or 0 to clear a locked channel
*
* @ return 0 on success , error on failure
*/
int lbs_set_channel ( struct lbs_private * priv , u8 channel )
{
struct cmd_ds_802_11_rf_channel cmd ;
u8 old_channel = priv - > curbssparams . channel ;
int ret = 0 ;
lbs_deb_enter ( LBS_DEB_CMD ) ;
cmd . hdr . size = cpu_to_le16 ( sizeof ( cmd ) ) ;
cmd . action = cpu_to_le16 ( CMD_OPT_802_11_RF_CHANNEL_SET ) ;
cmd . channel = cpu_to_le16 ( channel ) ;
2007-12-12 16:00:42 -05:00
ret = lbs_cmd_with_response ( priv , CMD_802_11_RF_CHANNEL , & cmd ) ;
2007-12-11 16:54:15 -05:00
if ( ret )
goto out ;
2007-12-11 17:35:51 -05:00
priv - > curbssparams . channel = ( uint8_t ) le16_to_cpu ( cmd . channel ) ;
lbs_deb_cmd ( " channel switch from %d to %d \n " , old_channel ,
priv - > curbssparams . channel ) ;
2007-12-11 16:54:15 -05:00
out :
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_rssi ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd )
{
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_RSSI ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_rssi ) + S_DS_GEN ) ;
2007-08-02 13:08:24 -04:00
cmd - > params . rssi . N = cpu_to_le16 ( DEFAULT_BCN_AVG_FACTOR ) ;
2007-02-10 12:25:27 -02:00
/* reset Beacon SNR/NF/RSSI values */
2007-12-08 20:04:36 +00:00
priv - > SNR [ TYPE_BEACON ] [ TYPE_NOAVG ] = 0 ;
priv - > SNR [ TYPE_BEACON ] [ TYPE_AVG ] = 0 ;
priv - > NF [ TYPE_BEACON ] [ TYPE_NOAVG ] = 0 ;
priv - > NF [ TYPE_BEACON ] [ TYPE_AVG ] = 0 ;
priv - > RSSI [ TYPE_BEACON ] [ TYPE_NOAVG ] = 0 ;
priv - > RSSI [ TYPE_BEACON ] [ TYPE_AVG ] = 0 ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_reg_access ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmdptr ,
u8 cmd_action , void * pdata_buf )
{
2007-11-15 18:05:47 -05:00
struct lbs_offset_value * offval ;
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
2007-11-15 18:05:47 -05:00
offval = ( struct lbs_offset_value * ) pdata_buf ;
2007-02-10 12:25:27 -02:00
2007-12-07 15:30:44 +00:00
switch ( le16_to_cpu ( cmdptr - > command ) ) {
2007-08-02 11:31:18 -04:00
case CMD_MAC_REG_ACCESS :
2007-02-10 12:25:27 -02:00
{
struct cmd_ds_mac_reg_access * macreg ;
cmdptr - > size =
2007-05-25 23:36:54 -04:00
cpu_to_le16 ( sizeof ( struct cmd_ds_mac_reg_access )
+ S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
macreg =
( struct cmd_ds_mac_reg_access * ) & cmdptr - > params .
macreg ;
macreg - > action = cpu_to_le16 ( cmd_action ) ;
macreg - > offset = cpu_to_le16 ( ( u16 ) offval - > offset ) ;
macreg - > value = cpu_to_le32 ( offval - > value ) ;
break ;
}
2007-08-02 11:31:18 -04:00
case CMD_BBP_REG_ACCESS :
2007-02-10 12:25:27 -02:00
{
struct cmd_ds_bbp_reg_access * bbpreg ;
cmdptr - > size =
cpu_to_le16 ( sizeof
( struct cmd_ds_bbp_reg_access )
+ S_DS_GEN ) ;
bbpreg =
( struct cmd_ds_bbp_reg_access * ) & cmdptr - > params .
bbpreg ;
bbpreg - > action = cpu_to_le16 ( cmd_action ) ;
bbpreg - > offset = cpu_to_le16 ( ( u16 ) offval - > offset ) ;
bbpreg - > value = ( u8 ) offval - > value ;
break ;
}
2007-08-02 11:31:18 -04:00
case CMD_RF_REG_ACCESS :
2007-02-10 12:25:27 -02:00
{
struct cmd_ds_rf_reg_access * rfreg ;
cmdptr - > size =
cpu_to_le16 ( sizeof
( struct cmd_ds_rf_reg_access ) +
S_DS_GEN ) ;
rfreg =
( struct cmd_ds_rf_reg_access * ) & cmdptr - > params .
rfreg ;
rfreg - > action = cpu_to_le16 ( cmd_action ) ;
rfreg - > offset = cpu_to_le16 ( ( u16 ) offval - > offset ) ;
rfreg - > value = ( u8 ) offval - > value ;
break ;
}
default :
break ;
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_mac_address ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action )
{
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_MAC_ADDRESS ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_mac_address ) +
2007-02-10 12:25:27 -02:00
S_DS_GEN ) ;
cmd - > result = 0 ;
cmd - > params . macadd . action = cpu_to_le16 ( cmd_action ) ;
2007-08-02 11:31:18 -04:00
if ( cmd_action = = CMD_ACT_SET ) {
2007-02-10 12:25:27 -02:00
memcpy ( cmd - > params . macadd . macadd ,
2007-12-08 20:04:36 +00:00
priv - > current_addr , ETH_ALEN ) ;
lbs_deb_hex ( LBS_DEB_CMD , " SET_CMD: MAC addr " , priv - > current_addr , 6 ) ;
2007-02-10 12:25:27 -02:00
}
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_802_11_eeprom_access ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
int cmd_action , void * pdata_buf )
{
2007-11-15 18:05:47 -05:00
struct lbs_ioctl_regrdwr * ea = pdata_buf ;
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
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_802_11_EEPROM_ACCESS ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_eeprom_access ) +
S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
cmd - > result = 0 ;
cmd - > params . rdeeprom . action = cpu_to_le16 ( ea - > action ) ;
cmd - > params . rdeeprom . offset = cpu_to_le16 ( ea - > offset ) ;
cmd - > params . rdeeprom . bytecount = cpu_to_le16 ( ea - > NOB ) ;
cmd - > params . rdeeprom . value = 0 ;
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_bt_access ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action , void * pdata_buf )
{
struct cmd_ds_bt_access * bt_access = & cmd - > params . bt ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter_args ( LBS_DEB_CMD , " action %d " , cmd_action ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_BT_ACCESS ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_bt_access ) + S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
cmd - > result = 0 ;
bt_access - > action = cpu_to_le16 ( cmd_action ) ;
switch ( cmd_action ) {
2007-08-02 11:31:18 -04:00
case CMD_ACT_BT_ACCESS_ADD :
2007-02-10 12:25:27 -02:00
memcpy ( bt_access - > addr1 , pdata_buf , 2 * ETH_ALEN ) ;
2007-08-02 11:53:06 -04:00
lbs_deb_hex ( LBS_DEB_MESH , " BT_ADD: blinded MAC addr " , bt_access - > addr1 , 6 ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_ACT_BT_ACCESS_DEL :
2007-02-10 12:25:27 -02:00
memcpy ( bt_access - > addr1 , pdata_buf , 1 * ETH_ALEN ) ;
2007-08-02 11:53:06 -04:00
lbs_deb_hex ( LBS_DEB_MESH , " BT_DEL: blinded MAC addr " , bt_access - > addr1 , 6 ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_ACT_BT_ACCESS_LIST :
2007-02-10 12:25:27 -02:00
bt_access - > id = cpu_to_le32 ( * ( u32 * ) pdata_buf ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_ACT_BT_ACCESS_RESET :
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_ACT_BT_ACCESS_SET_INVERT :
2007-05-25 13:53:26 -04:00
bt_access - > id = cpu_to_le32 ( * ( u32 * ) pdata_buf ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_ACT_BT_ACCESS_GET_INVERT :
2007-05-25 13:53:26 -04:00
break ;
2007-02-10 12:25:27 -02:00
default :
break ;
}
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_fwt_access ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd ,
u16 cmd_action , void * pdata_buf )
{
struct cmd_ds_fwt_access * fwt_access = & cmd - > params . fwt ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter_args ( LBS_DEB_CMD , " action %d " , cmd_action ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_FWT_ACCESS ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_fwt_access ) + S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
cmd - > result = 0 ;
if ( pdata_buf )
memcpy ( fwt_access , pdata_buf , sizeof ( * fwt_access ) ) ;
else
memset ( fwt_access , 0 , sizeof ( * fwt_access ) ) ;
fwt_access - > action = cpu_to_le16 ( cmd_action ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-12-11 15:23:59 -05:00
int lbs_mesh_access ( struct lbs_private * priv , uint16_t cmd_action ,
struct cmd_ds_mesh_access * cmd )
2007-02-10 12:25:27 -02:00
{
2007-12-11 15:23:59 -05:00
int ret ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter_args ( LBS_DEB_CMD , " action %d " , cmd_action ) ;
2007-02-10 12:25:27 -02:00
2007-12-11 15:23:59 -05:00
cmd - > hdr . command = cpu_to_le16 ( CMD_MESH_ACCESS ) ;
cmd - > hdr . size = cpu_to_le16 ( sizeof ( struct cmd_ds_mesh_access ) + S_DS_GEN ) ;
cmd - > hdr . result = 0 ;
2007-02-10 12:25:27 -02:00
2007-12-11 15:23:59 -05:00
cmd - > action = cpu_to_le16 ( cmd_action ) ;
2007-02-10 12:25:27 -02:00
2007-12-12 16:00:42 -05:00
ret = lbs_cmd_with_response ( priv , CMD_MESH_ACCESS , cmd ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-12-11 15:23:59 -05:00
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-12-11 15:23:59 -05:00
EXPORT_SYMBOL_GPL ( lbs_mesh_access ) ;
2007-02-10 12:25:27 -02:00
2007-12-13 00:32:36 -05:00
int lbs_mesh_config ( struct lbs_private * priv , uint16_t enable , uint16_t chan )
2007-12-11 18:56:42 -05:00
{
struct cmd_ds_mesh_config cmd ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
cmd . action = cpu_to_le16 ( enable ) ;
2007-12-13 00:32:36 -05:00
cmd . channel = cpu_to_le16 ( chan ) ;
2007-12-12 23:29:13 -05:00
cmd . type = cpu_to_le16 ( priv - > mesh_tlv ) ;
2007-12-14 22:53:41 -05:00
2007-12-11 18:56:42 -05:00
if ( enable ) {
cmd . length = cpu_to_le16 ( priv - > mesh_ssid_len ) ;
memcpy ( cmd . data , priv - > mesh_ssid , priv - > mesh_ssid_len ) ;
}
2007-12-12 23:29:13 -05:00
lbs_deb_cmd ( " mesh config enable %d TLV %x channel %d SSID %s \n " ,
2007-12-13 00:32:36 -05:00
enable , priv - > mesh_tlv , chan ,
2007-12-11 22:52:03 -05:00
escape_essid ( priv - > mesh_ssid , priv - > mesh_ssid_len ) ) ;
2007-12-12 16:00:42 -05:00
return lbs_cmd_with_response ( priv , CMD_MESH_CONFIG , & cmd ) ;
2007-12-11 18:56:42 -05:00
}
2007-11-20 17:44:28 -05:00
static int lbs_cmd_bcn_ctrl ( struct lbs_private * priv ,
struct cmd_ds_command * cmd ,
u16 cmd_action )
{
struct cmd_ds_802_11_beacon_control
* bcn_ctrl = & cmd - > params . bcn_ctrl ;
lbs_deb_enter ( LBS_DEB_CMD ) ;
cmd - > size =
cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_beacon_control )
+ S_DS_GEN ) ;
cmd - > command = cpu_to_le16 ( CMD_802_11_BEACON_CTRL ) ;
bcn_ctrl - > action = cpu_to_le16 ( cmd_action ) ;
2007-12-08 20:04:36 +00:00
bcn_ctrl - > beacon_enable = cpu_to_le16 ( priv - > beacon_enable ) ;
bcn_ctrl - > beacon_period = cpu_to_le16 ( priv - > beacon_period ) ;
2007-11-20 17:44:28 -05:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
return 0 ;
}
2007-10-30 10:52:46 -04:00
/*
2007-11-15 18:05:47 -05:00
* Note : NEVER use lbs_queue_cmd ( ) with addtail = = 0 other than for
2007-10-30 10:52:46 -04:00
* the command timer , because it does not account for queued commands .
*/
2007-12-08 20:04:36 +00:00
void lbs_queue_cmd ( struct lbs_private * priv ,
2007-11-23 15:43:44 +01:00
struct cmd_ctrl_node * cmdnode ,
u8 addtail )
2007-02-10 12:25:27 -02:00
{
unsigned long flags ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
2007-12-15 00:41:51 -05:00
if ( ! cmdnode ) {
lbs_deb_host ( " QUEUE_CMD: cmdnode is NULL \n " ) ;
2007-02-10 12:25:27 -02:00
goto done ;
}
2007-12-15 00:09:25 -05:00
if ( ! cmdnode - > cmdbuf - > size ) {
lbs_deb_host ( " DNLD_CMD: cmd size is zero \n " ) ;
goto done ;
}
2007-02-10 12:25:27 -02:00
/* Exit_PS command needs to be queued in the header always. */
2007-12-11 13:49:39 -05:00
if ( le16_to_cpu ( cmdnode - > cmdbuf - > command ) = = CMD_802_11_PS_MODE ) {
struct cmd_ds_802_11_ps_mode * psm = ( void * ) cmdnode - > cmdbuf ;
2007-08-02 11:31:18 -04:00
if ( psm - > action = = cpu_to_le16 ( CMD_SUBCMD_EXIT_PS ) ) {
2007-12-08 20:04:36 +00:00
if ( priv - > psstate ! = PS_STATE_FULL_POWER )
2007-02-10 12:25:27 -02:00
addtail = 0 ;
}
}
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 00:35:00 +00:00
if ( addtail )
2007-12-08 20:04:36 +00:00
list_add_tail ( & cmdnode - > list , & priv - > cmdpendingq ) ;
2007-12-08 00:35:00 +00:00
else
2007-12-08 20:04:36 +00:00
list_add ( & cmdnode - > list , & priv - > cmdpendingq ) ;
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
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " QUEUE_CMD: inserted command 0x%04x into cmdpendingq \n " ,
2007-12-15 00:41:51 -05:00
le16_to_cpu ( cmdnode - > cmdbuf - > command ) ) ;
2007-02-10 12:25:27 -02:00
done :
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-15 00:09:25 -05:00
static int lbs_submit_command ( struct lbs_private * priv ,
struct cmd_ctrl_node * cmdnode )
2007-02-10 12:25:27 -02:00
{
unsigned long flags ;
2007-12-11 13:49:39 -05:00
struct cmd_header * cmd ;
2007-08-02 13:18:07 -04:00
int ret = - 1 ;
2007-02-10 12:25:27 -02:00
u16 cmdsize ;
u16 command ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
2007-12-11 13:49:39 -05:00
cmd = cmdnode - > cmdbuf ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
priv - > cur_cmd = cmdnode ;
priv - > cur_cmd_retcode = 0 ;
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
2007-12-11 13:49:39 -05:00
cmdsize = le16_to_cpu ( cmd - > size ) ;
command = le16_to_cpu ( cmd - > command ) ;
2007-02-10 12:25:27 -02:00
2007-12-11 23:42:49 -05:00
lbs_deb_host ( " DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu \n " ,
command , le16_to_cpu ( cmd - > seqnum ) , cmdsize , jiffies ) ;
2007-12-11 13:49:39 -05:00
lbs_deb_hex ( LBS_DEB_HOST , " DNLD_CMD " , ( void * ) cmdnode - > cmdbuf , cmdsize ) ;
2007-08-02 11:54:31 -04:00
2007-12-11 13:49:39 -05:00
ret = priv - > hw_host_to_card ( priv , MVMS_CMD , ( u8 * ) cmd , cmdsize ) ;
2007-12-15 00:09:25 -05:00
if ( ret ) {
lbs_pr_info ( " DNLD_CMD: hw_host_to_card failed: %d \n " , ret ) ;
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
priv - > cur_cmd_retcode = ret ;
__lbs_cleanup_and_insert_cmd ( priv , priv - > cur_cmd ) ;
priv - > cur_cmd = NULL ;
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
goto done ;
}
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " DNLD_CMD: sent command 0x%04x, jiffies %lu \n " , command , jiffies ) ;
2007-02-10 12:25:27 -02:00
/* Setup the timer after transmit command */
2007-08-02 11:31:18 -04:00
if ( command = = CMD_802_11_SCAN | | command = = CMD_802_11_AUTHENTICATE
| | command = = CMD_802_11_ASSOCIATE )
2007-12-08 20:04:36 +00:00
mod_timer ( & priv - > command_timer , jiffies + ( 10 * HZ ) ) ;
2007-02-10 12:25:27 -02:00
else
2007-12-08 20:04:36 +00:00
mod_timer ( & priv - > command_timer , jiffies + ( 5 * HZ ) ) ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
2007-05-25 11:27:16 -04:00
done :
2007-08-02 11:54:31 -04:00
lbs_deb_leave_args ( LBS_DEB_HOST , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-23 15:43:44 +01:00
static int lbs_cmd_mac_control ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
struct cmd_ds_command * cmd )
{
struct cmd_ds_mac_control * mac = & cmd - > params . macctrl ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
cmd - > command = cpu_to_le16 ( CMD_MAC_CONTROL ) ;
2007-05-25 23:36:54 -04:00
cmd - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_mac_control ) + S_DS_GEN ) ;
2007-12-08 20:04:36 +00:00
mac - > action = cpu_to_le16 ( priv - > currentpacketfilter ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " MAC_CONTROL: action 0x%x, size %d \n " ,
2007-05-25 23:36:54 -04:00
le16_to_cpu ( mac - > action ) , le16_to_cpu ( cmd - > size ) ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
/**
* This function inserts command node to cmdfreeq
2007-12-08 20:04:36 +00:00
* after cleans it . Requires priv - > driver_lock held .
2007-02-10 12:25:27 -02:00
*/
2007-11-23 15:43:44 +01:00
void __lbs_cleanup_and_insert_cmd ( struct lbs_private * priv ,
struct cmd_ctrl_node * ptempcmd )
2007-02-10 12:25:27 -02:00
{
if ( ! ptempcmd )
2007-08-02 11:54:31 -04:00
return ;
2007-02-10 12:25:27 -02:00
cleanup_cmdnode ( ptempcmd ) ;
2007-12-08 20:04:36 +00:00
list_add_tail ( & ptempcmd - > list , & priv - > cmdfreeq ) ;
2007-02-10 12:25:27 -02:00
}
2007-11-23 15:43:44 +01:00
static void lbs_cleanup_and_insert_cmd ( struct lbs_private * priv ,
struct cmd_ctrl_node * ptempcmd )
2007-02-10 12:25:27 -02:00
{
unsigned long flags ;
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-11-15 18:05:47 -05:00
__lbs_cleanup_and_insert_cmd ( priv , ptempcmd ) ;
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
}
2007-11-23 15:43:44 +01:00
int lbs_set_radio_control ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
int ret = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
2007-11-15 18:05:47 -05:00
ret = lbs_prepare_and_send_command ( priv ,
2007-08-02 11:31:18 -04:00
CMD_802_11_RADIO_CONTROL ,
CMD_ACT_SET ,
CMD_OPTION_WAITFORRSP , 0 , NULL ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_cmd ( " RADIO_SET: radio %d, preamble %d \n " ,
2007-12-08 20:04:36 +00:00
priv - > radioon , priv - > preamble ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-23 15:43:44 +01:00
int lbs_set_mac_packet_filter ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
int ret = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_CMD ) ;
2007-02-10 12:25:27 -02:00
/* Send MAC control command to station */
2007-11-15 18:05:47 -05:00
ret = lbs_prepare_and_send_command ( priv ,
2007-08-02 11:31:18 -04:00
CMD_MAC_CONTROL , 0 , 0 , 0 , NULL ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_CMD , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
/**
* @ brief This function prepare the command before send to firmware .
*
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
* @ param cmd_no command number
* @ param cmd_action command action : GET or SET
* @ param wait_option wait option : wait response or not
* @ param cmd_oid cmd oid : treated as sub command
* @ param pdata_buf A pointer to informaion buffer
* @ return 0 or - 1
*/
2007-11-23 15:43:44 +01:00
int lbs_prepare_and_send_command ( struct lbs_private * priv ,
2007-02-10 12:25:27 -02:00
u16 cmd_no ,
u16 cmd_action ,
u16 wait_option , u32 cmd_oid , void * pdata_buf )
{
int ret = 0 ;
struct cmd_ctrl_node * cmdnode ;
struct cmd_ds_command * cmdptr ;
unsigned long flags ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( ! priv ) {
lbs_deb_host ( " PREP_CMD: priv is NULL \n " ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
2007-12-08 20:04:36 +00:00
if ( priv - > surpriseremoved ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " PREP_CMD: card removed \n " ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
2007-12-05 17:58:06 +01:00
cmdnode = lbs_get_cmd_ctrl_node ( priv ) ;
2007-02-10 12:25:27 -02:00
if ( cmdnode = = NULL ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " PREP_CMD: cmdnode is NULL \n " ) ;
2007-02-10 12:25:27 -02:00
/* Wake up main thread to execute next command */
2007-08-02 11:32:25 -04:00
wake_up_interruptible ( & priv - > waitq ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
2007-12-14 23:08:13 -05:00
lbs_set_cmd_ctrl_node ( priv , cmdnode , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
2007-12-11 13:49:39 -05:00
cmdptr = ( struct cmd_ds_command * ) cmdnode - > cmdbuf ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " PREP_CMD: command 0x%04x \n " , cmd_no ) ;
2007-02-10 12:25:27 -02:00
/* Set sequence number, command and INT option */
2007-12-08 20:04:36 +00:00
priv - > seqnum + + ;
cmdptr - > seqnum = cpu_to_le16 ( priv - > seqnum ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 23:36:54 -04:00
cmdptr - > command = cpu_to_le16 ( cmd_no ) ;
2007-02-10 12:25:27 -02:00
cmdptr - > result = 0 ;
switch ( cmd_no ) {
2007-08-02 11:31:18 -04:00
case CMD_802_11_PS_MODE :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_ps_mode ( priv , cmdptr , cmd_action ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_SCAN :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_80211_scan ( priv , cmdptr , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_MAC_CONTROL :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_mac_control ( priv , cmdptr ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_ASSOCIATE :
case CMD_802_11_REASSOCIATE :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_80211_associate ( priv , cmdptr , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_DEAUTHENTICATE :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_80211_deauthenticate ( priv , cmdptr ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_SET_WEP :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_set_wep ( priv , cmdptr , cmd_action , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_AD_HOC_START :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_80211_ad_hoc_start ( priv , cmdptr , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_CODE_DNLD :
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_RESET :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_reset ( priv , cmdptr , cmd_action ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_GET_LOG :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_get_log ( priv , cmdptr ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_AUTHENTICATE :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_80211_authenticate ( priv , cmdptr , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_GET_STAT :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_get_stat ( priv , cmdptr ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_SNMP_MIB :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_snmp_mib ( priv , cmdptr ,
2007-02-10 12:25:27 -02:00
cmd_action , cmd_oid , pdata_buf ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_MAC_REG_ACCESS :
case CMD_BBP_REG_ACCESS :
case CMD_RF_REG_ACCESS :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_reg_access ( priv , cmdptr , cmd_action , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_RF_TX_POWER :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_rf_tx_power ( priv , cmdptr ,
2007-02-10 12:25:27 -02:00
cmd_action , pdata_buf ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_RADIO_CONTROL :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_radio_control ( priv , cmdptr , cmd_action ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_RATE_ADAPT_RATESET :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_rate_adapt_rateset ( priv ,
2007-02-10 12:25:27 -02:00
cmdptr , cmd_action ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_MAC_MULTICAST_ADR :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_mac_multicast_adr ( priv , cmdptr , cmd_action ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 13:16:55 -04:00
case CMD_802_11_MONITOR_MODE :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_monitor_mode ( priv , cmdptr ,
2007-08-02 13:16:55 -04:00
cmd_action , pdata_buf ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_AD_HOC_JOIN :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_80211_ad_hoc_join ( priv , cmdptr , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_RSSI :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_rssi ( priv , cmdptr ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_AD_HOC_STOP :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_80211_ad_hoc_stop ( priv , cmdptr ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_ENABLE_RSN :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_enable_rsn ( priv , cmdptr , cmd_action ,
2007-05-25 23:01:24 -04:00
pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_KEY_MATERIAL :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_key_material ( priv , cmdptr , cmd_action ,
2007-05-25 23:01:24 -04:00
cmd_oid , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_PAIRWISE_TSC :
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_GROUP_TSC :
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_MAC_ADDRESS :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_mac_address ( priv , cmdptr , cmd_action ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_EEPROM_ACCESS :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_eeprom_access ( priv , cmdptr ,
2007-02-10 12:25:27 -02:00
cmd_action , pdata_buf ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_SET_AFC :
case CMD_802_11_GET_AFC :
2007-02-10 12:25:27 -02:00
cmdptr - > command = cpu_to_le16 ( cmd_no ) ;
2007-05-25 23:36:54 -04:00
cmdptr - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_afc ) +
S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
memmove ( & cmdptr - > params . afc ,
pdata_buf , sizeof ( struct cmd_ds_802_11_afc ) ) ;
ret = 0 ;
goto done ;
2007-08-02 11:31:18 -04:00
case CMD_802_11D_DOMAIN_INFO :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11d_domain_info ( priv , cmdptr ,
2007-02-10 12:25:27 -02:00
cmd_no , cmd_action ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_SLEEP_PARAMS :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_sleep_params ( priv , cmdptr , cmd_action ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_INACTIVITY_TIMEOUT :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_802_11_inactivity_timeout ( priv , cmdptr ,
2007-02-10 12:25:27 -02:00
cmd_action , pdata_buf ) ;
2007-12-14 23:08:13 -05:00
lbs_set_cmd_ctrl_node ( priv , cmdnode , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_TPC_CFG :
cmdptr - > command = cpu_to_le16 ( CMD_802_11_TPC_CFG ) ;
2007-02-10 12:25:27 -02:00
cmdptr - > size =
cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_tpc_cfg ) +
S_DS_GEN ) ;
memmove ( & cmdptr - > params . tpccfg ,
pdata_buf , sizeof ( struct cmd_ds_802_11_tpc_cfg ) ) ;
ret = 0 ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_LED_GPIO_CTRL :
2007-02-10 12:25:27 -02:00
{
struct mrvlietypes_ledgpio * gpio =
( struct mrvlietypes_ledgpio * )
cmdptr - > params . ledgpio . data ;
memmove ( & cmdptr - > params . ledgpio ,
pdata_buf ,
sizeof ( struct cmd_ds_802_11_led_ctrl ) ) ;
cmdptr - > command =
2007-08-02 11:31:18 -04:00
cpu_to_le16 ( CMD_802_11_LED_GPIO_CTRL ) ;
2007-02-10 12:25:27 -02:00
# define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
cmdptr - > size =
2007-12-07 15:30:44 +00:00
cpu_to_le16 ( le16_to_cpu ( gpio - > header . len )
+ S_DS_GEN
+ ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN ) ;
gpio - > header . len = gpio - > header . len ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
break ;
}
2007-11-26 10:07:14 +01:00
case CMD_802_11_SUBSCRIBE_EVENT :
lbs_cmd_802_11_subscribe_event ( priv , cmdptr ,
cmd_action , pdata_buf ) ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_802_11_PWR_CFG :
cmdptr - > command = cpu_to_le16 ( CMD_802_11_PWR_CFG ) ;
2007-02-10 12:25:27 -02:00
cmdptr - > size =
cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_pwr_cfg ) +
S_DS_GEN ) ;
memmove ( & cmdptr - > params . pwrcfg , pdata_buf ,
sizeof ( struct cmd_ds_802_11_pwr_cfg ) ) ;
ret = 0 ;
break ;
2007-08-02 11:31:18 -04:00
case CMD_BT_ACCESS :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_bt_access ( priv , cmdptr , cmd_action , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_FWT_ACCESS :
2007-11-15 18:05:47 -05:00
ret = lbs_cmd_fwt_access ( priv , cmdptr , cmd_action , pdata_buf ) ;
2007-02-10 12:25:27 -02:00
break ;
2007-08-02 11:31:18 -04:00
case CMD_GET_TSF :
cmdptr - > command = cpu_to_le16 ( CMD_GET_TSF ) ;
2007-05-25 23:36:54 -04:00
cmdptr - > size = cpu_to_le16 ( sizeof ( struct cmd_ds_get_tsf ) +
S_DS_GEN ) ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
break ;
2007-11-20 17:44:28 -05:00
case CMD_802_11_BEACON_CTRL :
ret = lbs_cmd_bcn_ctrl ( priv , cmdptr , cmd_action ) ;
break ;
2007-02-10 12:25:27 -02:00
default :
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " PREP_CMD: unknown command 0x%04x \n " , cmd_no ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
break ;
}
/* return error, since the command preparation failed */
if ( ret ! = 0 ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " PREP_CMD: command preparation failed \n " ) ;
2007-11-15 18:05:47 -05:00
lbs_cleanup_and_insert_cmd ( priv , cmdnode ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
cmdnode - > cmdwaitqwoken = 0 ;
2007-12-08 20:04:36 +00:00
lbs_queue_cmd ( priv , cmdnode , 1 ) ;
2007-08-02 11:32:25 -04:00
wake_up_interruptible ( & priv - > waitq ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:31:18 -04:00
if ( wait_option & CMD_OPTION_WAITFORRSP ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " PREP_CMD: wait for response \n " ) ;
2007-02-10 12:25:27 -02:00
might_sleep ( ) ;
wait_event_interruptible ( cmdnode - > cmdwait_q ,
cmdnode - > cmdwaitqwoken ) ;
}
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
if ( priv - > cur_cmd_retcode ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " PREP_CMD: command failed with return code %d \n " ,
2007-12-08 20:04:36 +00:00
priv - > cur_cmd_retcode ) ;
priv - > cur_cmd_retcode = 0 ;
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
done :
2007-08-02 11:54:31 -04:00
lbs_deb_leave_args ( LBS_DEB_HOST , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-15 18:05:47 -05:00
EXPORT_SYMBOL_GPL ( lbs_prepare_and_send_command ) ;
2007-02-10 12:25:27 -02:00
/**
* @ brief This function allocates the command buffer and link
* it to command free queue .
*
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 0 or - 1
*/
2007-11-23 15:43:44 +01:00
int lbs_allocate_cmd_buffer ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
int ret = 0 ;
2007-12-11 13:49:39 -05:00
u32 bufsize ;
2007-02-10 12:25:27 -02:00
u32 i ;
2007-12-11 13:49:39 -05:00
struct cmd_ctrl_node * cmdarray ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
2007-12-11 13:49:39 -05:00
/* Allocate and initialize the command array */
bufsize = sizeof ( struct cmd_ctrl_node ) * LBS_NUM_CMD_BUFFERS ;
if ( ! ( cmdarray = kzalloc ( bufsize , GFP_KERNEL ) ) ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " ALLOC_CMD_BUF: tempcmd_array is NULL \n " ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
2007-12-11 13:49:39 -05:00
priv - > cmd_array = cmdarray ;
2007-02-10 12:25:27 -02:00
2007-12-11 13:49:39 -05:00
/* Allocate and initialize each command buffer in the command array */
for ( i = 0 ; i < LBS_NUM_CMD_BUFFERS ; i + + ) {
cmdarray [ i ] . cmdbuf = kzalloc ( LBS_CMD_BUFFER_SIZE , GFP_KERNEL ) ;
if ( ! cmdarray [ i ] . cmdbuf ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " ALLOC_CMD_BUF: ptempvirtualaddr is NULL \n " ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
}
2007-12-11 13:49:39 -05:00
for ( i = 0 ; i < LBS_NUM_CMD_BUFFERS ; i + + ) {
init_waitqueue_head ( & cmdarray [ i ] . cmdwait_q ) ;
lbs_cleanup_and_insert_cmd ( priv , & cmdarray [ i ] ) ;
2007-02-10 12:25:27 -02:00
}
ret = 0 ;
2007-05-25 11:27:16 -04:00
done :
2007-08-02 11:54:31 -04:00
lbs_deb_leave_args ( LBS_DEB_HOST , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
/**
* @ brief This function frees the command buffer .
*
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 0 or - 1
*/
2007-11-23 15:43:44 +01:00
int lbs_free_cmd_buffer ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
2007-12-11 13:49:39 -05:00
struct cmd_ctrl_node * cmdarray ;
2007-02-10 12:25:27 -02:00
unsigned int i ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
/* need to check if cmd array is allocated or not */
2007-12-08 20:04:36 +00:00
if ( priv - > cmd_array = = NULL ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " FREE_CMD_BUF: cmd_array is NULL \n " ) ;
2007-02-10 12:25:27 -02:00
goto done ;
}
2007-12-11 13:49:39 -05:00
cmdarray = priv - > cmd_array ;
2007-02-10 12:25:27 -02:00
/* Release shared memory buffers */
2007-12-11 13:49:39 -05:00
for ( i = 0 ; i < LBS_NUM_CMD_BUFFERS ; i + + ) {
if ( cmdarray [ i ] . cmdbuf ) {
kfree ( cmdarray [ i ] . cmdbuf ) ;
cmdarray [ i ] . cmdbuf = NULL ;
2007-02-10 12:25:27 -02:00
}
}
/* Release cmd_ctrl_node */
2007-12-08 20:04:36 +00:00
if ( priv - > cmd_array ) {
kfree ( priv - > cmd_array ) ;
priv - > cmd_array = NULL ;
2007-02-10 12:25:27 -02:00
}
done :
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
return 0 ;
}
/**
* @ brief This function gets a free command node if available in
* command free queue .
*
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 cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
*/
2007-12-11 17:44:10 -05:00
static struct cmd_ctrl_node * lbs_get_cmd_ctrl_node ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
struct cmd_ctrl_node * tempnode ;
unsigned long flags ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-12-08 20:04:36 +00:00
if ( ! priv )
2007-02-10 12:25:27 -02:00
return NULL ;
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
if ( ! list_empty ( & priv - > cmdfreeq ) ) {
tempnode = list_first_entry ( & priv - > cmdfreeq ,
2007-12-06 13:01:21 +01:00
struct cmd_ctrl_node , list ) ;
list_del ( & tempnode - > list ) ;
2007-02-10 12:25:27 -02:00
} else {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " GET_CMD_NODE: cmd_ctrl_node is not available \n " ) ;
2007-02-10 12:25:27 -02:00
tempnode = NULL ;
}
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
if ( tempnode )
2007-02-10 12:25:27 -02:00
cleanup_cmdnode ( tempnode ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
return tempnode ;
}
/**
* @ brief This function cleans command node .
*
* @ param ptempnode A pointer to cmdCtrlNode structure
* @ return n / a
*/
2007-12-11 13:49:39 -05:00
static void cleanup_cmdnode ( struct cmd_ctrl_node * cmdnode )
2007-02-10 12:25:27 -02:00
{
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-12-11 13:49:39 -05:00
if ( ! cmdnode )
2007-02-10 12:25:27 -02:00
return ;
2007-12-11 13:49:39 -05:00
cmdnode - > cmdwaitqwoken = 1 ;
wake_up_interruptible ( & cmdnode - > cmdwait_q ) ;
cmdnode - > pdata_buf = NULL ;
cmdnode - > callback = NULL ;
cmdnode - > callback_arg = 0 ;
2007-02-10 12:25:27 -02:00
2007-12-15 00:41:51 -05:00
memset ( cmdnode - > cmdbuf , 0 , LBS_CMD_BUFFER_SIZE ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
}
/**
* @ brief This function initializes the command node .
*
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
* @ param ptempnode A pointer to cmd_ctrl_node structure
* @ param pdata_buf A pointer to informaion buffer
* @ return 0 or - 1
*/
2007-12-11 17:44:10 -05:00
static void lbs_set_cmd_ctrl_node ( struct lbs_private * priv ,
struct cmd_ctrl_node * ptempnode ,
2007-12-14 23:08:13 -05:00
void * pdata_buf )
2007-02-10 12:25:27 -02:00
{
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
if ( ! ptempnode )
return ;
ptempnode - > pdata_buf = pdata_buf ;
2007-12-07 15:13:05 +00:00
ptempnode - > callback = NULL ;
2007-12-10 13:36:10 -05:00
ptempnode - > callback_arg = 0 ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
}
/**
* @ brief This function executes next command in command
* pending queue . It will put fimware back to PS mode
* if applicable .
*
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 0 or - 1
*/
2007-11-23 15:43:44 +01:00
int lbs_execute_next_command ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
struct cmd_ctrl_node * cmdnode = NULL ;
2007-12-11 13:49:39 -05:00
struct cmd_header * cmd ;
2007-02-10 12:25:27 -02:00
unsigned long flags ;
int ret = 0 ;
2007-08-02 11:54:31 -04:00
// Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
2007-11-15 18:05:47 -05:00
// only caller to us is lbs_thread() and we get even when a
2007-08-02 11:54:31 -04:00
// data packet is received
lbs_deb_enter ( LBS_DEB_THREAD ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
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:31 -04:00
lbs_pr_alert ( " EXEC_NEXT_CMD: already processing command! \n " ) ;
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
if ( ! list_empty ( & priv - > cmdpendingq ) ) {
cmdnode = list_first_entry ( & priv - > cmdpendingq ,
2007-12-06 13:01:21 +01:00
struct cmd_ctrl_node , list ) ;
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
if ( cmdnode ) {
2007-12-11 13:49:39 -05:00
cmd = cmdnode - > cmdbuf ;
2007-02-10 12:25:27 -02:00
2007-12-11 13:49:39 -05:00
if ( is_command_allowed_in_ps ( le16_to_cpu ( cmd - > command ) ) ) {
2007-12-08 20:04:36 +00:00
if ( ( priv - > psstate = = PS_STATE_SLEEP ) | |
( priv - > psstate = = PS_STATE_PRE_SLEEP ) ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host (
" EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d \n " ,
2007-12-11 13:49:39 -05:00
le16_to_cpu ( cmd - > command ) ,
2007-12-08 20:04:36 +00:00
priv - > psstate ) ;
2007-02-10 12:25:27 -02:00
ret = - 1 ;
goto done ;
}
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " EXEC_NEXT_CMD: OK to send command "
2007-12-11 13:49:39 -05:00
" 0x%04x in psstate %d \n " ,
le16_to_cpu ( cmd - > command ) , priv - > psstate ) ;
2007-12-08 20:04:36 +00:00
} else if ( priv - > psstate ! = PS_STATE_FULL_POWER ) {
2007-02-10 12:25:27 -02:00
/*
* 1. Non - PS command :
* Queue it . set needtowakeup to TRUE if current state
2007-11-15 18:05:47 -05:00
* is SLEEP , otherwise call lbs_ps_wakeup to send Exit_PS .
2007-02-10 12:25:27 -02:00
* 2. PS command but not Exit_PS :
* Ignore it .
* 3. PS command Exit_PS :
* Set needtowakeup to TRUE if current state is SLEEP ,
* otherwise send this command down to firmware
* immediately .
*/
2007-12-11 13:49:39 -05:00
if ( cmd - > command ! = cpu_to_le16 ( CMD_802_11_PS_MODE ) ) {
2007-02-10 12:25:27 -02:00
/* Prepare to send Exit PS,
* this non PS command will be sent later */
2007-12-08 20:04:36 +00:00
if ( ( priv - > psstate = = PS_STATE_SLEEP )
| | ( priv - > psstate = = PS_STATE_PRE_SLEEP )
2007-02-10 12:25:27 -02:00
) {
/* w/ new scheme, it will not reach here.
since it is blocked in main_thread . */
2007-12-08 20:04:36 +00:00
priv - > needtowakeup = 1 ;
2007-02-10 12:25:27 -02:00
} else
2007-11-15 18:05:47 -05:00
lbs_ps_wakeup ( priv , 0 ) ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
goto done ;
} else {
/*
* PS command . Ignore it if it is not Exit_PS .
* otherwise send it down immediately .
*/
2007-12-11 13:49:39 -05:00
struct cmd_ds_802_11_ps_mode * psm = ( void * ) cmd ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_host (
" EXEC_NEXT_CMD: PS cmd, action 0x%02x \n " ,
2007-02-10 12:25:27 -02:00
psm - > action ) ;
if ( psm - > action ! =
2007-08-02 11:31:18 -04:00
cpu_to_le16 ( CMD_SUBCMD_EXIT_PS ) ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host (
" EXEC_NEXT_CMD: ignore ENTER_PS cmd \n " ) ;
2007-12-06 13:01:21 +01:00
list_del ( & cmdnode - > list ) ;
2007-11-15 18:05:47 -05:00
lbs_cleanup_and_insert_cmd ( priv , cmdnode ) ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
goto done ;
}
2007-12-08 20:04:36 +00:00
if ( ( priv - > psstate = = PS_STATE_SLEEP ) | |
( priv - > psstate = = PS_STATE_PRE_SLEEP ) ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host (
" EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep \n " ) ;
2007-12-06 13:01:21 +01:00
list_del ( & cmdnode - > list ) ;
2007-11-15 18:05:47 -05:00
lbs_cleanup_and_insert_cmd ( priv , cmdnode ) ;
2007-12-08 20:04:36 +00:00
priv - > needtowakeup = 1 ;
2007-02-10 12:25:27 -02:00
ret = 0 ;
goto done ;
}
2007-08-02 11:54:31 -04:00
lbs_deb_host (
" EXEC_NEXT_CMD: sending EXIT_PS \n " ) ;
2007-02-10 12:25:27 -02:00
}
}
2007-12-06 13:01:21 +01:00
list_del ( & cmdnode - > list ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " EXEC_NEXT_CMD: sending command 0x%04x \n " ,
2007-12-11 13:49:39 -05:00
le16_to_cpu ( cmd - > command ) ) ;
2007-12-15 00:09:25 -05:00
lbs_submit_command ( priv , cmdnode ) ;
2007-02-10 12:25:27 -02:00
} else {
/*
* check if in power save mode , if yes , put the device back
* to PS mode
*/
2007-12-08 20:04:36 +00:00
if ( ( priv - > psmode ! = LBS802_11POWERMODECAM ) & &
( priv - > psstate = = PS_STATE_FULL_POWER ) & &
( ( priv - > connect_status = = LBS_CONNECTED ) | |
( priv - > mesh_connect_status = = LBS_CONNECTED ) ) ) {
if ( priv - > secinfo . WPAenabled | |
priv - > secinfo . WPA2enabled ) {
2007-02-10 12:25:27 -02:00
/* check for valid WPA group keys */
2007-12-08 20:04:36 +00:00
if ( priv - > wpa_mcast_key . len | |
priv - > wpa_unicast_key . len ) {
2007-08-02 11:54:31 -04:00
lbs_deb_host (
2007-02-10 12:25:27 -02:00
" EXEC_NEXT_CMD: WPA enabled and GTK_SET "
" go back to PS_SLEEP " ) ;
2007-11-15 18:05:47 -05:00
lbs_ps_sleep ( priv , 0 ) ;
2007-02-10 12:25:27 -02:00
}
} else {
2007-08-02 11:54:31 -04:00
lbs_deb_host (
" EXEC_NEXT_CMD: cmdpendingq empty, "
" go back to PS_SLEEP " ) ;
2007-11-15 18:05:47 -05:00
lbs_ps_sleep ( priv , 0 ) ;
2007-02-10 12:25:27 -02:00
}
}
}
ret = 0 ;
done :
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_THREAD ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-23 15:43:44 +01:00
void lbs_send_iwevcustom_event ( struct lbs_private * priv , s8 * str )
2007-02-10 12:25:27 -02:00
{
union iwreq_data iwrq ;
u8 buf [ 50 ] ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
memset ( & iwrq , 0 , sizeof ( union iwreq_data ) ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
snprintf ( buf , sizeof ( buf ) - 1 , " %s " , str ) ;
iwrq . data . length = strlen ( buf ) + 1 + IW_EV_LCP_LEN ;
/* Send Event to upper layer */
2007-08-02 11:54:31 -04:00
lbs_deb_wext ( " event indication string %s \n " , ( char * ) buf ) ;
lbs_deb_wext ( " event indication length %d \n " , iwrq . data . length ) ;
lbs_deb_wext ( " sending wireless event IWEVCUSTOM for %s \n " , str ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 13:05:16 -04:00
wireless_send_event ( priv - > dev , IWEVCUSTOM , & iwrq , buf ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_WEXT ) ;
2007-02-10 12:25:27 -02:00
}
2007-11-23 15:43:44 +01:00
static int sendconfirmsleep ( struct lbs_private * priv , u8 * cmdptr , u16 size )
2007-02-10 12:25:27 -02:00
{
unsigned long flags ;
int ret = 0 ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " SEND_SLEEPC_CMD: before download, cmd size %d \n " ,
2007-02-10 12:25:27 -02:00
size ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_hex ( LBS_DEB_HOST , " sleep confirm command " , cmdptr , size ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 12:17:06 -04:00
ret = priv - > hw_host_to_card ( priv , MVMS_CMD , cmdptr , size ) ;
2007-05-25 13:05:16 -04:00
priv - > dnld_sent = DNLD_RES_RECEIVED ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
if ( priv - > intcounter | | priv - > currenttxskb )
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p \n " ,
2007-12-08 20:04:36 +00:00
priv - > intcounter , priv - > currenttxskb ) ;
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-02-10 12:25:27 -02:00
if ( ret ) {
lbs_pr_alert (
" SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep \n " ) ;
} else {
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
if ( ! priv - > intcounter ) {
priv - > psstate = PS_STATE_SLEEP ;
2007-02-10 12:25:27 -02:00
} else {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " SEND_SLEEPC_CMD: after sent, intcounter %d \n " ,
2007-12-08 20:04:36 +00:00
priv - > intcounter ) ;
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
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " SEND_SLEEPC_CMD: sent confirm sleep \n " ) ;
2007-02-10 12:25:27 -02:00
}
2007-08-02 11:54:31 -04:00
lbs_deb_leave_args ( LBS_DEB_HOST , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-11-23 15:43:44 +01:00
void lbs_ps_sleep ( struct lbs_private * priv , int wait_option )
2007-02-10 12:25:27 -02:00
{
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
/*
* PS is currently supported only in Infrastructure mode
* Remove this check if it is to be supported in IBSS mode also
*/
2007-11-15 18:05:47 -05:00
lbs_prepare_and_send_command ( priv , CMD_802_11_PS_MODE ,
2007-08-02 11:31:18 -04:00
CMD_SUBCMD_ENTER_PS , wait_option , 0 , NULL ) ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
}
/**
2007-08-02 11:54:31 -04:00
* @ brief This function sends Exit_PS command to firmware .
2007-02-10 12:25:27 -02:00
*
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
* @ param wait_option wait response or not
* @ return n / a
*/
2007-11-23 15:43:44 +01:00
void lbs_ps_wakeup ( struct lbs_private * priv , int wait_option )
2007-02-10 12:25:27 -02:00
{
2007-05-25 23:36:54 -04:00
__le32 Localpsmode ;
2007-02-10 12:25:27 -02:00
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
2007-11-15 18:05:47 -05:00
Localpsmode = cpu_to_le32 ( LBS802_11POWERMODECAM ) ;
2007-02-10 12:25:27 -02:00
2007-11-15 18:05:47 -05:00
lbs_prepare_and_send_command ( priv , CMD_802_11_PS_MODE ,
2007-08-02 11:31:18 -04:00
CMD_SUBCMD_EXIT_PS ,
2007-02-10 12:25:27 -02:00
wait_option , 0 , & Localpsmode ) ;
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
}
/**
* @ brief This function checks condition and prepares to
* send sleep confirm command to firmware if ok .
*
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
* @ param psmode Power Saving mode
* @ return n / a
*/
2007-11-23 15:43:44 +01:00
void lbs_ps_confirm_sleep ( struct lbs_private * priv , u16 psmode )
2007-02-10 12:25:27 -02:00
{
unsigned long flags = 0 ;
u8 allowed = 1 ;
2007-08-02 11:54:31 -04:00
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 13:05:16 -04:00
if ( priv - > dnld_sent ) {
2007-02-10 12:25:27 -02:00
allowed = 0 ;
2007-12-12 00:14:21 -05:00
lbs_deb_host ( " dnld_sent was set \n " ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
if ( priv - > cur_cmd ) {
2007-02-10 12:25:27 -02:00
allowed = 0 ;
2007-12-12 00:14:21 -05:00
lbs_deb_host ( " cur_cmd was set \n " ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 20:04:36 +00:00
if ( priv - > intcounter > 0 ) {
2007-02-10 12:25:27 -02:00
allowed = 0 ;
2007-12-12 00:14:21 -05:00
lbs_deb_host ( " intcounter %d \n " , priv - > intcounter ) ;
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
if ( allowed ) {
2007-11-15 18:05:47 -05:00
lbs_deb_host ( " sending lbs_ps_confirm_sleep \n " ) ;
2007-12-08 20:04:36 +00:00
sendconfirmsleep ( priv , ( u8 * ) & priv - > lbs_ps_confirm_sleep ,
2007-02-10 12:25:27 -02:00
sizeof ( struct PS_CMD_ConfirmSleep ) ) ;
} else {
2007-08-02 11:54:31 -04:00
lbs_deb_host ( " sleep confirm has been delayed \n " ) ;
2007-02-10 12:25:27 -02:00
}
2007-08-02 11:54:31 -04:00
lbs_deb_leave ( LBS_DEB_HOST ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-05 17:58:11 +01:00
2007-12-11 12:40:35 -05:00
/**
* @ brief Simple callback that copies response back into command
*
* @ param priv A pointer to struct lbs_private structure
* @ param extra A pointer to the original command structure for which
* ' resp ' is a response
* @ param resp A pointer to the command response
*
* @ return 0 on success , error on failure
*/
int lbs_cmd_copyback ( struct lbs_private * priv , unsigned long extra ,
2007-12-11 15:22:27 -05:00
struct cmd_header * resp )
2007-12-11 12:40:35 -05:00
{
struct cmd_header * buf = ( void * ) extra ;
uint16_t copy_len ;
lbs_deb_enter ( LBS_DEB_CMD ) ;
copy_len = min ( le16_to_cpu ( buf - > size ) , le16_to_cpu ( resp - > size ) ) ;
lbs_deb_cmd ( " Copying back %u bytes; command response was %u bytes, "
2007-12-11 15:22:27 -05:00
" copy back buffer was %u bytes \n " , copy_len ,
le16_to_cpu ( resp - > size ) , le16_to_cpu ( buf - > size ) ) ;
2007-12-11 12:40:35 -05:00
memcpy ( buf , resp , copy_len ) ;
lbs_deb_leave ( LBS_DEB_CMD ) ;
return 0 ;
}
2007-12-12 16:00:42 -05:00
EXPORT_SYMBOL_GPL ( lbs_cmd_copyback ) ;
2007-12-11 12:40:35 -05:00
2007-12-05 17:58:11 +01:00
/**
* @ brief Simple way to call firmware functions
*
* @ param priv A pointer to struct lbs_private structure
* @ param psmode one of the many CMD_802_11_xxxx
* @ param cmd pointer to the parameters structure for above command
* ( this should not include the command , size , sequence
* and result fields from struct cmd_ds_gen )
* @ param cmd_size size structure pointed to by cmd
* @ param rsp pointer to an area where the result should be placed
* @ param rsp_size pointer to the size of the rsp area . If the firmware
* returns fewer bytes , then this * rsp_size will be
* changed to the actual size .
* @ return - 1 in case of a higher level error , otherwise
* the result code from the firmware
*/
2007-12-11 12:33:30 -05:00
int __lbs_cmd ( struct lbs_private * priv , uint16_t command ,
struct cmd_header * in_cmd , int in_cmd_size ,
int ( * callback ) ( struct lbs_private * , unsigned long , struct cmd_header * ) ,
2007-12-10 15:11:23 -05:00
unsigned long callback_arg )
2007-12-05 17:58:11 +01:00
{
struct cmd_ctrl_node * cmdnode ;
unsigned long flags ;
int ret = 0 ;
lbs_deb_enter ( LBS_DEB_HOST ) ;
2007-12-08 20:04:36 +00:00
if ( ! priv ) {
lbs_deb_host ( " PREP_CMD: priv is NULL \n " ) ;
2007-12-05 17:58:11 +01:00
ret = - 1 ;
goto done ;
}
2007-12-08 20:04:36 +00:00
if ( priv - > surpriseremoved ) {
2007-12-05 17:58:11 +01:00
lbs_deb_host ( " PREP_CMD: card removed \n " ) ;
ret = - 1 ;
goto done ;
}
cmdnode = lbs_get_cmd_ctrl_node ( priv ) ;
if ( cmdnode = = NULL ) {
lbs_deb_host ( " PREP_CMD: cmdnode is NULL \n " ) ;
/* Wake up main thread to execute next command */
wake_up_interruptible ( & priv - > waitq ) ;
ret = - 1 ;
goto done ;
}
2007-12-08 00:59:54 +00:00
cmdnode - > callback = callback ;
2007-12-10 13:36:10 -05:00
cmdnode - > callback_arg = callback_arg ;
2007-12-05 17:58:11 +01:00
2007-12-11 12:33:30 -05:00
/* Copy the incoming command to the buffer */
2007-12-11 13:49:39 -05:00
memcpy ( cmdnode - > cmdbuf , in_cmd , in_cmd_size ) ;
2007-12-11 12:33:30 -05:00
2007-12-05 17:58:11 +01:00
/* Set sequence number, clean result, move to buffer */
2007-12-08 20:04:36 +00:00
priv - > seqnum + + ;
2007-12-11 13:49:39 -05:00
cmdnode - > cmdbuf - > command = cpu_to_le16 ( command ) ;
cmdnode - > cmdbuf - > size = cpu_to_le16 ( in_cmd_size ) ;
cmdnode - > cmdbuf - > seqnum = cpu_to_le16 ( priv - > seqnum ) ;
cmdnode - > cmdbuf - > result = 0 ;
2007-12-05 17:58:11 +01:00
lbs_deb_host ( " PREP_CMD: command 0x%04x \n " , command ) ;
/* here was the big old switch() statement, which is now obsolete,
* because the caller of lbs_cmd ( ) sets up all of * cmd for us . */
cmdnode - > cmdwaitqwoken = 0 ;
2007-12-08 20:04:36 +00:00
lbs_queue_cmd ( priv , cmdnode , 1 ) ;
2007-12-05 17:58:11 +01:00
wake_up_interruptible ( & priv - > waitq ) ;
might_sleep ( ) ;
wait_event_interruptible ( cmdnode - > cmdwait_q , cmdnode - > cmdwaitqwoken ) ;
2007-12-08 20:04:36 +00:00
spin_lock_irqsave ( & priv - > driver_lock , flags ) ;
if ( priv - > cur_cmd_retcode ) {
2007-12-05 17:58:11 +01:00
lbs_deb_host ( " PREP_CMD: command failed with return code %d \n " ,
2007-12-08 20:04:36 +00:00
priv - > cur_cmd_retcode ) ;
priv - > cur_cmd_retcode = 0 ;
2007-12-05 17:58:11 +01:00
ret = - 1 ;
}
2007-12-08 20:04:36 +00:00
spin_unlock_irqrestore ( & priv - > driver_lock , flags ) ;
2007-12-05 17:58:11 +01:00
done :
lbs_deb_leave_args ( LBS_DEB_HOST , " ret %d " , ret ) ;
return ret ;
}
2007-12-10 15:11:23 -05:00
EXPORT_SYMBOL_GPL ( __lbs_cmd ) ;
2007-12-05 17:58:11 +01:00