2011-02-21 11:11:05 -08:00
/******************************************************************************
*
2011-02-21 11:27:26 -08:00
* Copyright ( c ) 2003 - 2011 Intel Corporation . All rights reserved .
2011-02-21 11:11:05 -08:00
*
* Portions of this file are derived from the ipw3945 project , as well
* as portions of the ieee80211 subsystem header files .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 , USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE .
*
* Contact Information :
* Intel Linux Wireless < ilw @ linux . intel . com >
* Intel Corporation , 5200 N . E . Elam Young Parkway , Hillsboro , OR 97124 - 6497
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/pci.h>
# include <linux/pci-aspm.h>
# include <linux/slab.h>
# include <linux/dma-mapping.h>
# include <linux/delay.h>
# include <linux/sched.h>
# include <linux/skbuff.h>
# include <linux/netdevice.h>
# include <linux/firmware.h>
# include <linux/etherdevice.h>
# include <linux/if_arp.h>
# include <net/ieee80211_radiotap.h>
# include <net/mac80211.h>
# include <asm/div64.h>
# define DRV_NAME "iwl3945"
2011-08-31 10:59:02 +02:00
# include "commands.h"
2011-11-15 14:19:34 +01:00
# include "common.h"
2011-08-31 13:23:20 +02:00
# include "3945.h"
2011-02-21 11:11:05 -08:00
# include "iwl-spectrum.h"
/*
* module name , copyright , version , etc .
*/
# define DRV_DESCRIPTION \
" Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux "
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-02-21 11:11:05 -08:00
# define VD "d"
# else
# define VD
# endif
/*
* add " s " to indicate spectrum measurement included .
* we add it here to be consistent with previous releases in which
* this was configurable .
*/
# define DRV_VERSION IWLWIFI_VERSION VD "s"
2011-02-21 11:27:26 -08:00
# define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
2011-02-21 11:11:05 -08:00
# define DRV_AUTHOR "<ilw@linux.intel.com>"
MODULE_DESCRIPTION ( DRV_DESCRIPTION ) ;
MODULE_VERSION ( DRV_VERSION ) ;
MODULE_AUTHOR ( DRV_COPYRIGHT " " DRV_AUTHOR ) ;
MODULE_LICENSE ( " GPL " ) ;
/* module parameters */
2011-10-24 15:41:30 +02:00
struct il_mod_params il3945_mod_params = {
2011-02-21 11:11:05 -08:00
. sw_crypto = 1 ,
. restart_fw = 1 ,
2011-03-29 11:24:21 +02:00
. disable_hw_scan = 1 ,
2011-02-21 11:11:05 -08:00
/* the rest are 0 by default */
} ;
/**
2011-10-24 15:41:30 +02:00
* il3945_get_antenna_flags - Get antenna flags for RXON command
2011-10-24 16:49:25 +02:00
* @ il : eeprom and antenna fields are used to determine antenna flags
2011-02-21 11:11:05 -08:00
*
2011-10-24 16:49:25 +02:00
* il - > eeprom39 is used to determine if antenna AUX / MAIN are reversed
2011-10-24 15:41:30 +02:00
* il3945_mod_params . antenna specifies the antenna diversity mode :
2011-02-21 11:11:05 -08:00
*
2011-10-24 15:41:30 +02:00
* IL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
* IL_ANTENNA_MAIN - Force MAIN antenna
* IL_ANTENNA_AUX - Force AUX antenna
2011-02-21 11:11:05 -08:00
*/
2011-11-15 14:45:59 +01:00
__le32
il3945_get_antenna_flags ( const struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il3945_eeprom * eeprom = ( struct il3945_eeprom * ) il - > eeprom ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
switch ( il3945_mod_params . antenna ) {
case IL_ANTENNA_DIVERSITY :
2011-02-21 11:11:05 -08:00
return 0 ;
2011-10-24 15:41:30 +02:00
case IL_ANTENNA_MAIN :
2011-02-21 11:11:05 -08:00
if ( eeprom - > antenna_switch_type )
return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK ;
return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK ;
2011-10-24 15:41:30 +02:00
case IL_ANTENNA_AUX :
2011-02-21 11:11:05 -08:00
if ( eeprom - > antenna_switch_type )
return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK ;
return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK ;
}
/* bad antenna selector value */
2011-08-18 22:07:57 +02:00
IL_ERR ( " Bad antenna selector value (0x%x) \n " ,
2011-11-15 14:45:59 +01:00
il3945_mod_params . antenna ) ;
2011-02-21 11:11:05 -08:00
return 0 ; /* "diversity" is default if error */
}
2011-11-15 14:45:59 +01:00
static int
il3945_set_ccmp_dynamic_key_info ( struct il_priv * il ,
struct ieee80211_key_conf * keyconf , u8 sta_id )
2011-02-21 11:11:05 -08:00
{
unsigned long flags ;
__le16 key_flags = 0 ;
int ret ;
key_flags | = ( STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK ) ;
key_flags | = cpu_to_le16 ( keyconf - > keyidx < < STA_KEY_FLG_KEYID_POS ) ;
2012-02-03 17:31:44 +01:00
if ( sta_id = = il - > hw_params . bcast_id )
2011-02-21 11:11:05 -08:00
key_flags | = STA_KEY_MULTICAST_MSK ;
keyconf - > flags | = IEEE80211_KEY_FLAG_GENERATE_IV ;
keyconf - > hw_key_idx = keyconf - > keyidx ;
key_flags & = ~ STA_KEY_FLG_INVALID ;
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > sta_lock , flags ) ;
il - > stations [ sta_id ] . keyinfo . cipher = keyconf - > cipher ;
il - > stations [ sta_id ] . keyinfo . keylen = keyconf - > keylen ;
2011-11-15 14:45:59 +01:00
memcpy ( il - > stations [ sta_id ] . keyinfo . key , keyconf - > key , keyconf - > keylen ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
memcpy ( il - > stations [ sta_id ] . sta . key . key , keyconf - > key , keyconf - > keylen ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
if ( ( il - > stations [ sta_id ] . sta . key .
key_flags & STA_KEY_FLG_ENCRYPT_MSK ) = = STA_KEY_FLG_NO_ENC )
2011-10-24 16:49:25 +02:00
il - > stations [ sta_id ] . sta . key . key_offset =
2011-11-15 14:45:59 +01:00
il_get_free_ucode_key_idx ( il ) ;
2011-02-21 11:11:05 -08:00
/* else, we are overriding an existing key => no need to allocated room
2011-11-15 14:45:59 +01:00
* in uCode . */
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
WARN ( il - > stations [ sta_id ] . sta . key . key_offset = = WEP_INVALID_OFFSET ,
2011-11-15 14:45:59 +01:00
" no space for a new key " ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > stations [ sta_id ] . sta . key . key_flags = key_flags ;
il - > stations [ sta_id ] . sta . sta . modify_mask = STA_MODIFY_KEY_MASK ;
il - > stations [ sta_id ] . sta . mode = STA_CONTROL_MODIFY_MSK ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_INFO ( " hwcrypto: modify ucode station key info \n " ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
ret = il_send_add_sta ( il , & il - > stations [ sta_id ] . sta , CMD_ASYNC ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
spin_unlock_irqrestore ( & il - > sta_lock , flags ) ;
2011-02-21 11:11:05 -08:00
return ret ;
}
2011-11-15 14:45:59 +01:00
static int
il3945_set_tkip_dynamic_key_info ( struct il_priv * il ,
struct ieee80211_key_conf * keyconf , u8 sta_id )
2011-02-21 11:11:05 -08:00
{
return - EOPNOTSUPP ;
}
2011-11-15 14:45:59 +01:00
static int
il3945_set_wep_dynamic_key_info ( struct il_priv * il ,
struct ieee80211_key_conf * keyconf , u8 sta_id )
2011-02-21 11:11:05 -08:00
{
return - EOPNOTSUPP ;
}
2011-11-15 14:45:59 +01:00
static int
il3945_clear_sta_key_info ( struct il_priv * il , u8 sta_id )
2011-02-21 11:11:05 -08:00
{
unsigned long flags ;
2011-10-24 15:41:30 +02:00
struct il_addsta_cmd sta_cmd ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > sta_lock , flags ) ;
memset ( & il - > stations [ sta_id ] . keyinfo , 0 , sizeof ( struct il_hw_key ) ) ;
2011-11-15 14:45:59 +01:00
memset ( & il - > stations [ sta_id ] . sta . key , 0 , sizeof ( struct il4965_keyinfo ) ) ;
2011-10-24 16:49:25 +02:00
il - > stations [ sta_id ] . sta . key . key_flags = STA_KEY_FLG_NO_ENC ;
il - > stations [ sta_id ] . sta . sta . modify_mask = STA_MODIFY_KEY_MASK ;
il - > stations [ sta_id ] . sta . mode = STA_CONTROL_MODIFY_MSK ;
2011-11-15 14:45:59 +01:00
memcpy ( & sta_cmd , & il - > stations [ sta_id ] . sta ,
sizeof ( struct il_addsta_cmd ) ) ;
2011-10-24 16:49:25 +02:00
spin_unlock_irqrestore ( & il - > sta_lock , flags ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_INFO ( " hwcrypto: clear ucode station key info \n " ) ;
2011-10-24 16:49:25 +02:00
return il_send_add_sta ( il , & sta_cmd , CMD_SYNC ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static int
il3945_set_dynamic_key ( struct il_priv * il , struct ieee80211_key_conf * keyconf ,
u8 sta_id )
2011-02-21 11:11:05 -08:00
{
int ret = 0 ;
keyconf - > hw_key_idx = HW_KEY_DYNAMIC ;
switch ( keyconf - > cipher ) {
case WLAN_CIPHER_SUITE_CCMP :
2011-10-24 16:49:25 +02:00
ret = il3945_set_ccmp_dynamic_key_info ( il , keyconf , sta_id ) ;
2011-02-21 11:11:05 -08:00
break ;
case WLAN_CIPHER_SUITE_TKIP :
2011-10-24 16:49:25 +02:00
ret = il3945_set_tkip_dynamic_key_info ( il , keyconf , sta_id ) ;
2011-02-21 11:11:05 -08:00
break ;
case WLAN_CIPHER_SUITE_WEP40 :
case WLAN_CIPHER_SUITE_WEP104 :
2011-10-24 16:49:25 +02:00
ret = il3945_set_wep_dynamic_key_info ( il , keyconf , sta_id ) ;
2011-02-21 11:11:05 -08:00
break ;
default :
2011-11-15 14:45:59 +01:00
IL_ERR ( " Unknown alg: %s alg=%x \n " , __func__ , keyconf - > cipher ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
}
2011-11-15 11:21:01 +01:00
D_WEP ( " Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d \n " ,
2011-11-15 14:45:59 +01:00
keyconf - > cipher , keyconf - > keylen , keyconf - > keyidx , sta_id , ret ) ;
2011-02-21 11:11:05 -08:00
return ret ;
}
2011-11-15 14:45:59 +01:00
static int
il3945_remove_static_key ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
int ret = - EOPNOTSUPP ;
return ret ;
}
2011-11-15 14:45:59 +01:00
static int
il3945_set_static_key ( struct il_priv * il , struct ieee80211_key_conf * key )
2011-02-21 11:11:05 -08:00
{
if ( key - > cipher = = WLAN_CIPHER_SUITE_WEP40 | |
key - > cipher = = WLAN_CIPHER_SUITE_WEP104 )
return - EOPNOTSUPP ;
2011-08-18 22:07:57 +02:00
IL_ERR ( " Static key invalid: cipher %x \n " , key - > cipher ) ;
2011-02-21 11:11:05 -08:00
return - EINVAL ;
}
2011-11-15 14:45:59 +01:00
static void
il3945_clear_free_frames ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
struct list_head * element ;
2011-11-15 14:45:59 +01:00
D_INFO ( " %d frames on pre-allocated heap on clear. \n " , il - > frames_count ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
while ( ! list_empty ( & il - > free_frames ) ) {
element = il - > free_frames . next ;
2011-02-21 11:11:05 -08:00
list_del ( element ) ;
2011-10-24 15:41:30 +02:00
kfree ( list_entry ( element , struct il3945_frame , list ) ) ;
2011-10-24 16:49:25 +02:00
il - > frames_count - - ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 16:49:25 +02:00
if ( il - > frames_count ) {
2011-08-18 22:07:57 +02:00
IL_WARN ( " %d frames still in use. Did we lose one? \n " ,
2011-11-15 14:45:59 +01:00
il - > frames_count ) ;
2011-10-24 16:49:25 +02:00
il - > frames_count = 0 ;
2011-02-21 11:11:05 -08:00
}
}
2011-11-15 14:45:59 +01:00
static struct il3945_frame *
il3945_get_free_frame ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 15:41:30 +02:00
struct il3945_frame * frame ;
2011-02-21 11:11:05 -08:00
struct list_head * element ;
2011-10-24 16:49:25 +02:00
if ( list_empty ( & il - > free_frames ) ) {
2011-02-21 11:11:05 -08:00
frame = kzalloc ( sizeof ( * frame ) , GFP_KERNEL ) ;
if ( ! frame ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Could not allocate frame! \n " ) ;
2011-02-21 11:11:05 -08:00
return NULL ;
}
2011-10-24 16:49:25 +02:00
il - > frames_count + + ;
2011-02-21 11:11:05 -08:00
return frame ;
}
2011-10-24 16:49:25 +02:00
element = il - > free_frames . next ;
2011-02-21 11:11:05 -08:00
list_del ( element ) ;
2011-10-24 15:41:30 +02:00
return list_entry ( element , struct il3945_frame , list ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_free_frame ( struct il_priv * il , struct il3945_frame * frame )
2011-02-21 11:11:05 -08:00
{
memset ( frame , 0 , sizeof ( * frame ) ) ;
2011-10-24 16:49:25 +02:00
list_add ( & frame - > list , & il - > free_frames ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
unsigned int
il3945_fill_beacon_frame ( struct il_priv * il , struct ieee80211_hdr * hdr ,
int left )
2011-02-21 11:11:05 -08:00
{
2011-11-15 11:29:04 +01:00
if ( ! il_is_associated ( il ) | | ! il - > beacon_skb )
2011-02-21 11:11:05 -08:00
return 0 ;
2011-10-24 16:49:25 +02:00
if ( il - > beacon_skb - > len > left )
2011-02-21 11:11:05 -08:00
return 0 ;
2011-10-24 16:49:25 +02:00
memcpy ( hdr , il - > beacon_skb - > data , il - > beacon_skb - > len ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
return il - > beacon_skb - > len ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static int
il3945_send_beacon_cmd ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 15:41:30 +02:00
struct il3945_frame * frame ;
2011-02-21 11:11:05 -08:00
unsigned int frame_size ;
int rc ;
u8 rate ;
2011-10-24 16:49:25 +02:00
frame = il3945_get_free_frame ( il ) ;
2011-02-21 11:11:05 -08:00
if ( ! frame ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Could not obtain free frame buffer for beacon "
2011-11-15 14:45:59 +01:00
" command. \n " ) ;
2011-02-21 11:11:05 -08:00
return - ENOMEM ;
}
2012-02-03 17:31:57 +01:00
rate = il_get_lowest_plcp ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
frame_size = il3945_hw_get_beacon_cmd ( il , frame , rate ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
rc = il_send_cmd_pdu ( il , C_TX_BEACON , frame_size , & frame - > u . cmd [ 0 ] ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_free_frame ( il , frame ) ;
2011-02-21 11:11:05 -08:00
return rc ;
}
2011-11-15 14:45:59 +01:00
static void
il3945_unset_hw_params ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
if ( il - > _3945 . shared_virt )
dma_free_coherent ( & il - > pci_dev - > dev ,
2011-10-24 15:41:30 +02:00
sizeof ( struct il3945_shared ) ,
2011-11-15 14:45:59 +01:00
il - > _3945 . shared_virt , il - > _3945 . shared_phys ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_build_tx_cmd_hwcrypto ( struct il_priv * il , struct ieee80211_tx_info * info ,
struct il_device_cmd * cmd ,
struct sk_buff * skb_frag , int sta_id )
2011-02-21 11:11:05 -08:00
{
2011-10-24 15:41:30 +02:00
struct il3945_tx_cmd * tx_cmd = ( struct il3945_tx_cmd * ) cmd - > cmd . payload ;
2011-10-24 16:49:25 +02:00
struct il_hw_key * keyinfo = & il - > stations [ sta_id ] . keyinfo ;
2011-02-21 11:11:05 -08:00
tx_cmd - > sec_ctl = 0 ;
switch ( keyinfo - > cipher ) {
case WLAN_CIPHER_SUITE_CCMP :
tx_cmd - > sec_ctl = TX_CMD_SEC_CCM ;
memcpy ( tx_cmd - > key , keyinfo - > key , keyinfo - > keylen ) ;
2011-11-15 11:21:01 +01:00
D_TX ( " tx_cmd with AES hwcrypto \n " ) ;
2011-02-21 11:11:05 -08:00
break ;
case WLAN_CIPHER_SUITE_TKIP :
break ;
case WLAN_CIPHER_SUITE_WEP104 :
tx_cmd - > sec_ctl | = TX_CMD_SEC_KEY128 ;
/* fall through */
case WLAN_CIPHER_SUITE_WEP40 :
2011-11-15 14:45:59 +01:00
tx_cmd - > sec_ctl | =
TX_CMD_SEC_WEP | ( info - > control . hw_key - >
hw_key_idx & TX_CMD_SEC_MSK ) < <
TX_CMD_SEC_SHIFT ;
2011-02-21 11:11:05 -08:00
memcpy ( & tx_cmd - > key [ 3 ] , keyinfo - > key , keyinfo - > keylen ) ;
2011-11-15 14:45:59 +01:00
D_TX ( " Configuring packet for WEP encryption " " with key %d \n " ,
info - > control . hw_key - > hw_key_idx ) ;
2011-02-21 11:11:05 -08:00
break ;
default :
2011-08-18 22:07:57 +02:00
IL_ERR ( " Unknown encode cipher %x \n " , keyinfo - > cipher ) ;
2011-02-21 11:11:05 -08:00
break ;
}
}
/*
2011-08-30 15:26:35 +02:00
* handle build C_TX command notification .
2011-02-21 11:11:05 -08:00
*/
2011-11-15 14:45:59 +01:00
static void
il3945_build_tx_cmd_basic ( struct il_priv * il , struct il_device_cmd * cmd ,
struct ieee80211_tx_info * info ,
struct ieee80211_hdr * hdr , u8 std_id )
2011-02-21 11:11:05 -08:00
{
2011-10-24 15:41:30 +02:00
struct il3945_tx_cmd * tx_cmd = ( struct il3945_tx_cmd * ) cmd - > cmd . payload ;
2011-02-21 11:11:05 -08:00
__le32 tx_flags = tx_cmd - > tx_flags ;
__le16 fc = hdr - > frame_control ;
tx_cmd - > stop_time . life_time = TX_CMD_LIFE_TIME_INFINITE ;
if ( ! ( info - > flags & IEEE80211_TX_CTL_NO_ACK ) ) {
tx_flags | = TX_CMD_FLG_ACK_MSK ;
if ( ieee80211_is_mgmt ( fc ) )
tx_flags | = TX_CMD_FLG_SEQ_CTL_MSK ;
if ( ieee80211_is_probe_resp ( fc ) & &
! ( le16_to_cpu ( hdr - > seq_ctrl ) & 0xf ) )
tx_flags | = TX_CMD_FLG_TSF_MSK ;
} else {
tx_flags & = ( ~ TX_CMD_FLG_ACK_MSK ) ;
tx_flags | = TX_CMD_FLG_SEQ_CTL_MSK ;
}
tx_cmd - > sta_id = std_id ;
if ( ieee80211_has_morefrags ( fc ) )
tx_flags | = TX_CMD_FLG_MORE_FRAG_MSK ;
if ( ieee80211_is_data_qos ( fc ) ) {
u8 * qc = ieee80211_get_qos_ctl ( hdr ) ;
tx_cmd - > tid_tspec = qc [ 0 ] & 0xf ;
tx_flags & = ~ TX_CMD_FLG_SEQ_CTL_MSK ;
} else {
tx_flags | = TX_CMD_FLG_SEQ_CTL_MSK ;
}
2011-10-24 16:49:25 +02:00
il_tx_cmd_protection ( il , info , fc , & tx_flags ) ;
2011-02-21 11:11:05 -08:00
tx_flags & = ~ ( TX_CMD_FLG_ANT_SEL_MSK ) ;
if ( ieee80211_is_mgmt ( fc ) ) {
if ( ieee80211_is_assoc_req ( fc ) | | ieee80211_is_reassoc_req ( fc ) )
tx_cmd - > timeout . pm_frame_timeout = cpu_to_le16 ( 3 ) ;
else
tx_cmd - > timeout . pm_frame_timeout = cpu_to_le16 ( 2 ) ;
} else {
tx_cmd - > timeout . pm_frame_timeout = 0 ;
}
tx_cmd - > driver_txop = 0 ;
tx_cmd - > tx_flags = tx_flags ;
tx_cmd - > next_frame_len = 0 ;
}
/*
2011-08-30 15:26:35 +02:00
* start C_TX command process
2011-02-21 11:11:05 -08:00
*/
2011-11-15 14:45:59 +01:00
static int
2012-07-23 21:33:42 +02:00
il3945_tx_skb ( struct il_priv * il ,
struct ieee80211_sta * sta ,
struct sk_buff * skb )
2011-02-21 11:11:05 -08:00
{
struct ieee80211_hdr * hdr = ( struct ieee80211_hdr * ) skb - > data ;
struct ieee80211_tx_info * info = IEEE80211_SKB_CB ( skb ) ;
2011-10-24 15:41:30 +02:00
struct il3945_tx_cmd * tx_cmd ;
struct il_tx_queue * txq = NULL ;
struct il_queue * q = NULL ;
struct il_device_cmd * out_cmd ;
struct il_cmd_meta * out_meta ;
2011-02-21 11:11:05 -08:00
dma_addr_t phys_addr ;
dma_addr_t txcmd_phys ;
int txq_id = skb_get_queue_mapping ( skb ) ;
u16 len , idx , hdr_len ;
2013-03-14 12:48:40 +01:00
u16 firstlen , secondlen ;
2011-02-21 11:11:05 -08:00
u8 id ;
u8 unicast ;
u8 sta_id ;
u8 tid = 0 ;
__le16 fc ;
u8 wait_write_ptr = 0 ;
unsigned long flags ;
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
if ( il_is_rfkill ( il ) ) {
2011-11-15 11:21:01 +01:00
D_DROP ( " Dropping - RF KILL \n " ) ;
2011-02-21 11:11:05 -08:00
goto drop_unlock ;
}
2011-11-15 14:45:59 +01:00
if ( ( ieee80211_get_tx_rate ( il - > hw , info ) - > hw_value & 0xFF ) = =
IL_INVALID_RATE ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " ERROR: No TX rate available. \n " ) ;
2011-02-21 11:11:05 -08:00
goto drop_unlock ;
}
unicast = ! is_multicast_ether_addr ( hdr - > addr1 ) ;
id = 0 ;
fc = hdr - > frame_control ;
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-02-21 11:11:05 -08:00
if ( ieee80211_is_auth ( fc ) )
2011-11-15 11:21:01 +01:00
D_TX ( " Sending AUTH frame \n " ) ;
2011-02-21 11:11:05 -08:00
else if ( ieee80211_is_assoc_req ( fc ) )
2011-11-15 11:21:01 +01:00
D_TX ( " Sending ASSOC frame \n " ) ;
2011-02-21 11:11:05 -08:00
else if ( ieee80211_is_reassoc_req ( fc ) )
2011-11-15 11:21:01 +01:00
D_TX ( " Sending REASSOC frame \n " ) ;
2011-02-21 11:11:05 -08:00
# endif
2011-10-24 16:49:25 +02:00
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
hdr_len = ieee80211_hdrlen ( fc ) ;
2011-11-15 12:30:17 +01:00
/* Find idx into station table for destination station */
2012-07-23 21:33:42 +02:00
sta_id = il_sta_id_or_broadcast ( il , sta ) ;
2011-10-24 15:41:30 +02:00
if ( sta_id = = IL_INVALID_STATION ) {
2011-11-15 14:45:59 +01:00
D_DROP ( " Dropping - INVALID STATION: %pM \n " , hdr - > addr1 ) ;
2011-02-21 11:11:05 -08:00
goto drop ;
}
2011-11-15 11:21:01 +01:00
D_RATE ( " station Id %d \n " , sta_id ) ;
2011-02-21 11:11:05 -08:00
if ( ieee80211_is_data_qos ( fc ) ) {
u8 * qc = ieee80211_get_qos_ctl ( hdr ) ;
tid = qc [ 0 ] & IEEE80211_QOS_CTL_TID_MASK ;
if ( unlikely ( tid > = MAX_TID_COUNT ) )
goto drop ;
}
/* Descriptor for chosen Tx queue */
2011-10-24 16:49:25 +02:00
txq = & il - > txq [ txq_id ] ;
2011-02-21 11:11:05 -08:00
q = & txq - > q ;
2011-10-24 15:41:30 +02:00
if ( ( il_queue_space ( q ) < q - > high_mark ) )
2011-02-21 11:11:05 -08:00
goto drop ;
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 12:30:17 +01:00
idx = il_get_cmd_idx ( q , q - > write_ptr , 0 ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:32:00 +01:00
txq - > skbs [ q - > write_ptr ] = skb ;
2011-02-21 11:11:05 -08:00
/* Init first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq - > cmd [ idx ] ;
out_meta = & txq - > meta [ idx ] ;
2011-10-24 15:41:30 +02:00
tx_cmd = ( struct il3945_tx_cmd * ) out_cmd - > cmd . payload ;
2011-02-21 11:11:05 -08:00
memset ( & out_cmd - > hdr , 0 , sizeof ( out_cmd - > hdr ) ) ;
memset ( tx_cmd , 0 , sizeof ( * tx_cmd ) ) ;
/*
* Set up the Tx - command ( not MAC ! ) header .
2011-11-15 12:30:17 +01:00
* Store the chosen Tx queue and TFD idx within the sequence field ;
2011-02-21 11:11:05 -08:00
* after Tx , uCode ' s Tx response will return this value so driver can
* locate the frame within the tx queue and do post - tx processing .
*/
2011-08-30 15:26:35 +02:00
out_cmd - > hdr . cmd = C_TX ;
2011-11-15 14:45:59 +01:00
out_cmd - > hdr . sequence =
cpu_to_le16 ( ( u16 )
( QUEUE_TO_SEQ ( txq_id ) | IDX_TO_SEQ ( q - > write_ptr ) ) ) ;
2011-02-21 11:11:05 -08:00
/* Copy MAC header from skb into command buffer */
memcpy ( tx_cmd - > hdr , hdr , hdr_len ) ;
if ( info - > control . hw_key )
2011-10-24 16:49:25 +02:00
il3945_build_tx_cmd_hwcrypto ( il , info , out_cmd , skb , sta_id ) ;
2011-02-21 11:11:05 -08:00
/* TODO need this for burst mode later on */
2011-10-24 16:49:25 +02:00
il3945_build_tx_cmd_basic ( il , out_cmd , info , hdr , sta_id ) ;
2011-02-21 11:11:05 -08:00
2011-12-23 08:13:49 +01:00
il3945_hw_build_tx_cmd_rate ( il , out_cmd , info , hdr , sta_id ) ;
2011-02-21 11:11:05 -08:00
/* Total # bytes to be transmitted */
2013-02-13 15:49:08 +01:00
tx_cmd - > len = cpu_to_le16 ( ( u16 ) skb - > len ) ;
2011-02-21 11:11:05 -08:00
tx_cmd - > tx_flags & = ~ TX_CMD_FLG_ANT_A_MSK ;
tx_cmd - > tx_flags & = ~ TX_CMD_FLG_ANT_B_MSK ;
/*
* Use the first empty entry in this queue ' s command buffer array
* to contain the Tx command and MAC header concatenated together
* ( payload data will be in another buffer ) .
* Size of this varies , due to varying MAC header length .
* If end is not dword aligned , we ' ll have 2 extra bytes at the end
* of the MAC header ( device reads on dword boundaries ) .
* We ' ll tell device about this padding later .
*/
2011-11-15 14:45:59 +01:00
len =
sizeof ( struct il3945_tx_cmd ) + sizeof ( struct il_cmd_header ) +
hdr_len ;
2013-03-14 12:48:40 +01:00
firstlen = ( len + 3 ) & ~ 3 ;
2011-02-21 11:11:05 -08:00
/* Physical address of this Tx command's header (not MAC header!),
* within command buffer array . */
2011-11-15 14:45:59 +01:00
txcmd_phys =
2013-03-14 12:48:40 +01:00
pci_map_single ( il - > pci_dev , & out_cmd - > hdr , firstlen ,
PCI_DMA_TODEVICE ) ;
2013-02-13 15:49:08 +01:00
if ( unlikely ( pci_dma_mapping_error ( il - > pci_dev , txcmd_phys ) ) )
goto drop_unlock ;
2011-02-21 11:11:05 -08:00
/* Set up TFD's 2nd entry to point directly to remainder of skb,
* if any ( 802.11 null frames have no payload ) . */
2013-03-14 12:48:40 +01:00
secondlen = skb - > len - hdr_len ;
if ( secondlen > 0 ) {
2011-11-15 14:45:59 +01:00
phys_addr =
2013-03-14 12:48:40 +01:00
pci_map_single ( il - > pci_dev , skb - > data + hdr_len , secondlen ,
2011-11-15 14:45:59 +01:00
PCI_DMA_TODEVICE ) ;
2013-02-13 15:49:08 +01:00
if ( unlikely ( pci_dma_mapping_error ( il - > pci_dev , phys_addr ) ) )
goto drop_unlock ;
}
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
2013-03-14 12:48:40 +01:00
il - > ops - > txq_attach_buf_to_tfd ( il , txq , txcmd_phys , firstlen , 1 , 0 ) ;
2013-02-13 15:49:08 +01:00
dma_unmap_addr_set ( out_meta , mapping , txcmd_phys ) ;
2013-03-14 12:48:40 +01:00
dma_unmap_len_set ( out_meta , len , firstlen ) ;
if ( secondlen > 0 )
il - > ops - > txq_attach_buf_to_tfd ( il , txq , phys_addr , secondlen , 0 ,
U32_PAD ( secondlen ) ) ;
2013-02-13 15:49:08 +01:00
if ( ! ieee80211_has_morefrags ( hdr - > frame_control ) ) {
txq - > need_update = 1 ;
} else {
wait_write_ptr = 1 ;
txq - > need_update = 0 ;
2011-02-21 11:11:05 -08:00
}
2013-02-13 15:49:08 +01:00
il_update_stats ( il , true , fc , skb - > len ) ;
D_TX ( " sequence nr = 0X%x \n " , le16_to_cpu ( out_cmd - > hdr . sequence ) ) ;
D_TX ( " tx_flags = 0X%x \n " , le32_to_cpu ( tx_cmd - > tx_flags ) ) ;
il_print_hex_dump ( il , IL_DL_TX , tx_cmd , sizeof ( * tx_cmd ) ) ;
il_print_hex_dump ( il , IL_DL_TX , ( u8 * ) tx_cmd - > hdr ,
ieee80211_hdrlen ( fc ) ) ;
2011-11-15 12:30:17 +01:00
/* Tell device the write idx *just past* this latest filled TFD */
2011-10-24 15:41:30 +02:00
q - > write_ptr = il_queue_inc_wrap ( q - > write_ptr , q - > n_bd ) ;
2011-10-24 16:49:25 +02:00
il_txq_update_write_ptr ( il , txq ) ;
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
if ( il_queue_space ( q ) < q - > high_mark & & il - > mac80211_registered ) {
2011-02-21 11:11:05 -08:00
if ( wait_write_ptr ) {
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
txq - > need_update = 1 ;
2011-10-24 16:49:25 +02:00
il_txq_update_write_ptr ( il , txq ) ;
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 16:49:25 +02:00
il_stop_queue ( il , txq ) ;
2011-02-21 11:11:05 -08:00
}
return 0 ;
drop_unlock :
2011-10-24 16:49:25 +02:00
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
drop :
return - 1 ;
}
2011-11-15 14:45:59 +01:00
static int
il3945_get_measurement ( struct il_priv * il ,
struct ieee80211_measurement_params * params , u8 type )
2011-02-21 11:11:05 -08:00
{
2011-10-24 15:41:30 +02:00
struct il_spectrum_cmd spectrum ;
2011-08-26 14:36:21 +02:00
struct il_rx_pkt * pkt ;
2011-10-24 15:41:30 +02:00
struct il_host_cmd cmd = {
2011-08-30 15:26:35 +02:00
. id = C_SPECTRUM_MEASUREMENT ,
2011-02-21 11:11:05 -08:00
. data = ( void * ) & spectrum ,
. flags = CMD_WANT_SKB ,
} ;
u32 add_time = le64_to_cpu ( params - > start_time ) ;
int rc ;
int spectrum_resp_status ;
int duration = le16_to_cpu ( params - > duration ) ;
2011-11-15 11:29:04 +01:00
if ( il_is_associated ( il ) )
2011-11-15 14:45:59 +01:00
add_time =
il_usecs_to_beacons ( il ,
le64_to_cpu ( params - > start_time ) -
il - > _3945 . last_tsf ,
2012-02-03 17:31:37 +01:00
le16_to_cpu ( il - > timing . beacon_interval ) ) ;
2011-02-21 11:11:05 -08:00
memset ( & spectrum , 0 , sizeof ( spectrum ) ) ;
spectrum . channel_count = cpu_to_le16 ( 1 ) ;
spectrum . flags =
RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK ;
spectrum . filter_flags = MEASUREMENT_FILTER_FLAG ;
cmd . len = sizeof ( spectrum ) ;
spectrum . len = cpu_to_le16 ( cmd . len - sizeof ( spectrum . len ) ) ;
2011-11-15 11:29:04 +01:00
if ( il_is_associated ( il ) )
2011-02-21 11:11:05 -08:00
spectrum . start_time =
2011-11-15 14:45:59 +01:00
il_add_beacon_time ( il , il - > _3945 . last_beacon_time , add_time ,
2012-02-03 17:31:37 +01:00
le16_to_cpu ( il - > timing . beacon_interval ) ) ;
2011-02-21 11:11:05 -08:00
else
spectrum . start_time = 0 ;
spectrum . channels [ 0 ] . duration = cpu_to_le32 ( duration * TIME_UNIT ) ;
spectrum . channels [ 0 ] . channel = params - > channel ;
spectrum . channels [ 0 ] . type = type ;
2012-02-03 17:31:37 +01:00
if ( il - > active . flags & RXON_FLG_BAND_24G_MSK )
2011-11-15 14:45:59 +01:00
spectrum . flags | =
RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK |
RXON_FLG_TGG_PROTECT_MSK ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
rc = il_send_cmd_sync ( il , & cmd ) ;
2011-02-21 11:11:05 -08:00
if ( rc )
return rc ;
2011-08-26 14:36:21 +02:00
pkt = ( struct il_rx_pkt * ) cmd . reply_page ;
2011-10-24 15:41:30 +02:00
if ( pkt - > hdr . flags & IL_CMD_FAILED_MSK ) {
2011-08-30 15:26:35 +02:00
IL_ERR ( " Bad return from N_RX_ON_ASSOC command \n " ) ;
2011-02-21 11:11:05 -08:00
rc = - EIO ;
}
spectrum_resp_status = le16_to_cpu ( pkt - > u . spectrum . status ) ;
switch ( spectrum_resp_status ) {
case 0 : /* Command will be handled */
if ( pkt - > u . spectrum . id ! = 0xff ) {
2011-11-15 11:21:01 +01:00
D_INFO ( " Replaced existing measurement: %d \n " ,
2011-11-15 14:45:59 +01:00
pkt - > u . spectrum . id ) ;
2011-10-24 16:49:25 +02:00
il - > measurement_status & = ~ MEASUREMENT_READY ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 16:49:25 +02:00
il - > measurement_status | = MEASUREMENT_ACTIVE ;
2011-02-21 11:11:05 -08:00
rc = 0 ;
break ;
case 1 : /* Command will not be handled */
rc = - EAGAIN ;
break ;
}
2011-10-24 16:49:25 +02:00
il_free_pages ( il , cmd . reply_page ) ;
2011-02-21 11:11:05 -08:00
return rc ;
}
2011-11-15 14:45:59 +01:00
static void
il3945_hdl_alive ( struct il_priv * il , struct il_rx_buf * rxb )
2011-02-21 11:11:05 -08:00
{
2011-08-26 14:36:21 +02:00
struct il_rx_pkt * pkt = rxb_addr ( rxb ) ;
2011-10-24 15:41:30 +02:00
struct il_alive_resp * palive ;
2011-02-21 11:11:05 -08:00
struct delayed_work * pwork ;
palive = & pkt - > u . alive_frame ;
2011-11-15 14:45:59 +01:00
D_INFO ( " Alive ucode status 0x%08X revision " " 0x%01X 0x%01X \n " ,
palive - > is_valid , palive - > ver_type , palive - > ver_subtype ) ;
2011-02-21 11:11:05 -08:00
if ( palive - > ver_subtype = = INITIALIZE_SUBTYPE ) {
2011-11-15 11:21:01 +01:00
D_INFO ( " Initialization Alive received. \n " ) ;
2011-10-24 16:49:25 +02:00
memcpy ( & il - > card_alive_init , & pkt - > u . alive_frame ,
2011-10-24 15:41:30 +02:00
sizeof ( struct il_alive_resp ) ) ;
2011-10-24 16:49:25 +02:00
pwork = & il - > init_alive_start ;
2011-02-21 11:11:05 -08:00
} else {
2011-11-15 11:21:01 +01:00
D_INFO ( " Runtime Alive received. \n " ) ;
2011-10-24 16:49:25 +02:00
memcpy ( & il - > card_alive , & pkt - > u . alive_frame ,
2011-10-24 15:41:30 +02:00
sizeof ( struct il_alive_resp ) ) ;
2011-10-24 16:49:25 +02:00
pwork = & il - > alive_start ;
il3945_disable_events ( il ) ;
2011-02-21 11:11:05 -08:00
}
/* We delay the ALIVE response by 5ms to
* give the HW RF Kill time to activate . . . */
if ( palive - > is_valid = = UCODE_VALID_OK )
2011-11-15 14:45:59 +01:00
queue_delayed_work ( il - > workqueue , pwork , msecs_to_jiffies ( 5 ) ) ;
2011-02-21 11:11:05 -08:00
else
2011-08-18 22:07:57 +02:00
IL_WARN ( " uCode did not respond OK. \n " ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_hdl_add_sta ( struct il_priv * il , struct il_rx_buf * rxb )
2011-02-21 11:11:05 -08:00
{
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-08-26 14:36:21 +02:00
struct il_rx_pkt * pkt = rxb_addr ( rxb ) ;
2011-02-21 11:11:05 -08:00
# endif
2011-08-30 15:26:35 +02:00
D_RX ( " Received C_ADD_STA: 0x%02X \n " , pkt - > u . status ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_hdl_beacon ( struct il_priv * il , struct il_rx_buf * rxb )
2011-02-21 11:11:05 -08:00
{
2011-08-26 14:36:21 +02:00
struct il_rx_pkt * pkt = rxb_addr ( rxb ) ;
2011-10-24 15:41:30 +02:00
struct il3945_beacon_notif * beacon = & ( pkt - > u . beacon_status ) ;
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-02-21 11:11:05 -08:00
u8 rate = beacon - > beacon_notify_hdr . rate ;
2011-11-15 14:45:59 +01:00
D_RX ( " beacon status %x retries %d iss %d " " tsf %d %d rate %d \n " ,
le32_to_cpu ( beacon - > beacon_notify_hdr . status ) & TX_STATUS_MSK ,
beacon - > beacon_notify_hdr . failure_frame ,
le32_to_cpu ( beacon - > ibss_mgr_status ) ,
le32_to_cpu ( beacon - > high_tsf ) , le32_to_cpu ( beacon - > low_tsf ) , rate ) ;
2011-02-21 11:11:05 -08:00
# endif
2011-10-24 16:49:25 +02:00
il - > ibss_manager = le32_to_cpu ( beacon - > ibss_mgr_status ) ;
2011-02-21 11:11:05 -08:00
}
/* Handle notification from uCode that card's power state is changing
* due to software , hardware , or critical temperature RFKILL */
2011-11-15 14:45:59 +01:00
static void
il3945_hdl_card_state ( struct il_priv * il , struct il_rx_buf * rxb )
2011-02-21 11:11:05 -08:00
{
2011-08-26 14:36:21 +02:00
struct il_rx_pkt * pkt = rxb_addr ( rxb ) ;
2011-02-21 11:11:05 -08:00
u32 flags = le32_to_cpu ( pkt - > u . card_state_notif . flags ) ;
2011-10-24 16:49:25 +02:00
unsigned long status = il - > status ;
2011-02-21 11:11:05 -08:00
2011-08-18 22:07:57 +02:00
IL_WARN ( " Card state received: HW:%s SW:%s \n " ,
2011-11-15 14:45:59 +01:00
( flags & HW_CARD_DISABLED ) ? " Kill " : " On " ,
( flags & SW_CARD_DISABLED ) ? " Kill " : " On " ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
_il_wr ( il , CSR_UCODE_DRV_GP1_SET , CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED ) ;
2011-02-21 11:11:05 -08:00
if ( flags & HW_CARD_DISABLED )
2012-02-13 11:23:29 +01:00
set_bit ( S_RFKILL , & il - > status ) ;
2011-02-21 11:11:05 -08:00
else
2012-02-13 11:23:29 +01:00
clear_bit ( S_RFKILL , & il - > status ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_scan_cancel ( il ) ;
2011-02-21 11:11:05 -08:00
2012-02-13 11:23:29 +01:00
if ( ( test_bit ( S_RFKILL , & status ) ! =
test_bit ( S_RFKILL , & il - > status ) ) )
2011-10-24 16:49:25 +02:00
wiphy_rfkill_set_hw_state ( il - > hw - > wiphy ,
2012-02-13 11:23:29 +01:00
test_bit ( S_RFKILL , & il - > status ) ) ;
2011-02-21 11:11:05 -08:00
else
2011-10-24 16:49:25 +02:00
wake_up ( & il - > wait_command_queue ) ;
2011-02-21 11:11:05 -08:00
}
/**
2011-08-30 15:39:42 +02:00
* il3945_setup_handlers - Initialize Rx handler callbacks
2011-02-21 11:11:05 -08:00
*
* Setup the RX handlers for each of the reply types sent from the uCode
* to the host .
*
* This function chains into the hardware specific files for them to setup
* any hardware specific handlers as well .
*/
2011-11-15 14:45:59 +01:00
static void
il3945_setup_handlers ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-08-30 15:45:31 +02:00
il - > handlers [ N_ALIVE ] = il3945_hdl_alive ;
il - > handlers [ C_ADD_STA ] = il3945_hdl_add_sta ;
il - > handlers [ N_ERROR ] = il_hdl_error ;
2011-11-15 13:16:38 +01:00
il - > handlers [ N_CHANNEL_SWITCH ] = il_hdl_csa ;
2011-11-15 14:45:59 +01:00
il - > handlers [ N_SPECTRUM_MEASUREMENT ] = il_hdl_spectrum_measurement ;
2011-11-15 13:16:38 +01:00
il - > handlers [ N_PM_SLEEP ] = il_hdl_pm_sleep ;
2011-11-15 14:45:59 +01:00
il - > handlers [ N_PM_DEBUG_STATS ] = il_hdl_pm_debug_stats ;
2011-11-15 13:16:38 +01:00
il - > handlers [ N_BEACON ] = il3945_hdl_beacon ;
2011-02-21 11:11:05 -08:00
/*
* The same handler is used for both the REPLY to a discrete
2011-08-26 15:43:47 +02:00
* stats request from the host as well as for the periodic
* stats notifications ( after received beacons ) from the uCode .
2011-02-21 11:11:05 -08:00
*/
2011-11-15 13:16:38 +01:00
il - > handlers [ C_STATS ] = il3945_hdl_c_stats ;
il - > handlers [ N_STATS ] = il3945_hdl_stats ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_setup_rx_scan_handlers ( il ) ;
2011-11-15 13:16:38 +01:00
il - > handlers [ N_CARD_STATE ] = il3945_hdl_card_state ;
2011-02-21 11:11:05 -08:00
/* Set up hardware specific Rx handlers */
2011-08-30 15:39:42 +02:00
il3945_hw_handler_setup ( il ) ;
2011-02-21 11:11:05 -08:00
}
/************************** RX-FUNCTIONS ****************************/
/*
* Rx theory of operation
*
* The host allocates 32 DMA target addresses and passes the host address
2011-08-26 16:29:35 +02:00
* to the firmware at register IL_RFDS_TBL_LOWER + N * RFD_SIZE where N is
2011-02-21 11:11:05 -08:00
* 0 to 31
*
* Rx Queue Indexes
2011-11-15 12:30:17 +01:00
* The host / firmware share two idx registers for managing the Rx buffers .
2011-02-21 11:11:05 -08:00
*
2011-11-15 12:30:17 +01:00
* The READ idx maps to the first position that the firmware may be writing
2011-02-21 11:11:05 -08:00
* to - - the driver can read up to ( but not including ) this position and get
* good data .
2011-11-15 12:30:17 +01:00
* The READ idx is managed by the firmware once the card is enabled .
2011-02-21 11:11:05 -08:00
*
2011-11-15 12:30:17 +01:00
* The WRITE idx maps to the last position the driver has read from - - the
2011-02-21 11:11:05 -08:00
* position preceding WRITE is the last slot the firmware can place a packet .
*
* The queue is empty ( no good data ) if WRITE = READ - 1 , and is full if
* WRITE = READ .
*
* During initialization , the host sets up the READ queue position to the first
2011-08-26 16:10:40 +02:00
* IDX position , and WRITE to the last ( READ - 1 wrapped )
2011-02-21 11:11:05 -08:00
*
2011-11-15 12:30:17 +01:00
* When the firmware places a packet in a buffer , it will advance the READ idx
* and fire the RX interrupt . The driver can then query the READ idx and
* process as many packets as possible , moving the WRITE idx forward as it
2011-02-21 11:11:05 -08:00
* resets the Rx queue buffers with new memory .
*
* The management in the driver is as follows :
* + A list of pre - allocated SKBs is stored in iwl - > rxq - > rx_free . When
* iwl - > rxq - > free_count drops to or below RX_LOW_WATERMARK , work is scheduled
* to replenish the iwl - > rxq - > rx_free .
2011-10-24 15:41:30 +02:00
* + In il3945_rx_replenish ( scheduled ) if ' processed ' ! = ' read ' then the
2011-08-26 16:10:40 +02:00
* iwl - > rxq is replenished and the READ IDX is updated ( updating the
2011-11-15 12:30:17 +01:00
* ' processed ' and ' read ' driver idxes as well )
2011-02-21 11:11:05 -08:00
* + A received packet is processed and handed to the kernel network stack ,
2011-11-15 12:30:17 +01:00
* detached from the iwl - > rxq . The driver ' processed ' idx is updated .
2011-02-21 11:11:05 -08:00
* + The Host / Firmware iwl - > rxq is replenished at tasklet time from the rx_free
* list . If there are no allocated buffers in iwl - > rxq - > rx_free , the READ
2011-08-26 16:10:40 +02:00
* IDX is not incremented and iwl - > status ( RX_STALLED ) is set . If there
2011-02-21 11:11:05 -08:00
* were enough free buffers and RX_STALLED is set it is cleared .
*
*
* Driver sequence :
*
2011-10-24 15:41:30 +02:00
* il3945_rx_replenish ( ) Replenishes rx_free list from rx_used , and calls
* il3945_rx_queue_restock
* il3945_rx_queue_restock ( ) Moves available buffers from rx_free into Rx
2011-02-21 11:11:05 -08:00
* queue , updates firmware pointers , and updates
2011-11-15 12:30:17 +01:00
* the WRITE idx . If insufficient rx_free buffers
2011-10-24 15:41:30 +02:00
* are available , schedules il3945_rx_replenish
2011-02-21 11:11:05 -08:00
*
* - - enable interrupts - -
2011-08-26 14:37:54 +02:00
* ISR - il3945_rx ( ) Detach il_rx_bufs from pool up to the
2011-08-26 16:10:40 +02:00
* READ IDX , detaching the SKB from the pool .
2011-02-21 11:11:05 -08:00
* Moves the packet buffer from queue to rx_used .
2011-10-24 15:41:30 +02:00
* Calls il3945_rx_queue_restock to refill any empty
2011-02-21 11:11:05 -08:00
* slots .
* . . .
*
*/
/**
2011-10-24 15:41:30 +02:00
* il3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
2011-02-21 11:11:05 -08:00
*/
2011-11-15 14:45:59 +01:00
static inline __le32
il3945_dma_addr2rbd_ptr ( struct il_priv * il , dma_addr_t dma_addr )
2011-02-21 11:11:05 -08:00
{
2011-11-15 14:45:59 +01:00
return cpu_to_le32 ( ( u32 ) dma_addr ) ;
2011-02-21 11:11:05 -08:00
}
/**
2011-10-24 15:41:30 +02:00
* il3945_rx_queue_restock - refill RX queue from pre - allocated pool
2011-02-21 11:11:05 -08:00
*
* If there are slots in the RX queue that need to be restocked ,
* and we have free pre - allocated buffers , fill the ranks as much
* as we can , pulling from rx_free .
*
2011-11-15 12:30:17 +01:00
* This moves the ' write ' idx forward to catch up with ' processed ' , and
2011-02-21 11:11:05 -08:00
* also updates the memory address in the firmware to reference the new
* target buffer .
*/
2011-11-15 14:45:59 +01:00
static void
il3945_rx_queue_restock ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_rx_queue * rxq = & il - > rxq ;
2011-02-21 11:11:05 -08:00
struct list_head * element ;
2011-08-26 14:37:54 +02:00
struct il_rx_buf * rxb ;
2011-02-21 11:11:05 -08:00
unsigned long flags ;
int write ;
spin_lock_irqsave ( & rxq - > lock , flags ) ;
write = rxq - > write & ~ 0x7 ;
2011-08-26 10:45:16 +02:00
while ( il_rx_queue_space ( rxq ) > 0 & & rxq - > free_count ) {
2011-02-21 11:11:05 -08:00
/* Get next free Rx buffer, remove from free list */
element = rxq - > rx_free . next ;
2011-08-26 14:37:54 +02:00
rxb = list_entry ( element , struct il_rx_buf , list ) ;
2011-02-21 11:11:05 -08:00
list_del ( element ) ;
/* Point to Rx buffer via next RBD in circular buffer */
2011-11-15 14:45:59 +01:00
rxq - > bd [ rxq - > write ] =
il3945_dma_addr2rbd_ptr ( il , rxb - > page_dma ) ;
2011-02-21 11:11:05 -08:00
rxq - > queue [ rxq - > write ] = rxb ;
rxq - > write = ( rxq - > write + 1 ) & RX_QUEUE_MASK ;
rxq - > free_count - - ;
}
spin_unlock_irqrestore ( & rxq - > lock , flags ) ;
/* If the pre-allocated buffer pool is dropping low, schedule to
* refill it */
if ( rxq - > free_count < = RX_LOW_WATERMARK )
2011-10-24 16:49:25 +02:00
queue_work ( il - > workqueue , & il - > rx_replenish ) ;
2011-02-21 11:11:05 -08:00
/* If we've added more space for the firmware to place data, tell it.
* Increment device ' s write pointer in multiples of 8. */
2011-08-26 10:45:16 +02:00
if ( rxq - > write_actual ! = ( rxq - > write & ~ 0x7 ) | |
abs ( rxq - > write - rxq - > read ) > 7 ) {
2011-02-21 11:11:05 -08:00
spin_lock_irqsave ( & rxq - > lock , flags ) ;
rxq - > need_update = 1 ;
spin_unlock_irqrestore ( & rxq - > lock , flags ) ;
2011-10-24 16:49:25 +02:00
il_rx_queue_update_write_ptr ( il , rxq ) ;
2011-02-21 11:11:05 -08:00
}
}
/**
2011-10-24 15:41:30 +02:00
* il3945_rx_replenish - Move all used packet from rx_used to rx_free
2011-02-21 11:11:05 -08:00
*
* When moving to rx_free an SKB is allocated for the slot .
*
2011-10-24 15:41:30 +02:00
* Also restock the Rx queue via il3945_rx_queue_restock .
2011-02-21 11:11:05 -08:00
* This is called as a scheduled work item ( except for during initialization )
*/
2011-11-15 14:45:59 +01:00
static void
il3945_rx_allocate ( struct il_priv * il , gfp_t priority )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_rx_queue * rxq = & il - > rxq ;
2011-02-21 11:11:05 -08:00
struct list_head * element ;
2011-08-26 14:37:54 +02:00
struct il_rx_buf * rxb ;
2011-02-21 11:11:05 -08:00
struct page * page ;
2013-01-30 17:08:03 +01:00
dma_addr_t page_dma ;
2011-02-21 11:11:05 -08:00
unsigned long flags ;
gfp_t gfp_mask = priority ;
while ( 1 ) {
spin_lock_irqsave ( & rxq - > lock , flags ) ;
if ( list_empty ( & rxq - > rx_used ) ) {
spin_unlock_irqrestore ( & rxq - > lock , flags ) ;
return ;
}
spin_unlock_irqrestore ( & rxq - > lock , flags ) ;
if ( rxq - > free_count > RX_LOW_WATERMARK )
gfp_mask | = __GFP_NOWARN ;
2011-10-24 16:49:25 +02:00
if ( il - > hw_params . rx_page_order > 0 )
2011-02-21 11:11:05 -08:00
gfp_mask | = __GFP_COMP ;
/* Alloc a new receive buffer */
2011-10-24 16:49:25 +02:00
page = alloc_pages ( gfp_mask , il - > hw_params . rx_page_order ) ;
2011-02-21 11:11:05 -08:00
if ( ! page ) {
if ( net_ratelimit ( ) )
2011-11-15 11:21:01 +01:00
D_INFO ( " Failed to allocate SKB buffer. \n " ) ;
2011-08-26 10:45:16 +02:00
if ( rxq - > free_count < = RX_LOW_WATERMARK & &
2011-02-21 11:11:05 -08:00
net_ratelimit ( ) )
2011-11-15 14:51:01 +01:00
IL_ERR ( " Failed to allocate SKB buffer with %0x. "
" Only %u free buffers remaining. \n " ,
priority , rxq - > free_count ) ;
2011-02-21 11:11:05 -08:00
/* We don't reschedule replenish work here -- we will
* call the restock method and if it still needs
* more buffers it will schedule replenish */
break ;
}
2013-01-30 17:08:03 +01:00
/* Get physical address of RB/SKB */
page_dma =
pci_map_page ( il - > pci_dev , page , 0 ,
PAGE_SIZE < < il - > hw_params . rx_page_order ,
PCI_DMA_FROMDEVICE ) ;
if ( unlikely ( pci_dma_mapping_error ( il - > pci_dev , page_dma ) ) ) {
__free_pages ( page , il - > hw_params . rx_page_order ) ;
break ;
}
2011-02-21 11:11:05 -08:00
spin_lock_irqsave ( & rxq - > lock , flags ) ;
2013-01-30 17:08:03 +01:00
2011-02-21 11:11:05 -08:00
if ( list_empty ( & rxq - > rx_used ) ) {
spin_unlock_irqrestore ( & rxq - > lock , flags ) ;
2013-01-30 17:08:03 +01:00
pci_unmap_page ( il - > pci_dev , page_dma ,
PAGE_SIZE < < il - > hw_params . rx_page_order ,
PCI_DMA_FROMDEVICE ) ;
2011-10-24 16:49:25 +02:00
__free_pages ( page , il - > hw_params . rx_page_order ) ;
2011-02-21 11:11:05 -08:00
return ;
}
2013-01-30 17:08:03 +01:00
2011-02-21 11:11:05 -08:00
element = rxq - > rx_used . next ;
2011-08-26 14:37:54 +02:00
rxb = list_entry ( element , struct il_rx_buf , list ) ;
2011-02-21 11:11:05 -08:00
list_del ( element ) ;
rxb - > page = page ;
2013-01-30 17:08:03 +01:00
rxb - > page_dma = page_dma ;
2011-02-21 11:11:05 -08:00
list_add_tail ( & rxb - > list , & rxq - > rx_free ) ;
rxq - > free_count + + ;
2011-10-24 16:49:25 +02:00
il - > alloc_rxb_page + + ;
2011-02-21 11:11:05 -08:00
spin_unlock_irqrestore ( & rxq - > lock , flags ) ;
}
}
2011-11-15 14:45:59 +01:00
void
il3945_rx_queue_reset ( struct il_priv * il , struct il_rx_queue * rxq )
2011-02-21 11:11:05 -08:00
{
unsigned long flags ;
int i ;
spin_lock_irqsave ( & rxq - > lock , flags ) ;
INIT_LIST_HEAD ( & rxq - > rx_free ) ;
INIT_LIST_HEAD ( & rxq - > rx_used ) ;
/* Fill the rx_used queue with _all_ of the Rx buffers */
for ( i = 0 ; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE ; i + + ) {
/* In the reset function, these buffers may have been allocated
* to an SKB , so we need to unmap and free potential storage */
if ( rxq - > pool [ i ] . page ! = NULL ) {
2011-10-24 16:49:25 +02:00
pci_unmap_page ( il - > pci_dev , rxq - > pool [ i ] . page_dma ,
2011-11-15 14:45:59 +01:00
PAGE_SIZE < < il - > hw_params . rx_page_order ,
PCI_DMA_FROMDEVICE ) ;
2011-10-24 16:49:25 +02:00
__il_free_pages ( il , rxq - > pool [ i ] . page ) ;
2011-02-21 11:11:05 -08:00
rxq - > pool [ i ] . page = NULL ;
}
list_add_tail ( & rxq - > pool [ i ] . list , & rxq - > rx_used ) ;
}
/* Set us so that we have processed and used all buffers, but have
* not restocked the Rx queue with fresh buffers */
rxq - > read = rxq - > write = 0 ;
rxq - > write_actual = 0 ;
rxq - > free_count = 0 ;
spin_unlock_irqrestore ( & rxq - > lock , flags ) ;
}
2011-11-15 14:45:59 +01:00
void
il3945_rx_replenish ( void * data )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = data ;
2011-02-21 11:11:05 -08:00
unsigned long flags ;
2011-10-24 16:49:25 +02:00
il3945_rx_allocate ( il , GFP_KERNEL ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
il3945_rx_queue_restock ( il ) ;
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_rx_replenish_now ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
il3945_rx_allocate ( il , GFP_ATOMIC ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_rx_queue_restock ( il ) ;
2011-02-21 11:11:05 -08:00
}
/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
* If an SKB has been detached , the POOL needs to have its SKB set to NULL
* This free routine walks the list of POOL entries and if SKB is set to
* non NULL it is unmapped and freed
*/
2011-11-15 14:45:59 +01:00
static void
il3945_rx_queue_free ( struct il_priv * il , struct il_rx_queue * rxq )
2011-02-21 11:11:05 -08:00
{
int i ;
for ( i = 0 ; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS ; i + + ) {
if ( rxq - > pool [ i ] . page ! = NULL ) {
2011-10-24 16:49:25 +02:00
pci_unmap_page ( il - > pci_dev , rxq - > pool [ i ] . page_dma ,
2011-11-15 14:45:59 +01:00
PAGE_SIZE < < il - > hw_params . rx_page_order ,
PCI_DMA_FROMDEVICE ) ;
2011-10-24 16:49:25 +02:00
__il_free_pages ( il , rxq - > pool [ i ] . page ) ;
2011-02-21 11:11:05 -08:00
rxq - > pool [ i ] . page = NULL ;
}
}
2011-10-24 16:49:25 +02:00
dma_free_coherent ( & il - > pci_dev - > dev , 4 * RX_QUEUE_SIZE , rxq - > bd ,
2011-02-21 11:11:05 -08:00
rxq - > bd_dma ) ;
2011-10-24 16:49:25 +02:00
dma_free_coherent ( & il - > pci_dev - > dev , sizeof ( struct il_rb_status ) ,
2011-02-21 11:11:05 -08:00
rxq - > rb_stts , rxq - > rb_stts_dma ) ;
rxq - > bd = NULL ;
2011-11-15 14:45:59 +01:00
rxq - > rb_stts = NULL ;
2011-02-21 11:11:05 -08:00
}
/* Convert linear signal-to-noise ratio into dB */
static u8 ratio2dB [ 100 ] = {
/* 0 1 2 3 4 5 6 7 8 9 */
2011-11-15 14:45:59 +01:00
0 , 0 , 6 , 10 , 12 , 14 , 16 , 17 , 18 , 19 , /* 00 - 09 */
20 , 21 , 22 , 22 , 23 , 23 , 24 , 25 , 26 , 26 , /* 10 - 19 */
26 , 26 , 26 , 27 , 27 , 28 , 28 , 28 , 29 , 29 , /* 20 - 29 */
29 , 30 , 30 , 30 , 31 , 31 , 31 , 31 , 32 , 32 , /* 30 - 39 */
32 , 32 , 32 , 33 , 33 , 33 , 33 , 33 , 34 , 34 , /* 40 - 49 */
34 , 34 , 34 , 34 , 35 , 35 , 35 , 35 , 35 , 35 , /* 50 - 59 */
36 , 36 , 36 , 36 , 36 , 36 , 36 , 37 , 37 , 37 , /* 60 - 69 */
37 , 37 , 37 , 37 , 37 , 38 , 38 , 38 , 38 , 38 , /* 70 - 79 */
38 , 38 , 38 , 38 , 38 , 39 , 39 , 39 , 39 , 39 , /* 80 - 89 */
39 , 39 , 39 , 39 , 39 , 40 , 40 , 40 , 40 , 40 /* 90 - 99 */
2011-02-21 11:11:05 -08:00
} ;
/* Calculates a relative dB value from a ratio of linear
* ( i . e . not dB ) signal levels .
* Conversion assumes that levels are voltages ( 20 * log ) , not powers ( 10 * log ) . */
2011-11-15 14:45:59 +01:00
int
il3945_calc_db_from_ratio ( int sig_ratio )
2011-02-21 11:11:05 -08:00
{
/* 1000:1 or higher just report as 60 dB */
if ( sig_ratio > = 1000 )
return 60 ;
/* 100:1 or higher, divide by 10 and use table,
* add 20 dB to make up for divide by 10 */
if ( sig_ratio > = 100 )
2011-11-15 14:45:59 +01:00
return 20 + ( int ) ratio2dB [ sig_ratio / 10 ] ;
2011-02-21 11:11:05 -08:00
/* We shouldn't see this */
if ( sig_ratio < 1 )
return 0 ;
/* Use table for ratios 1:1 - 99:1 */
return ( int ) ratio2dB [ sig_ratio ] ;
}
/**
2011-10-24 15:41:30 +02:00
* il3945_rx_handle - Main entry function for receiving responses from uCode
2011-02-21 11:11:05 -08:00
*
2011-08-30 15:39:42 +02:00
* Uses the il - > handlers callback function array to invoke
2011-02-21 11:11:05 -08:00
* the appropriate handlers , including command responses ,
* frame - received notifications , and other notifications .
*/
2011-11-15 14:45:59 +01:00
static void
il3945_rx_handle ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-08-26 14:37:54 +02:00
struct il_rx_buf * rxb ;
2011-08-26 14:36:21 +02:00
struct il_rx_pkt * pkt ;
2011-10-24 16:49:25 +02:00
struct il_rx_queue * rxq = & il - > rxq ;
2011-02-21 11:11:05 -08:00
u32 r , i ;
int reclaim ;
unsigned long flags ;
u8 fill_rx = 0 ;
u32 count = 8 ;
int total_empty = 0 ;
2011-11-15 12:30:17 +01:00
/* uCode's read idx (stored in shared DRAM) indicates the last Rx
2011-02-21 11:11:05 -08:00
* buffer that the driver may process ( last buffer filled by ucode ) . */
2011-11-15 14:45:59 +01:00
r = le16_to_cpu ( rxq - > rb_stts - > closed_rb_num ) & 0x0FFF ;
2011-02-21 11:11:05 -08:00
i = rxq - > read ;
/* calculate total frames need to be restock after handling RX */
total_empty = r - rxq - > write_actual ;
if ( total_empty < 0 )
total_empty + = RX_QUEUE_SIZE ;
if ( total_empty > ( RX_QUEUE_SIZE / 2 ) )
fill_rx = 1 ;
/* Rx interrupt, but nothing sent from uCode */
if ( i = = r )
2011-11-15 11:21:01 +01:00
D_RX ( " r = %d, i = %d \n " , r , i ) ;
2011-02-21 11:11:05 -08:00
while ( i ! = r ) {
int len ;
rxb = rxq - > queue [ i ] ;
/* If an RXB doesn't have a Rx queue slot associated with it,
* then a bug has been introduced in the queue refilling
* routines - - catch it here */
BUG_ON ( rxb = = NULL ) ;
rxq - > queue [ i ] = NULL ;
2011-10-24 16:49:25 +02:00
pci_unmap_page ( il - > pci_dev , rxb - > page_dma ,
PAGE_SIZE < < il - > hw_params . rx_page_order ,
2011-02-21 11:11:05 -08:00
PCI_DMA_FROMDEVICE ) ;
pkt = rxb_addr ( rxb ) ;
2011-08-31 13:23:20 +02:00
len = le32_to_cpu ( pkt - > len_n_flags ) & IL_RX_FRAME_SIZE_MSK ;
2011-11-15 14:45:59 +01:00
len + = sizeof ( u32 ) ; /* account for status word */
2011-02-21 11:11:05 -08:00
2014-02-19 09:15:10 +01:00
reclaim = il_need_reclaim ( il , pkt ) ;
2011-02-21 11:11:05 -08:00
/* Based on type of command response or notification,
* handle those that need handling via function in
2011-08-30 15:39:42 +02:00
* handlers table . See il3945_setup_handlers ( ) */
if ( il - > handlers [ pkt - > hdr . cmd ] ) {
2011-11-15 11:21:01 +01:00
D_RX ( " r = %d, i = %d, %s, 0x%02x \n " , r , i ,
2011-11-15 14:45:59 +01:00
il_get_cmd_string ( pkt - > hdr . cmd ) , pkt - > hdr . cmd ) ;
2011-08-30 15:39:42 +02:00
il - > isr_stats . handlers [ pkt - > hdr . cmd ] + + ;
il - > handlers [ pkt - > hdr . cmd ] ( il , rxb ) ;
2011-02-21 11:11:05 -08:00
} else {
/* No handling needed */
2011-11-15 14:45:59 +01:00
D_RX ( " r %d i %d No handler needed for %s, 0x%02x \n " , r ,
i , il_get_cmd_string ( pkt - > hdr . cmd ) , pkt - > hdr . cmd ) ;
2011-02-21 11:11:05 -08:00
}
/*
* XXX : After here , we should always check rxb - > page
* against NULL before touching it or its virtual
2011-08-30 15:39:42 +02:00
* memory ( pkt ) . Because some handler might have
2011-02-21 11:11:05 -08:00
* already taken or freed the pages .
*/
if ( reclaim ) {
/* Invoke any callbacks, transfer the buffer to caller,
2011-10-24 15:41:30 +02:00
* and fire off the ( possibly ) blocking il_send_cmd ( )
2011-02-21 11:11:05 -08:00
* as we reclaim the driver command queue */
if ( rxb - > page )
2011-10-24 16:49:25 +02:00
il_tx_cmd_complete ( il , rxb ) ;
2011-02-21 11:11:05 -08:00
else
2011-08-18 22:07:57 +02:00
IL_WARN ( " Claim null rxb? \n " ) ;
2011-02-21 11:11:05 -08:00
}
/* Reuse the page if possible. For notification packets and
* SKBs that fail to Rx correctly , add them back into the
* rx_free list for reuse later . */
spin_lock_irqsave ( & rxq - > lock , flags ) ;
if ( rxb - > page ! = NULL ) {
2011-11-15 14:45:59 +01:00
rxb - > page_dma =
pci_map_page ( il - > pci_dev , rxb - > page , 0 ,
PAGE_SIZE < < il - > hw_params .
rx_page_order , PCI_DMA_FROMDEVICE ) ;
2013-01-30 17:08:03 +01:00
if ( unlikely ( pci_dma_mapping_error ( il - > pci_dev ,
rxb - > page_dma ) ) ) {
__il_free_pages ( il , rxb - > page ) ;
rxb - > page = NULL ;
list_add_tail ( & rxb - > list , & rxq - > rx_used ) ;
} else {
list_add_tail ( & rxb - > list , & rxq - > rx_free ) ;
rxq - > free_count + + ;
}
2011-02-21 11:11:05 -08:00
} else
list_add_tail ( & rxb - > list , & rxq - > rx_used ) ;
spin_unlock_irqrestore ( & rxq - > lock , flags ) ;
i = ( i + 1 ) & RX_QUEUE_MASK ;
/* If there are a lot of unused frames,
* restock the Rx queue so ucode won ' t assert . */
if ( fill_rx ) {
count + + ;
if ( count > = 8 ) {
rxq - > read = i ;
2011-10-24 16:49:25 +02:00
il3945_rx_replenish_now ( il ) ;
2011-02-21 11:11:05 -08:00
count = 0 ;
}
}
}
/* Backtrack one entry */
rxq - > read = i ;
if ( fill_rx )
2011-10-24 16:49:25 +02:00
il3945_rx_replenish_now ( il ) ;
2011-02-21 11:11:05 -08:00
else
2011-10-24 16:49:25 +02:00
il3945_rx_queue_restock ( il ) ;
2011-02-21 11:11:05 -08:00
}
/* call this function to flush any scheduled tasklet */
2011-11-15 14:45:59 +01:00
static inline void
il3945_synchronize_irq ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-11-15 14:45:59 +01:00
/* wait to make sure we flush pending tasklet */
2011-10-24 16:49:25 +02:00
synchronize_irq ( il - > pci_dev - > irq ) ;
tasklet_kill ( & il - > irq_tasklet ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static const char *
il3945_desc_lookup ( int i )
2011-02-21 11:11:05 -08:00
{
switch ( i ) {
case 1 :
return " FAIL " ;
case 2 :
return " BAD_PARAM " ;
case 3 :
return " BAD_CHECKSUM " ;
case 4 :
return " NMI_INTERRUPT " ;
case 5 :
return " SYSASSERT " ;
case 6 :
return " FATAL_ERROR " ;
}
return " UNKNOWN " ;
}
# define ERROR_START_OFFSET (1 * sizeof(u32))
# define ERROR_ELEM_SIZE (7 * sizeof(u32))
2011-11-15 14:45:59 +01:00
void
il3945_dump_nic_error_log ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
u32 i ;
u32 desc , time , count , base , data1 ;
u32 blink1 , blink2 , ilink1 , ilink2 ;
2011-10-24 16:49:25 +02:00
base = le32_to_cpu ( il - > card_alive . error_event_table_ptr ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
if ( ! il3945_hw_valid_rtc_data_addr ( base ) ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Not valid error log pointer 0x%08X \n " , base ) ;
2011-02-21 11:11:05 -08:00
return ;
}
2011-10-24 16:49:25 +02:00
count = il_read_targ_mem ( il , base ) ;
2011-02-21 11:11:05 -08:00
if ( ERROR_START_OFFSET < = count * ERROR_ELEM_SIZE ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Start IWL Error Log Dump: \n " ) ;
2011-11-15 14:45:59 +01:00
IL_ERR ( " Status: 0x%08lX, count: %d \n " , il - > status , count ) ;
2011-02-21 11:11:05 -08:00
}
2011-08-18 22:07:57 +02:00
IL_ERR ( " Desc Time asrtPC blink2 "
2011-11-15 14:45:59 +01:00
" ilink1 nmiPC Line \n " ) ;
2011-02-21 11:11:05 -08:00
for ( i = ERROR_START_OFFSET ;
i < ( count * ERROR_ELEM_SIZE ) + ERROR_START_OFFSET ;
i + = ERROR_ELEM_SIZE ) {
2011-10-24 16:49:25 +02:00
desc = il_read_targ_mem ( il , base + i ) ;
2011-11-15 14:45:59 +01:00
time = il_read_targ_mem ( il , base + i + 1 * sizeof ( u32 ) ) ;
blink1 = il_read_targ_mem ( il , base + i + 2 * sizeof ( u32 ) ) ;
blink2 = il_read_targ_mem ( il , base + i + 3 * sizeof ( u32 ) ) ;
ilink1 = il_read_targ_mem ( il , base + i + 4 * sizeof ( u32 ) ) ;
ilink2 = il_read_targ_mem ( il , base + i + 5 * sizeof ( u32 ) ) ;
data1 = il_read_targ_mem ( il , base + i + 6 * sizeof ( u32 ) ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
IL_ERR ( " %-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u \n \n " ,
il3945_desc_lookup ( desc ) , desc , time , blink1 , blink2 ,
ilink1 , ilink2 , data1 ) ;
2011-02-21 11:11:05 -08:00
}
}
2011-11-15 14:45:59 +01:00
static void
il3945_irq_tasklet ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
u32 inta , handled = 0 ;
u32 inta_fh ;
unsigned long flags ;
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-02-21 11:11:05 -08:00
u32 inta_mask ;
# endif
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
/* Ack/clear/reset pending uCode interrupts.
* Note : Some bits in CSR_INT are " OR " of bits in CSR_FH_INT_STATUS ,
* and will clear only when CSR_FH_INT_STATUS gets cleared . */
2011-08-24 15:14:03 +02:00
inta = _il_rd ( il , CSR_INT ) ;
_il_wr ( il , CSR_INT , inta ) ;
2011-02-21 11:11:05 -08:00
/* Ack/clear/reset pending flow-handler (DMA) interrupts.
* Any new interrupts that happen after this , either while we ' re
* in this tasklet , or later , will show up in next ISR / tasklet . */
2011-08-24 15:14:03 +02:00
inta_fh = _il_rd ( il , CSR_FH_INT_STATUS ) ;
_il_wr ( il , CSR_FH_INT_STATUS , inta_fh ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-10-24 16:49:25 +02:00
if ( il_get_debug_level ( il ) & IL_DL_ISR ) {
2011-02-21 11:11:05 -08:00
/* just for debug */
2011-08-24 15:14:03 +02:00
inta_mask = _il_rd ( il , CSR_INT_MASK ) ;
2011-11-15 14:45:59 +01:00
D_ISR ( " inta 0x%08x, enabled 0x%08x, fh 0x%08x \n " , inta ,
inta_mask , inta_fh ) ;
2011-02-21 11:11:05 -08:00
}
# endif
2011-10-24 16:49:25 +02:00
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
* atomic , make sure that inta covers all the interrupts that
* we ' ve discovered , even if FH interrupt came in just after
* reading CSR_INT . */
if ( inta_fh & CSR39_FH_INT_RX_MASK )
inta | = CSR_INT_BIT_FH_RX ;
if ( inta_fh & CSR39_FH_INT_TX_MASK )
inta | = CSR_INT_BIT_FH_TX ;
/* Now service all interrupt bits discovered above. */
if ( inta & CSR_INT_BIT_HW_ERR ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Hardware error detected. Restarting. \n " ) ;
2011-02-21 11:11:05 -08:00
/* Tell the device to stop sending interrupts */
2011-10-24 16:49:25 +02:00
il_disable_interrupts ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > isr_stats . hw + + ;
il_irq_handle_error ( il ) ;
2011-02-21 11:11:05 -08:00
handled | = CSR_INT_BIT_HW_ERR ;
return ;
}
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-10-24 16:49:25 +02:00
if ( il_get_debug_level ( il ) & ( IL_DL_ISR ) ) {
2011-02-21 11:11:05 -08:00
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if ( inta & CSR_INT_BIT_SCD ) {
2011-11-15 11:21:01 +01:00
D_ISR ( " Scheduler finished to transmit "
2011-11-15 14:45:59 +01:00
" the frame/frames. \n " ) ;
2011-10-24 16:49:25 +02:00
il - > isr_stats . sch + + ;
2011-02-21 11:11:05 -08:00
}
/* Alive notification via Rx interrupt will do the real work */
if ( inta & CSR_INT_BIT_ALIVE ) {
2011-11-15 11:21:01 +01:00
D_ISR ( " Alive interrupt \n " ) ;
2011-10-24 16:49:25 +02:00
il - > isr_stats . alive + + ;
2011-02-21 11:11:05 -08:00
}
}
# endif
/* Safely ignore these bits for debug checks below */
inta & = ~ ( CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE ) ;
/* Error detected by uCode */
if ( inta & CSR_INT_BIT_SW_ERR ) {
2011-11-15 14:45:59 +01:00
IL_ERR ( " Microcode SW error detected. " " Restarting 0x%X. \n " ,
inta ) ;
2011-10-24 16:49:25 +02:00
il - > isr_stats . sw + + ;
il_irq_handle_error ( il ) ;
2011-02-21 11:11:05 -08:00
handled | = CSR_INT_BIT_SW_ERR ;
}
/* uCode wakes up after power-down sleep */
if ( inta & CSR_INT_BIT_WAKEUP ) {
2011-11-15 11:21:01 +01:00
D_ISR ( " Wakeup interrupt \n " ) ;
2011-10-24 16:49:25 +02:00
il_rx_queue_update_write_ptr ( il , & il - > rxq ) ;
2014-02-19 09:15:09 +01:00
spin_lock_irqsave ( & il - > lock , flags ) ;
2011-10-24 16:49:25 +02:00
il_txq_update_write_ptr ( il , & il - > txq [ 0 ] ) ;
il_txq_update_write_ptr ( il , & il - > txq [ 1 ] ) ;
il_txq_update_write_ptr ( il , & il - > txq [ 2 ] ) ;
il_txq_update_write_ptr ( il , & il - > txq [ 3 ] ) ;
il_txq_update_write_ptr ( il , & il - > txq [ 4 ] ) ;
2014-02-19 09:15:09 +01:00
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-10-24 16:49:25 +02:00
il - > isr_stats . wakeup + + ;
2011-02-21 11:11:05 -08:00
handled | = CSR_INT_BIT_WAKEUP ;
}
/* All uCode command responses, including Tx command responses,
* Rx " responses " ( frame - received notification ) , and other
* notifications from uCode come through here */
if ( inta & ( CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX ) ) {
2011-10-24 16:49:25 +02:00
il3945_rx_handle ( il ) ;
il - > isr_stats . rx + + ;
2011-02-21 11:11:05 -08:00
handled | = ( CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX ) ;
}
if ( inta & CSR_INT_BIT_FH_TX ) {
2011-11-15 11:21:01 +01:00
D_ISR ( " Tx interrupt \n " ) ;
2011-10-24 16:49:25 +02:00
il - > isr_stats . tx + + ;
2011-02-21 11:11:05 -08:00
2011-08-24 15:14:03 +02:00
_il_wr ( il , CSR_FH_INT_STATUS , ( 1 < < 6 ) ) ;
2011-11-15 14:45:59 +01:00
il_wr ( il , FH39_TCSR_CREDIT ( FH39_SRVC_CHNL ) , 0x0 ) ;
2011-02-21 11:11:05 -08:00
handled | = CSR_INT_BIT_FH_TX ;
}
if ( inta & ~ handled ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Unhandled INTA bits 0x%08x \n " , inta & ~ handled ) ;
2011-10-24 16:49:25 +02:00
il - > isr_stats . unhandled + + ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 16:49:25 +02:00
if ( inta & ~ il - > inta_mask ) {
2011-08-18 22:07:57 +02:00
IL_WARN ( " Disabled INTA bits 0x%08x were pending \n " ,
2011-11-15 14:45:59 +01:00
inta & ~ il - > inta_mask ) ;
2011-08-31 14:14:18 +02:00
IL_WARN ( " with inta_fh = 0x%08x \n " , inta_fh ) ;
2011-02-21 11:11:05 -08:00
}
/* Re-enable all interrupts */
/* only Re-enable if disabled by irq */
2011-11-15 13:09:01 +01:00
if ( test_bit ( S_INT_ENABLED , & il - > status ) )
2011-10-24 16:49:25 +02:00
il_enable_interrupts ( il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-10-24 16:49:25 +02:00
if ( il_get_debug_level ( il ) & ( IL_DL_ISR ) ) {
2011-08-24 15:14:03 +02:00
inta = _il_rd ( il , CSR_INT ) ;
inta_mask = _il_rd ( il , CSR_INT_MASK ) ;
inta_fh = _il_rd ( il , CSR_FH_INT_STATUS ) ;
2011-11-15 11:21:01 +01:00
D_ISR ( " End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
2011-11-15 14:45:59 +01:00
" flags 0x%08lx \n " , inta , inta_mask , inta_fh , flags ) ;
2011-02-21 11:11:05 -08:00
}
# endif
}
2011-11-15 14:45:59 +01:00
static int
il3945_get_channels_for_scan ( struct il_priv * il , enum ieee80211_band band ,
u8 is_active , u8 n_probes ,
struct il3945_scan_channel * scan_ch ,
struct ieee80211_vif * vif )
2011-02-21 11:11:05 -08:00
{
struct ieee80211_channel * chan ;
const struct ieee80211_supported_band * sband ;
2011-10-24 15:41:30 +02:00
const struct il_channel_info * ch_info ;
2011-02-21 11:11:05 -08:00
u16 passive_dwell = 0 ;
u16 active_dwell = 0 ;
int added , i ;
2011-10-24 16:49:25 +02:00
sband = il_get_hw_mode ( il , band ) ;
2011-02-21 11:11:05 -08:00
if ( ! sband )
return 0 ;
2011-10-24 16:49:25 +02:00
active_dwell = il_get_active_dwell_time ( il , band , n_probes ) ;
passive_dwell = il_get_passive_dwell_time ( il , band , vif ) ;
2011-02-21 11:11:05 -08:00
if ( passive_dwell < = active_dwell )
passive_dwell = active_dwell + 1 ;
2011-10-24 16:49:25 +02:00
for ( i = 0 , added = 0 ; i < il - > scan_request - > n_channels ; i + + ) {
chan = il - > scan_request - > channels [ i ] ;
2011-02-21 11:11:05 -08:00
if ( chan - > band ! = band )
continue ;
scan_ch - > channel = chan - > hw_value ;
2011-11-15 14:45:59 +01:00
ch_info = il_get_channel_info ( il , band , scan_ch - > channel ) ;
2011-10-24 15:41:30 +02:00
if ( ! il_is_channel_valid ( ch_info ) ) {
2011-11-15 14:45:59 +01:00
D_SCAN ( " Channel %d is INVALID for this band. \n " ,
2011-02-21 11:27:26 -08:00
scan_ch - > channel ) ;
2011-02-21 11:11:05 -08:00
continue ;
}
scan_ch - > active_dwell = cpu_to_le16 ( active_dwell ) ;
scan_ch - > passive_dwell = cpu_to_le16 ( passive_dwell ) ;
/* If passive , set up for auto-switch
* and use long active_dwell time .
*/
2011-10-24 15:41:30 +02:00
if ( ! is_active | | il_is_channel_passive ( ch_info ) | |
2013-10-21 19:22:25 +02:00
( chan - > flags & IEEE80211_CHAN_NO_IR ) ) {
2011-02-21 11:11:05 -08:00
scan_ch - > type = 0 ; /* passive */
2011-10-24 16:49:25 +02:00
if ( IL_UCODE_API ( il - > ucode_ver ) = = 1 )
2011-11-15 14:45:59 +01:00
scan_ch - > active_dwell =
cpu_to_le16 ( passive_dwell - 1 ) ;
2011-02-21 11:11:05 -08:00
} else {
scan_ch - > type = 1 ; /* active */
}
/* Set direct probe bits. These may be used both for active
* scan channels ( probes gets sent right away ) ,
* or for passive channels ( probes get se sent only after
* hearing clear Rx packet ) . */
2011-10-24 16:49:25 +02:00
if ( IL_UCODE_API ( il - > ucode_ver ) > = 2 ) {
2011-02-21 11:11:05 -08:00
if ( n_probes )
2011-11-15 11:25:42 +01:00
scan_ch - > type | = IL39_SCAN_PROBE_MASK ( n_probes ) ;
2011-02-21 11:11:05 -08:00
} else {
/* uCode v1 does not allow setting direct probe bits on
* passive channel . */
if ( ( scan_ch - > type & 1 ) & & n_probes )
2011-11-15 11:25:42 +01:00
scan_ch - > type | = IL39_SCAN_PROBE_MASK ( n_probes ) ;
2011-02-21 11:11:05 -08:00
}
/* Set txpower levels to defaults */
scan_ch - > tpc . dsp_atten = 110 ;
/* scan_pwr_info->tpc.dsp_atten; */
/*scan_pwr_info->tpc.tx_gain; */
if ( band = = IEEE80211_BAND_5GHZ )
scan_ch - > tpc . tx_gain = ( ( 1 < < 5 ) | ( 3 < < 3 ) ) | 3 ;
else {
scan_ch - > tpc . tx_gain = ( ( 1 < < 5 ) | ( 5 < < 3 ) ) ;
/* NOTE: if we were doing 6Mb OFDM for scans we'd use
* power level :
* scan_ch - > tpc . tx_gain = ( ( 1 < < 5 ) | ( 2 < < 3 ) ) | 3 ;
*/
}
2011-11-15 14:45:59 +01:00
D_SCAN ( " Scanning %d [%s %d] \n " , scan_ch - > channel ,
( scan_ch - > type & 1 ) ? " ACTIVE " : " PASSIVE " ,
( scan_ch - > type & 1 ) ? active_dwell : passive_dwell ) ;
2011-02-21 11:11:05 -08:00
scan_ch + + ;
added + + ;
}
2011-11-15 11:21:01 +01:00
D_SCAN ( " total channels to scan %d \n " , added ) ;
2011-02-21 11:11:05 -08:00
return added ;
}
2011-11-15 14:45:59 +01:00
static void
il3945_init_hw_rates ( struct il_priv * il , struct ieee80211_rate * rates )
2011-02-21 11:11:05 -08:00
{
int i ;
2011-08-26 16:07:43 +02:00
for ( i = 0 ; i < RATE_COUNT_LEGACY ; i + + ) {
2011-10-24 15:41:30 +02:00
rates [ i ] . bitrate = il3945_rates [ i ] . ieee * 5 ;
2011-11-15 14:45:59 +01:00
rates [ i ] . hw_value = i ; /* Rate scaling will work on idxes */
2011-02-21 11:11:05 -08:00
rates [ i ] . hw_value_short = i ;
rates [ i ] . flags = 0 ;
2011-11-15 11:25:42 +01:00
if ( i > IL39_LAST_OFDM_RATE | | i < IL_FIRST_OFDM_RATE ) {
2011-02-21 11:11:05 -08:00
/*
* If CCK ! = 1 M then set short preamble rate flag .
*/
2011-11-15 14:45:59 +01:00
rates [ i ] . flags | =
( il3945_rates [ i ] . plcp = =
10 ) ? 0 : IEEE80211_RATE_SHORT_PREAMBLE ;
2011-02-21 11:11:05 -08:00
}
}
}
/******************************************************************************
*
* uCode download functions
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-11-15 14:45:59 +01:00
static void
il3945_dealloc_ucode_pci ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
il_free_fw_desc ( il - > pci_dev , & il - > ucode_code ) ;
il_free_fw_desc ( il - > pci_dev , & il - > ucode_data ) ;
il_free_fw_desc ( il - > pci_dev , & il - > ucode_data_backup ) ;
il_free_fw_desc ( il - > pci_dev , & il - > ucode_init ) ;
il_free_fw_desc ( il - > pci_dev , & il - > ucode_init_data ) ;
il_free_fw_desc ( il - > pci_dev , & il - > ucode_boot ) ;
2011-02-21 11:11:05 -08:00
}
/**
2011-10-24 15:41:30 +02:00
* il3945_verify_inst_full - verify runtime uCode image in card vs . host ,
2011-02-21 11:11:05 -08:00
* looking at all data .
*/
2011-11-15 14:45:59 +01:00
static int
il3945_verify_inst_full ( struct il_priv * il , __le32 * image , u32 len )
2011-02-21 11:11:05 -08:00
{
u32 val ;
u32 save_len = len ;
int rc = 0 ;
u32 errcnt ;
2011-11-15 11:21:01 +01:00
D_INFO ( " ucode inst image size is %u \n " , len ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
il_wr ( il , HBUS_TARG_MEM_RADDR , IL39_RTC_INST_LOWER_BOUND ) ;
2011-02-21 11:11:05 -08:00
errcnt = 0 ;
for ( ; len > 0 ; len - = sizeof ( u32 ) , image + + ) {
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
2011-10-24 15:41:30 +02:00
* if IL_DL_IO is set */
2011-08-24 15:46:03 +02:00
val = _il_rd ( il , HBUS_TARG_MEM_RDAT ) ;
2011-02-21 11:11:05 -08:00
if ( val ! = le32_to_cpu ( * image ) ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " uCode INST section is invalid at "
2011-11-15 14:45:59 +01:00
" offset 0x%x, is 0x%x, s/b 0x%x \n " ,
save_len - len , val , le32_to_cpu ( * image ) ) ;
2011-02-21 11:11:05 -08:00
rc = - EIO ;
errcnt + + ;
if ( errcnt > = 20 )
break ;
}
}
if ( ! errcnt )
2011-11-15 14:45:59 +01:00
D_INFO ( " ucode image in INSTRUCTION memory is good \n " ) ;
2011-02-21 11:11:05 -08:00
return rc ;
}
/**
2011-10-24 15:41:30 +02:00
* il3945_verify_inst_sparse - verify runtime uCode image in card vs . host ,
2011-02-21 11:11:05 -08:00
* using sample data 100 bytes apart . If these sample points are good ,
* it ' s a pretty good bet that everything between them is good , too .
*/
2011-11-15 14:45:59 +01:00
static int
il3945_verify_inst_sparse ( struct il_priv * il , __le32 * image , u32 len )
2011-02-21 11:11:05 -08:00
{
u32 val ;
int rc = 0 ;
u32 errcnt = 0 ;
u32 i ;
2011-11-15 11:21:01 +01:00
D_INFO ( " ucode inst image size is %u \n " , len ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
for ( i = 0 ; i < len ; i + = 100 , image + = 100 / sizeof ( u32 ) ) {
2011-02-21 11:11:05 -08:00
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
2011-10-24 15:41:30 +02:00
* if IL_DL_IO is set */
2011-11-15 14:45:59 +01:00
il_wr ( il , HBUS_TARG_MEM_RADDR , i + IL39_RTC_INST_LOWER_BOUND ) ;
2011-08-24 15:46:03 +02:00
val = _il_rd ( il , HBUS_TARG_MEM_RDAT ) ;
2011-02-21 11:11:05 -08:00
if ( val ! = le32_to_cpu ( * image ) ) {
2011-11-15 14:45:59 +01:00
#if 0 /* Enable this if you want to see details */
2011-08-18 22:07:57 +02:00
IL_ERR ( " uCode INST section is invalid at "
2011-11-15 14:45:59 +01:00
" offset 0x%x, is 0x%x, s/b 0x%x \n " , i , val ,
* image ) ;
2011-02-21 11:11:05 -08:00
# endif
rc = - EIO ;
errcnt + + ;
if ( errcnt > = 3 )
break ;
}
}
return rc ;
}
/**
2011-10-24 15:41:30 +02:00
* il3945_verify_ucode - determine which instruction image is in SRAM ,
2011-02-21 11:11:05 -08:00
* and verify its contents
*/
2011-11-15 14:45:59 +01:00
static int
il3945_verify_ucode ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
__le32 * image ;
u32 len ;
int rc = 0 ;
/* Try bootstrap */
2011-11-15 14:45:59 +01:00
image = ( __le32 * ) il - > ucode_boot . v_addr ;
2011-10-24 16:49:25 +02:00
len = il - > ucode_boot . len ;
rc = il3945_verify_inst_sparse ( il , image , len ) ;
2011-02-21 11:11:05 -08:00
if ( rc = = 0 ) {
2011-11-15 11:21:01 +01:00
D_INFO ( " Bootstrap uCode is good in inst SRAM \n " ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
/* Try initialize */
2011-11-15 14:45:59 +01:00
image = ( __le32 * ) il - > ucode_init . v_addr ;
2011-10-24 16:49:25 +02:00
len = il - > ucode_init . len ;
rc = il3945_verify_inst_sparse ( il , image , len ) ;
2011-02-21 11:11:05 -08:00
if ( rc = = 0 ) {
2011-11-15 11:21:01 +01:00
D_INFO ( " Initialize uCode is good in inst SRAM \n " ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
/* Try runtime/protocol */
2011-11-15 14:45:59 +01:00
image = ( __le32 * ) il - > ucode_code . v_addr ;
2011-10-24 16:49:25 +02:00
len = il - > ucode_code . len ;
rc = il3945_verify_inst_sparse ( il , image , len ) ;
2011-02-21 11:11:05 -08:00
if ( rc = = 0 ) {
2011-11-15 11:21:01 +01:00
D_INFO ( " Runtime uCode is good in inst SRAM \n " ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
2011-08-18 22:07:57 +02:00
IL_ERR ( " NO VALID UCODE IMAGE IN INSTRUCTION SRAM!! \n " ) ;
2011-02-21 11:11:05 -08:00
/* Since nothing seems to match, show first several data entries in
* instruction SRAM , so maybe visual inspection will give a clue .
* Selection of bootstrap image ( vs . other images ) is arbitrary . */
2011-11-15 14:45:59 +01:00
image = ( __le32 * ) il - > ucode_boot . v_addr ;
2011-10-24 16:49:25 +02:00
len = il - > ucode_boot . len ;
rc = il3945_verify_inst_full ( il , image , len ) ;
2011-02-21 11:11:05 -08:00
return rc ;
}
2011-11-15 14:45:59 +01:00
static void
il3945_nic_start ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
/* Remove all resets to allow NIC to operate */
2011-08-24 15:14:03 +02:00
_il_wr ( il , CSR_RESET , 0 ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 11:25:42 +01:00
# define IL3945_UCODE_GET(item) \
2011-10-24 15:41:30 +02:00
static u32 il3945_ucode_get_ # # item ( const struct il_ucode_header * ucode ) \
2011-02-21 11:11:05 -08:00
{ \
2011-02-21 11:27:26 -08:00
return le32_to_cpu ( ucode - > v1 . item ) ; \
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static u32
il3945_ucode_get_header_size ( u32 api_ver )
2011-02-21 11:11:05 -08:00
{
return 24 ;
}
2011-11-15 14:45:59 +01:00
static u8 *
il3945_ucode_get_data ( const struct il_ucode_header * ucode )
2011-02-21 11:11:05 -08:00
{
2011-02-21 11:27:26 -08:00
return ( u8 * ) ucode - > v1 . data ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 11:25:42 +01:00
IL3945_UCODE_GET ( inst_size ) ;
IL3945_UCODE_GET ( data_size ) ;
IL3945_UCODE_GET ( init_size ) ;
IL3945_UCODE_GET ( init_data_size ) ;
IL3945_UCODE_GET ( boot_size ) ;
2011-02-21 11:11:05 -08:00
/**
2011-10-24 15:41:30 +02:00
* il3945_read_ucode - Read uCode images from disk file .
2011-02-21 11:11:05 -08:00
*
* Copy into buffers for card to fetch via bus - mastering
*/
2011-11-15 14:45:59 +01:00
static int
il3945_read_ucode ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 15:41:30 +02:00
const struct il_ucode_header * ucode ;
2011-11-15 12:30:17 +01:00
int ret = - EINVAL , idx ;
2011-02-21 11:11:05 -08:00
const struct firmware * ucode_raw ;
/* firmware file name contains uCode/driver compatibility version */
2011-10-24 16:49:25 +02:00
const char * name_pre = il - > cfg - > fw_name_pre ;
const unsigned int api_max = il - > cfg - > ucode_api_max ;
const unsigned int api_min = il - > cfg - > ucode_api_min ;
2011-02-21 11:11:05 -08:00
char buf [ 25 ] ;
u8 * src ;
size_t len ;
u32 api_ver , inst_size , data_size , init_size , init_data_size , boot_size ;
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware ( ) is synchronous , file is in memory on return . */
2011-11-15 12:30:17 +01:00
for ( idx = api_max ; idx > = api_min ; idx - - ) {
sprintf ( buf , " %s%u%s " , name_pre , idx , " .ucode " ) ;
2011-10-24 16:49:25 +02:00
ret = request_firmware ( & ucode_raw , buf , & il - > pci_dev - > dev ) ;
2011-02-21 11:11:05 -08:00
if ( ret < 0 ) {
2011-11-15 14:45:59 +01:00
IL_ERR ( " %s firmware file req failed: %d \n " , buf , ret ) ;
2011-02-21 11:11:05 -08:00
if ( ret = = - ENOENT )
continue ;
else
goto error ;
} else {
2011-11-15 12:30:17 +01:00
if ( idx < api_max )
2011-08-18 22:07:57 +02:00
IL_ERR ( " Loaded firmware %s, "
2011-11-15 14:45:59 +01:00
" which is deprecated. "
" Please use API v%u instead. \n " , buf ,
api_max ) ;
2011-11-15 11:21:01 +01:00
D_INFO ( " Got firmware '%s' file "
2011-11-15 14:45:59 +01:00
" (%zd bytes) from disk \n " , buf , ucode_raw - > size ) ;
2011-02-21 11:11:05 -08:00
break ;
}
}
if ( ret < 0 )
goto error ;
/* Make sure that we got at least our header! */
2011-11-15 14:45:59 +01:00
if ( ucode_raw - > size < il3945_ucode_get_header_size ( 1 ) ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " File size way too small! \n " ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err_release ;
}
/* Data from ucode file: header followed by uCode images */
2011-10-24 15:41:30 +02:00
ucode = ( struct il_ucode_header * ) ucode_raw - > data ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > ucode_ver = le32_to_cpu ( ucode - > ver ) ;
api_ver = IL_UCODE_API ( il - > ucode_ver ) ;
2011-10-24 15:41:30 +02:00
inst_size = il3945_ucode_get_inst_size ( ucode ) ;
data_size = il3945_ucode_get_data_size ( ucode ) ;
init_size = il3945_ucode_get_init_size ( ucode ) ;
init_data_size = il3945_ucode_get_init_data_size ( ucode ) ;
boot_size = il3945_ucode_get_boot_size ( ucode ) ;
src = il3945_ucode_get_data ( ucode ) ;
2011-02-21 11:11:05 -08:00
/* api_ver should match the api version forming part of the
* firmware filename . . . but we don ' t check for that and only rely
* on the API version read from firmware header from here on forward */
if ( api_ver < api_min | | api_ver > api_max ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Driver unable to support your firmware API. "
2011-11-15 14:45:59 +01:00
" Driver supports v%u, firmware is v%u. \n " , api_max ,
api_ver ) ;
2011-10-24 16:49:25 +02:00
il - > ucode_ver = 0 ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err_release ;
}
if ( api_ver ! = api_max )
2011-08-18 22:07:57 +02:00
IL_ERR ( " Firmware has old API version. Expected %u, "
2011-11-15 14:45:59 +01:00
" got %u. New firmware can be obtained "
" from http://www.intellinuxwireless.org. \n " , api_max ,
api_ver ) ;
2011-02-21 11:11:05 -08:00
2011-08-18 22:07:57 +02:00
IL_INFO ( " loaded firmware version %u.%u.%u.%u \n " ,
2011-11-15 14:45:59 +01:00
IL_UCODE_MAJOR ( il - > ucode_ver ) , IL_UCODE_MINOR ( il - > ucode_ver ) ,
IL_UCODE_API ( il - > ucode_ver ) , IL_UCODE_SERIAL ( il - > ucode_ver ) ) ;
2011-10-24 16:49:25 +02:00
2011-11-15 14:45:59 +01:00
snprintf ( il - > hw - > wiphy - > fw_version , sizeof ( il - > hw - > wiphy - > fw_version ) ,
" %u.%u.%u.%u " , IL_UCODE_MAJOR ( il - > ucode_ver ) ,
IL_UCODE_MINOR ( il - > ucode_ver ) , IL_UCODE_API ( il - > ucode_ver ) ,
IL_UCODE_SERIAL ( il - > ucode_ver ) ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
D_INFO ( " f/w package hdr ucode version raw = 0x%x \n " , il - > ucode_ver ) ;
D_INFO ( " f/w package hdr runtime inst size = %u \n " , inst_size ) ;
D_INFO ( " f/w package hdr runtime data size = %u \n " , data_size ) ;
D_INFO ( " f/w package hdr init inst size = %u \n " , init_size ) ;
D_INFO ( " f/w package hdr init data size = %u \n " , init_data_size ) ;
D_INFO ( " f/w package hdr boot inst size = %u \n " , boot_size ) ;
2011-02-21 11:11:05 -08:00
/* Verify size of file vs. image size info in file's header */
2011-11-15 14:45:59 +01:00
if ( ucode_raw - > size ! =
il3945_ucode_get_header_size ( api_ver ) + inst_size + data_size +
init_size + init_data_size + boot_size ) {
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
D_INFO ( " uCode file size %zd does not match expected size \n " ,
ucode_raw - > size ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err_release ;
}
/* Verify that uCode images will fit in card's SRAM */
2011-11-15 11:25:42 +01:00
if ( inst_size > IL39_MAX_INST_SIZE ) {
2011-11-15 14:45:59 +01:00
D_INFO ( " uCode instr len %d too large to fit in \n " , inst_size ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err_release ;
}
2011-11-15 11:25:42 +01:00
if ( data_size > IL39_MAX_DATA_SIZE ) {
2011-11-15 14:45:59 +01:00
D_INFO ( " uCode data len %d too large to fit in \n " , data_size ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err_release ;
}
2011-11-15 11:25:42 +01:00
if ( init_size > IL39_MAX_INST_SIZE ) {
2011-11-15 14:45:59 +01:00
D_INFO ( " uCode init instr len %d too large to fit in \n " ,
init_size ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err_release ;
}
2011-11-15 11:25:42 +01:00
if ( init_data_size > IL39_MAX_DATA_SIZE ) {
2011-11-15 14:45:59 +01:00
D_INFO ( " uCode init data len %d too large to fit in \n " ,
init_data_size ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err_release ;
}
2011-11-15 11:25:42 +01:00
if ( boot_size > IL39_MAX_BSM_SIZE ) {
2011-11-15 14:45:59 +01:00
D_INFO ( " uCode boot instr len %d too large to fit in \n " ,
boot_size ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err_release ;
}
/* Allocate ucode buffers for card's bus-master loading ... */
/* Runtime instructions and 2 copies of data:
* 1 ) unmodified from disk
* 2 ) backup cache for save / restore during power - downs */
2011-10-24 16:49:25 +02:00
il - > ucode_code . len = inst_size ;
il_alloc_fw_desc ( il - > pci_dev , & il - > ucode_code ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > ucode_data . len = data_size ;
il_alloc_fw_desc ( il - > pci_dev , & il - > ucode_data ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > ucode_data_backup . len = data_size ;
il_alloc_fw_desc ( il - > pci_dev , & il - > ucode_data_backup ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( ! il - > ucode_code . v_addr | | ! il - > ucode_data . v_addr | |
! il - > ucode_data_backup . v_addr )
2011-02-21 11:11:05 -08:00
goto err_pci_alloc ;
/* Initialization instructions and data */
if ( init_size & & init_data_size ) {
2011-10-24 16:49:25 +02:00
il - > ucode_init . len = init_size ;
il_alloc_fw_desc ( il - > pci_dev , & il - > ucode_init ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > ucode_init_data . len = init_data_size ;
il_alloc_fw_desc ( il - > pci_dev , & il - > ucode_init_data ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( ! il - > ucode_init . v_addr | | ! il - > ucode_init_data . v_addr )
2011-02-21 11:11:05 -08:00
goto err_pci_alloc ;
}
/* Bootstrap (instructions only, no data) */
if ( boot_size ) {
2011-10-24 16:49:25 +02:00
il - > ucode_boot . len = boot_size ;
il_alloc_fw_desc ( il - > pci_dev , & il - > ucode_boot ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( ! il - > ucode_boot . v_addr )
2011-02-21 11:11:05 -08:00
goto err_pci_alloc ;
}
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
len = inst_size ;
2011-11-15 14:45:59 +01:00
D_INFO ( " Copying (but not loading) uCode instr len %zd \n " , len ) ;
2011-10-24 16:49:25 +02:00
memcpy ( il - > ucode_code . v_addr , src , len ) ;
2011-02-21 11:11:05 -08:00
src + = len ;
2011-11-15 11:21:01 +01:00
D_INFO ( " uCode instr buf vaddr = 0x%p, paddr = 0x%08x \n " ,
2011-11-15 14:45:59 +01:00
il - > ucode_code . v_addr , ( u32 ) il - > ucode_code . p_addr ) ;
2011-02-21 11:11:05 -08:00
/* Runtime data (2nd block)
2011-10-24 15:41:30 +02:00
* NOTE : Copy into backup buffer will be done in il3945_up ( ) */
2011-02-21 11:11:05 -08:00
len = data_size ;
2011-11-15 14:45:59 +01:00
D_INFO ( " Copying (but not loading) uCode data len %zd \n " , len ) ;
2011-10-24 16:49:25 +02:00
memcpy ( il - > ucode_data . v_addr , src , len ) ;
memcpy ( il - > ucode_data_backup . v_addr , src , len ) ;
2011-02-21 11:11:05 -08:00
src + = len ;
/* Initialization instructions (3rd block) */
if ( init_size ) {
len = init_size ;
2011-11-15 14:45:59 +01:00
D_INFO ( " Copying (but not loading) init instr len %zd \n " , len ) ;
2011-10-24 16:49:25 +02:00
memcpy ( il - > ucode_init . v_addr , src , len ) ;
2011-02-21 11:11:05 -08:00
src + = len ;
}
/* Initialization data (4th block) */
if ( init_data_size ) {
len = init_data_size ;
2011-11-15 14:45:59 +01:00
D_INFO ( " Copying (but not loading) init data len %zd \n " , len ) ;
2011-10-24 16:49:25 +02:00
memcpy ( il - > ucode_init_data . v_addr , src , len ) ;
2011-02-21 11:11:05 -08:00
src + = len ;
}
/* Bootstrap instructions (5th block) */
len = boot_size ;
2011-11-15 14:45:59 +01:00
D_INFO ( " Copying (but not loading) boot instr len %zd \n " , len ) ;
2011-10-24 16:49:25 +02:00
memcpy ( il - > ucode_boot . v_addr , src , len ) ;
2011-02-21 11:11:05 -08:00
/* We have our copies now, allow OS release its copies */
release_firmware ( ucode_raw ) ;
return 0 ;
2011-11-15 14:45:59 +01:00
err_pci_alloc :
2011-08-18 22:07:57 +02:00
IL_ERR ( " failed to allocate pci memory \n " ) ;
2011-02-21 11:11:05 -08:00
ret = - ENOMEM ;
2011-10-24 16:49:25 +02:00
il3945_dealloc_ucode_pci ( il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
err_release :
2011-02-21 11:11:05 -08:00
release_firmware ( ucode_raw ) ;
2011-11-15 14:45:59 +01:00
error :
2011-02-21 11:11:05 -08:00
return ret ;
}
/**
2011-10-24 15:41:30 +02:00
* il3945_set_ucode_ptrs - Set uCode address location
2011-02-21 11:11:05 -08:00
*
* Tell initialization uCode where to find runtime uCode .
*
* BSM registers initially contain pointers to initialization uCode .
* We need to replace them to load runtime uCode inst and data ,
* and to save runtime data when powering down .
*/
2011-11-15 14:45:59 +01:00
static int
il3945_set_ucode_ptrs ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
dma_addr_t pinst ;
dma_addr_t pdata ;
/* bits 31:0 for 3945 */
2011-10-24 16:49:25 +02:00
pinst = il - > ucode_code . p_addr ;
pdata = il - > ucode_data_backup . p_addr ;
2011-02-21 11:11:05 -08:00
/* Tell bootstrap uCode where to find image to load */
2011-08-24 21:06:33 +02:00
il_wr_prph ( il , BSM_DRAM_INST_PTR_REG , pinst ) ;
il_wr_prph ( il , BSM_DRAM_DATA_PTR_REG , pdata ) ;
2011-11-15 14:45:59 +01:00
il_wr_prph ( il , BSM_DRAM_DATA_BYTECOUNT_REG , il - > ucode_data . len ) ;
2011-02-21 11:11:05 -08:00
/* Inst byte count must be last to set up, bit 31 signals uCode
* that all new ptr / size info is in place */
2011-08-24 21:06:33 +02:00
il_wr_prph ( il , BSM_DRAM_INST_BYTECOUNT_REG ,
2011-11-15 14:45:59 +01:00
il - > ucode_code . len | BSM_DRAM_INST_LOAD ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_INFO ( " Runtime uCode pointers are set. \n " ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
/**
2011-08-30 15:26:35 +02:00
* il3945_init_alive_start - Called after N_ALIVE notification received
2011-02-21 11:11:05 -08:00
*
2011-08-30 15:26:35 +02:00
* Called after N_ALIVE notification received from " initialize " uCode .
2011-02-21 11:11:05 -08:00
*
* Tell " initialize " uCode to go ahead and load the runtime uCode .
*/
2011-11-15 14:45:59 +01:00
static void
il3945_init_alive_start ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
/* Check alive response for "valid" sign from uCode */
2011-10-24 16:49:25 +02:00
if ( il - > card_alive_init . is_valid ! = UCODE_VALID_OK ) {
2011-02-21 11:11:05 -08:00
/* We had an error bringing up the hardware, so take it
* all the way back down so we can try again */
2011-11-15 11:21:01 +01:00
D_INFO ( " Initialize Alive failed. \n " ) ;
2011-02-21 11:11:05 -08:00
goto restart ;
}
/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
* This is a paranoid check , because we would not have gotten the
* " initialize " alive if code weren ' t properly loaded . */
2011-10-24 16:49:25 +02:00
if ( il3945_verify_ucode ( il ) ) {
2011-02-21 11:11:05 -08:00
/* Runtime instruction load was bad;
* take it all the way back down so we can try again */
2011-11-15 11:21:01 +01:00
D_INFO ( " Bad \" initialize \" uCode load. \n " ) ;
2011-02-21 11:11:05 -08:00
goto restart ;
}
/* Send pointers to protocol/runtime uCode image ... init code will
* load and launch runtime uCode , which will send us another " Alive "
* notification . */
2011-11-15 11:21:01 +01:00
D_INFO ( " Initialization Alive received. \n " ) ;
2011-10-24 16:49:25 +02:00
if ( il3945_set_ucode_ptrs ( il ) ) {
2011-02-21 11:11:05 -08:00
/* Runtime instruction load won't happen;
* take it all the way back down so we can try again */
2011-11-15 11:21:01 +01:00
D_INFO ( " Couldn't set up uCode pointers. \n " ) ;
2011-02-21 11:11:05 -08:00
goto restart ;
}
return ;
2011-11-15 14:45:59 +01:00
restart :
2011-10-24 16:49:25 +02:00
queue_work ( il - > workqueue , & il - > restart ) ;
2011-02-21 11:11:05 -08:00
}
/**
2011-08-30 15:26:35 +02:00
* il3945_alive_start - called after N_ALIVE notification received
2011-02-21 11:11:05 -08:00
* from protocol / runtime uCode ( initialization uCode ' s
2011-10-24 15:41:30 +02:00
* Alive gets handled by il3945_init_alive_start ( ) ) .
2011-02-21 11:11:05 -08:00
*/
2011-11-15 14:45:59 +01:00
static void
il3945_alive_start ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
int thermal_spin = 0 ;
u32 rfkill ;
2011-11-15 11:21:01 +01:00
D_INFO ( " Runtime Alive received. \n " ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( il - > card_alive . is_valid ! = UCODE_VALID_OK ) {
2011-02-21 11:11:05 -08:00
/* We had an error bringing up the hardware, so take it
* all the way back down so we can try again */
2011-11-15 11:21:01 +01:00
D_INFO ( " Alive failed. \n " ) ;
2011-02-21 11:11:05 -08:00
goto restart ;
}
/* Initialize uCode has loaded Runtime uCode ... verify inst image.
* This is a paranoid check , because we would not have gotten the
* " runtime " alive if code weren ' t properly loaded . */
2011-10-24 16:49:25 +02:00
if ( il3945_verify_ucode ( il ) ) {
2011-02-21 11:11:05 -08:00
/* Runtime instruction load was bad;
* take it all the way back down so we can try again */
2011-11-15 11:21:01 +01:00
D_INFO ( " Bad runtime uCode load. \n " ) ;
2011-02-21 11:11:05 -08:00
goto restart ;
}
2011-08-24 21:06:33 +02:00
rfkill = il_rd_prph ( il , APMG_RFKILL_REG ) ;
2011-11-15 11:21:01 +01:00
D_INFO ( " RFKILL status: 0x%x \n " , rfkill ) ;
2011-02-21 11:11:05 -08:00
if ( rfkill & 0x1 ) {
2012-02-13 11:23:29 +01:00
clear_bit ( S_RFKILL , & il - > status ) ;
2011-02-21 11:11:05 -08:00
/* if RFKILL is not on, then wait for thermal
* sensor in adapter to kick in */
2011-10-24 16:49:25 +02:00
while ( il3945_hw_get_temperature ( il ) = = 0 ) {
2011-02-21 11:11:05 -08:00
thermal_spin + + ;
udelay ( 10 ) ;
}
if ( thermal_spin )
2011-11-15 11:21:01 +01:00
D_INFO ( " Thermal calibration took %dus \n " ,
2011-11-15 14:45:59 +01:00
thermal_spin * 10 ) ;
2011-02-21 11:11:05 -08:00
} else
2012-02-13 11:23:29 +01:00
set_bit ( S_RFKILL , & il - > status ) ;
2011-02-21 11:11:05 -08:00
/* After the ALIVE response, we can send commands to 3945 uCode */
2011-11-15 13:09:01 +01:00
set_bit ( S_ALIVE , & il - > status ) ;
2011-02-21 11:11:05 -08:00
/* Enable watchdog to monitor the driver tx queues */
2011-10-24 16:49:25 +02:00
il_setup_watchdog ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( il_is_rfkill ( il ) )
2011-02-21 11:11:05 -08:00
return ;
2011-10-24 16:49:25 +02:00
ieee80211_wake_queues ( il - > hw ) ;
2011-02-21 11:11:05 -08:00
2011-08-26 16:07:43 +02:00
il - > active_rate = RATES_MASK_3945 ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_power_update_mode ( il , true ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:29:04 +01:00
if ( il_is_associated ( il ) ) {
2011-10-24 15:41:30 +02:00
struct il3945_rxon_cmd * active_rxon =
2012-02-03 17:31:37 +01:00
( struct il3945_rxon_cmd * ) ( & il - > active ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
il - > staging . filter_flags | = RXON_FILTER_ASSOC_MSK ;
2011-02-21 11:11:05 -08:00
active_rxon - > filter_flags & = ~ RXON_FILTER_ASSOC_MSK ;
} else {
/* Initialize our rx_config data */
2012-02-03 17:31:57 +01:00
il_connection_init_rx_config ( il ) ;
2011-02-21 11:11:05 -08:00
}
/* Configure Bluetooth device coexistence support */
2011-10-24 16:49:25 +02:00
il_send_bt_config ( il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 13:09:01 +01:00
set_bit ( S_READY , & il - > status ) ;
2011-02-21 11:11:05 -08:00
/* Configure the adapter for unassociated operation */
2012-02-03 17:31:57 +01:00
il3945_commit_rxon ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_reg_txpower_periodic ( il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_INFO ( " ALIVE processing complete. \n " ) ;
2011-10-24 16:49:25 +02:00
wake_up ( & il - > wait_command_queue ) ;
2011-02-21 11:11:05 -08:00
return ;
2011-11-15 14:45:59 +01:00
restart :
2011-10-24 16:49:25 +02:00
queue_work ( il - > workqueue , & il - > restart ) ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 16:49:25 +02:00
static void il3945_cancel_deferred_work ( struct il_priv * il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static void
__il3945_down ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
unsigned long flags ;
int exit_pending ;
2011-11-15 11:21:01 +01:00
D_INFO ( DRV_NAME " is going down \n " ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_scan_cancel_timeout ( il , 200 ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 13:09:01 +01:00
exit_pending = test_and_set_bit ( S_EXIT_PENDING , & il - > status ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 13:09:01 +01:00
/* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set
2011-02-21 11:11:05 -08:00
* to prevent rearm timer */
2011-10-24 16:49:25 +02:00
del_timer_sync ( & il - > watchdog ) ;
2011-02-21 11:11:05 -08:00
/* Station information will now be cleared in device */
2012-02-03 17:31:57 +01:00
il_clear_ucode_stations ( il ) ;
2011-10-24 16:49:25 +02:00
il_dealloc_bcast_stations ( il ) ;
il_clear_driver_stations ( il ) ;
2011-02-21 11:11:05 -08:00
/* Unblock any waiting calls */
2011-10-24 16:49:25 +02:00
wake_up_all ( & il - > wait_command_queue ) ;
2011-02-21 11:11:05 -08:00
/* Wipe out the EXIT_PENDING status bit if we are not actually
* exiting the module */
if ( ! exit_pending )
2011-11-15 13:09:01 +01:00
clear_bit ( S_EXIT_PENDING , & il - > status ) ;
2011-02-21 11:11:05 -08:00
/* stop and reset the on-board processor */
2011-08-24 15:14:03 +02:00
_il_wr ( il , CSR_RESET , CSR_RESET_REG_FLAG_NEVO_RESET ) ;
2011-02-21 11:11:05 -08:00
/* tell the device to stop sending interrupts */
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
il_disable_interrupts ( il ) ;
spin_unlock_irqrestore ( & il - > lock , flags ) ;
il3945_synchronize_irq ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( il - > mac80211_registered )
ieee80211_stop_queues ( il - > hw ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
/* If we have not previously called il3945_init() then
2011-02-21 11:11:05 -08:00
* clear all bits but the RF Kill bits and return */
2011-10-24 16:49:25 +02:00
if ( ! il_is_init ( il ) ) {
2011-11-15 14:45:59 +01:00
il - > status =
2012-02-13 11:23:29 +01:00
test_bit ( S_RFKILL , & il - > status ) < < S_RFKILL |
2012-02-13 11:23:23 +01:00
test_bit ( S_GEO_CONFIGURED , & il - > status ) < < S_GEO_CONFIGURED |
2011-11-15 14:45:59 +01:00
test_bit ( S_EXIT_PENDING , & il - > status ) < < S_EXIT_PENDING ;
2011-02-21 11:11:05 -08:00
goto exit ;
}
/* ...otherwise clear out all the status bits but the RF Kill
* bit and continue taking the NIC down . */
2011-11-15 14:45:59 +01:00
il - > status & =
2012-02-13 11:23:29 +01:00
test_bit ( S_RFKILL , & il - > status ) < < S_RFKILL |
2012-02-13 11:23:23 +01:00
test_bit ( S_GEO_CONFIGURED , & il - > status ) < < S_GEO_CONFIGURED |
test_bit ( S_FW_ERROR , & il - > status ) < < S_FW_ERROR |
2011-11-15 14:45:59 +01:00
test_bit ( S_EXIT_PENDING , & il - > status ) < < S_EXIT_PENDING ;
2011-02-21 11:11:05 -08:00
2012-02-13 11:23:24 +01:00
/*
* We disabled and synchronized interrupt , and priv - > mutex is taken , so
* here is the only thread which will program device registers , but
* still have lockdep assertions , so we are taking reg_lock .
*/
spin_lock_irq ( & il - > reg_lock ) ;
/* FIXME: il_grab_nic_access if rfkill is off ? */
2011-10-24 16:49:25 +02:00
il3945_hw_txq_ctx_stop ( il ) ;
il3945_hw_rxq_stop ( il ) ;
2011-02-21 11:11:05 -08:00
/* Power-down device's busmaster DMA clocks */
2012-02-13 11:23:24 +01:00
_il_wr_prph ( il , APMG_CLK_DIS_REG , APMG_CLK_VAL_DMA_CLK_RQT ) ;
2011-02-21 11:11:05 -08:00
udelay ( 5 ) ;
/* Stop the device, and put it in low power state */
2012-02-13 11:23:24 +01:00
_il_apm_stop ( il ) ;
spin_unlock_irq ( & il - > reg_lock ) ;
2011-02-21 11:11:05 -08:00
2012-02-13 11:23:24 +01:00
il3945_hw_txq_ctx_free ( il ) ;
2011-11-15 14:45:59 +01:00
exit :
2011-10-24 16:49:25 +02:00
memset ( & il - > card_alive , 0 , sizeof ( struct il_alive_resp ) ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( il - > beacon_skb )
dev_kfree_skb ( il - > beacon_skb ) ;
il - > beacon_skb = NULL ;
2011-02-21 11:11:05 -08:00
/* clear out any free frames */
2011-10-24 16:49:25 +02:00
il3945_clear_free_frames ( il ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_down ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
__il3945_down ( il ) ;
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_cancel_deferred_work ( il ) ;
2011-02-21 11:11:05 -08:00
}
# define MAX_HW_RESTARTS 5
2011-11-15 14:45:59 +01:00
static int
il3945_alloc_bcast_station ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
unsigned long flags ;
u8 sta_id ;
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > sta_lock , flags ) ;
2012-02-03 17:31:57 +01:00
sta_id = il_prep_station ( il , il_bcast_addr , false , NULL ) ;
2011-10-24 15:41:30 +02:00
if ( sta_id = = IL_INVALID_STATION ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Unable to prepare broadcast station \n " ) ;
2011-10-24 16:49:25 +02:00
spin_unlock_irqrestore ( & il - > sta_lock , flags ) ;
2011-02-21 11:11:05 -08:00
return - EINVAL ;
}
2011-10-24 16:49:25 +02:00
il - > stations [ sta_id ] . used | = IL_STA_DRIVER_ACTIVE ;
il - > stations [ sta_id ] . used | = IL_STA_BCAST ;
spin_unlock_irqrestore ( & il - > sta_lock , flags ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
2011-11-15 14:45:59 +01:00
static int
__il3945_up ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
int rc , i ;
2011-10-24 16:49:25 +02:00
rc = il3945_alloc_bcast_station ( il ) ;
2011-02-21 11:11:05 -08:00
if ( rc )
return rc ;
2011-11-15 13:09:01 +01:00
if ( test_bit ( S_EXIT_PENDING , & il - > status ) ) {
2011-08-18 22:07:57 +02:00
IL_WARN ( " Exit pending; will not bring the NIC up \n " ) ;
2011-02-21 11:11:05 -08:00
return - EIO ;
}
2011-10-24 16:49:25 +02:00
if ( ! il - > ucode_data_backup . v_addr | | ! il - > ucode_data . v_addr ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " ucode not available for device bring up \n " ) ;
2011-02-21 11:11:05 -08:00
return - EIO ;
}
/* If platform's RF_KILL switch is NOT set to KILL */
2011-11-15 14:45:59 +01:00
if ( _il_rd ( il , CSR_GP_CNTRL ) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW )
2012-02-13 11:23:29 +01:00
clear_bit ( S_RFKILL , & il - > status ) ;
2011-02-21 11:11:05 -08:00
else {
2012-02-13 11:23:29 +01:00
set_bit ( S_RFKILL , & il - > status ) ;
2013-10-25 12:37:54 +02:00
return - ERFKILL ;
2011-02-21 11:11:05 -08:00
}
2011-08-24 15:14:03 +02:00
_il_wr ( il , CSR_INT , 0xFFFFFFFF ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
rc = il3945_hw_nic_init ( il ) ;
2011-02-21 11:11:05 -08:00
if ( rc ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Unable to int nic \n " ) ;
2011-02-21 11:11:05 -08:00
return rc ;
}
/* make sure rfkill handshake bits are cleared */
2011-08-24 15:14:03 +02:00
_il_wr ( il , CSR_UCODE_DRV_GP1_CLR , CSR_UCODE_SW_BIT_RFKILL ) ;
2011-11-15 14:45:59 +01:00
_il_wr ( il , CSR_UCODE_DRV_GP1_CLR , CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED ) ;
2011-02-21 11:11:05 -08:00
/* clear (again), then enable host interrupts */
2011-08-24 15:14:03 +02:00
_il_wr ( il , CSR_INT , 0xFFFFFFFF ) ;
2011-10-24 16:49:25 +02:00
il_enable_interrupts ( il ) ;
2011-02-21 11:11:05 -08:00
/* really make sure rfkill handshake bits are cleared */
2011-08-24 15:14:03 +02:00
_il_wr ( il , CSR_UCODE_DRV_GP1_CLR , CSR_UCODE_SW_BIT_RFKILL ) ;
_il_wr ( il , CSR_UCODE_DRV_GP1_CLR , CSR_UCODE_SW_BIT_RFKILL ) ;
2011-02-21 11:11:05 -08:00
/* Copy original ucode data image from disk into backup cache.
* This will be used to initialize the on - board processor ' s
* data SRAM for a clean start when the runtime program first loads . */
2011-10-24 16:49:25 +02:00
memcpy ( il - > ucode_data_backup . v_addr , il - > ucode_data . v_addr ,
il - > ucode_data . len ) ;
2011-02-21 11:11:05 -08:00
/* We return success when we resume from suspend and rf_kill is on. */
2012-02-13 11:23:29 +01:00
if ( test_bit ( S_RFKILL , & il - > status ) )
2011-02-21 11:11:05 -08:00
return 0 ;
for ( i = 0 ; i < MAX_HW_RESTARTS ; i + + ) {
/* load bootstrap state machine,
* load bootstrap program into processor ' s memory ,
* prepare to load the " initialize " uCode */
2012-02-13 11:23:18 +01:00
rc = il - > ops - > load_ucode ( il ) ;
2011-02-21 11:11:05 -08:00
if ( rc ) {
2011-11-15 14:45:59 +01:00
IL_ERR ( " Unable to set up bootstrap uCode: %d \n " , rc ) ;
2011-02-21 11:11:05 -08:00
continue ;
}
/* start card; "initialize" will load runtime ucode */
2011-10-24 16:49:25 +02:00
il3945_nic_start ( il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_INFO ( DRV_NAME " is coming up \n " ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
2011-11-15 13:09:01 +01:00
set_bit ( S_EXIT_PENDING , & il - > status ) ;
2011-10-24 16:49:25 +02:00
__il3945_down ( il ) ;
2011-11-15 13:09:01 +01:00
clear_bit ( S_EXIT_PENDING , & il - > status ) ;
2011-02-21 11:11:05 -08:00
/* tried to restart and config the device for as long as our
* patience could withstand */
2011-08-18 22:07:57 +02:00
IL_ERR ( " Unable to initialize device after %d attempts. \n " , i ) ;
2011-02-21 11:11:05 -08:00
return - EIO ;
}
/*****************************************************************************
*
* Workqueue callbacks
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-11-15 14:45:59 +01:00
static void
il3945_bg_init_alive_start ( struct work_struct * data )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il =
2011-10-24 15:41:30 +02:00
container_of ( data , struct il_priv , init_alive_start . work ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2011-11-15 13:09:01 +01:00
if ( test_bit ( S_EXIT_PENDING , & il - > status ) )
2011-04-28 11:51:32 +02:00
goto out ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_init_alive_start ( il ) ;
2011-04-28 11:51:32 +02:00
out :
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_bg_alive_start ( struct work_struct * data )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il =
2011-10-24 15:41:30 +02:00
container_of ( data , struct il_priv , alive_start . work ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2012-03-08 13:16:01 +01:00
if ( test_bit ( S_EXIT_PENDING , & il - > status ) | | il - > txq = = NULL )
2011-04-28 11:51:32 +02:00
goto out ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_alive_start ( il ) ;
2011-04-28 11:51:32 +02:00
out :
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
}
/*
* 3945 cannot interrupt driver when hardware rf kill switch toggles ;
* driver must poll CSR_GP_CNTRL_REG register for change . This register
* * is * readable even when device has been SW_RESET into low power mode
* ( e . g . during RF KILL ) .
*/
2011-11-15 14:45:59 +01:00
static void
il3945_rfkill_poll ( struct work_struct * data )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il =
2011-10-24 15:41:30 +02:00
container_of ( data , struct il_priv , _3945 . rfkill_poll . work ) ;
2012-02-13 11:23:29 +01:00
bool old_rfkill = test_bit ( S_RFKILL , & il - > status ) ;
2011-11-15 14:45:59 +01:00
bool new_rfkill =
! ( _il_rd ( il , CSR_GP_CNTRL ) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW ) ;
2011-02-21 11:11:05 -08:00
if ( new_rfkill ! = old_rfkill ) {
if ( new_rfkill )
2012-02-13 11:23:29 +01:00
set_bit ( S_RFKILL , & il - > status ) ;
2011-02-21 11:11:05 -08:00
else
2012-02-13 11:23:29 +01:00
clear_bit ( S_RFKILL , & il - > status ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
wiphy_rfkill_set_hw_state ( il - > hw - > wiphy , new_rfkill ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_RF_KILL ( " RF_KILL bit toggled to %s. \n " ,
2011-11-15 14:45:59 +01:00
new_rfkill ? " disable radio " : " enable radio " ) ;
2011-02-21 11:11:05 -08:00
}
/* Keep this running, even if radio now enabled. This will be
* cancelled in mac_start ( ) if system decides to start again */
2011-10-24 16:49:25 +02:00
queue_delayed_work ( il - > workqueue , & il - > _3945 . rfkill_poll ,
2011-02-21 11:11:05 -08:00
round_jiffies_relative ( 2 * HZ ) ) ;
}
2011-11-15 14:45:59 +01:00
int
il3945_request_scan ( struct il_priv * il , struct ieee80211_vif * vif )
2011-02-21 11:11:05 -08:00
{
2011-10-24 15:41:30 +02:00
struct il_host_cmd cmd = {
2011-08-30 15:26:35 +02:00
. id = C_SCAN ,
2011-10-24 15:41:30 +02:00
. len = sizeof ( struct il3945_scan_cmd ) ,
2011-02-21 11:11:05 -08:00
. flags = CMD_SIZE_HUGE ,
} ;
2011-10-24 15:41:30 +02:00
struct il3945_scan_cmd * scan ;
2011-02-21 11:11:05 -08:00
u8 n_probes = 0 ;
enum ieee80211_band band ;
bool is_active = false ;
int ret ;
2011-06-08 15:28:26 +02:00
u16 len ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
lockdep_assert_held ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( ! il - > scan_cmd ) {
2011-11-15 14:45:59 +01:00
il - > scan_cmd =
kmalloc ( sizeof ( struct il3945_scan_cmd ) + IL_MAX_SCAN_SIZE ,
GFP_KERNEL ) ;
2011-10-24 16:49:25 +02:00
if ( ! il - > scan_cmd ) {
2011-11-15 11:21:01 +01:00
D_SCAN ( " Fail to allocate scan memory \n " ) ;
2011-02-21 11:11:05 -08:00
return - ENOMEM ;
}
}
2011-10-24 16:49:25 +02:00
scan = il - > scan_cmd ;
2011-10-24 15:41:30 +02:00
memset ( scan , 0 , sizeof ( struct il3945_scan_cmd ) + IL_MAX_SCAN_SIZE ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
scan - > quiet_plcp_th = IL_PLCP_QUIET_THRESH ;
scan - > quiet_time = IL_ACTIVE_QUIET_TIME ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:29:04 +01:00
if ( il_is_associated ( il ) ) {
2011-06-08 15:28:26 +02:00
u16 interval ;
2011-02-21 11:11:05 -08:00
u32 extra ;
u32 suspend_time = 100 ;
u32 scan_suspend_time = 100 ;
2011-11-15 11:21:01 +01:00
D_INFO ( " Scanning while associated... \n " ) ;
2011-02-21 11:11:05 -08:00
2011-06-08 15:28:26 +02:00
interval = vif - > bss_conf . beacon_int ;
2011-02-21 11:11:05 -08:00
scan - > suspend_time = 0 ;
scan - > max_out_time = cpu_to_le32 ( 200 * 1024 ) ;
if ( ! interval )
interval = suspend_time ;
/*
* suspend time format :
* 0 - 19 : beacon interval in usec ( time before exec . )
* 20 - 23 : 0
* 24 - 31 : number of beacons ( suspend between channels )
*/
extra = ( suspend_time / interval ) < < 24 ;
2011-11-15 14:45:59 +01:00
scan_suspend_time =
0xFF0FFFFF & ( extra | ( ( suspend_time % interval ) * 1024 ) ) ;
2011-02-21 11:11:05 -08:00
scan - > suspend_time = cpu_to_le32 ( scan_suspend_time ) ;
2011-11-15 11:21:01 +01:00
D_SCAN ( " suspend_time 0x%X beacon interval %d \n " ,
2011-11-15 14:45:59 +01:00
scan_suspend_time , interval ) ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 16:49:25 +02:00
if ( il - > scan_request - > n_ssids ) {
2011-02-21 11:11:05 -08:00
int i , p = 0 ;
2011-11-15 11:21:01 +01:00
D_SCAN ( " Kicking off active scan \n " ) ;
2011-10-24 16:49:25 +02:00
for ( i = 0 ; i < il - > scan_request - > n_ssids ; i + + ) {
2011-02-21 11:11:05 -08:00
/* always does wildcard anyway */
2011-10-24 16:49:25 +02:00
if ( ! il - > scan_request - > ssids [ i ] . ssid_len )
2011-02-21 11:11:05 -08:00
continue ;
scan - > direct_scan [ p ] . id = WLAN_EID_SSID ;
scan - > direct_scan [ p ] . len =
2011-11-15 14:45:59 +01:00
il - > scan_request - > ssids [ i ] . ssid_len ;
2011-02-21 11:11:05 -08:00
memcpy ( scan - > direct_scan [ p ] . ssid ,
2011-10-24 16:49:25 +02:00
il - > scan_request - > ssids [ i ] . ssid ,
il - > scan_request - > ssids [ i ] . ssid_len ) ;
2011-02-21 11:11:05 -08:00
n_probes + + ;
p + + ;
}
is_active = true ;
} else
2011-11-15 11:21:01 +01:00
D_SCAN ( " Kicking off passive scan. \n " ) ;
2011-02-21 11:11:05 -08:00
/* We don't build a direct scan probe request; the uCode will do
* that based on the direct_mask added to each channel entry */
scan - > tx_cmd . tx_flags = TX_CMD_FLG_SEQ_CTL_MSK ;
2012-02-03 17:31:44 +01:00
scan - > tx_cmd . sta_id = il - > hw_params . bcast_id ;
2011-02-21 11:11:05 -08:00
scan - > tx_cmd . stop_time . life_time = TX_CMD_LIFE_TIME_INFINITE ;
/* flags + rate selection */
2011-10-24 16:49:25 +02:00
switch ( il - > scan_band ) {
2011-02-21 11:11:05 -08:00
case IEEE80211_BAND_2GHZ :
scan - > flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK ;
2011-08-26 16:07:43 +02:00
scan - > tx_cmd . rate = RATE_1M_PLCP ;
2011-02-21 11:11:05 -08:00
band = IEEE80211_BAND_2GHZ ;
break ;
case IEEE80211_BAND_5GHZ :
2011-08-26 16:07:43 +02:00
scan - > tx_cmd . rate = RATE_6M_PLCP ;
2011-02-21 11:11:05 -08:00
band = IEEE80211_BAND_5GHZ ;
break ;
default :
2011-08-18 22:07:57 +02:00
IL_WARN ( " Invalid scan band \n " ) ;
2011-02-21 11:11:05 -08:00
return - EIO ;
}
/*
2011-12-23 08:13:50 +01:00
* If active scaning is requested but a certain channel is marked
* passive , we can do active scanning if we detect transmissions . For
* passive only scanning disable switching to active on any channel .
2011-02-21 11:11:05 -08:00
*/
2011-11-15 14:45:59 +01:00
scan - > good_CRC_th =
2011-12-23 08:13:50 +01:00
is_active ? IL_GOOD_CRC_TH_DEFAULT : IL_GOOD_CRC_TH_NEVER ;
2011-11-15 14:45:59 +01:00
len =
il_fill_probe_req ( il , ( struct ieee80211_mgmt * ) scan - > data ,
vif - > addr , il - > scan_request - > ie ,
il - > scan_request - > ie_len ,
IL_MAX_SCAN_SIZE - sizeof ( * scan ) ) ;
2011-06-08 15:28:26 +02:00
scan - > tx_cmd . len = cpu_to_le16 ( len ) ;
2011-02-21 11:11:05 -08:00
/* select Rx antennas */
2011-10-24 16:49:25 +02:00
scan - > flags | = il3945_get_antenna_flags ( il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
scan - > channel_count =
il3945_get_channels_for_scan ( il , band , is_active , n_probes ,
( void * ) & scan - > data [ len ] , vif ) ;
2011-02-21 11:11:05 -08:00
if ( scan - > channel_count = = 0 ) {
2011-11-15 11:21:01 +01:00
D_SCAN ( " channel count %d \n " , scan - > channel_count ) ;
2011-02-21 11:11:05 -08:00
return - EIO ;
}
2011-11-15 14:45:59 +01:00
cmd . len + =
le16_to_cpu ( scan - > tx_cmd . len ) +
2011-10-24 15:41:30 +02:00
scan - > channel_count * sizeof ( struct il3945_scan_channel ) ;
2011-02-21 11:11:05 -08:00
cmd . data = scan ;
scan - > len = cpu_to_le16 ( cmd . len ) ;
2011-11-15 13:09:01 +01:00
set_bit ( S_SCAN_HW , & il - > status ) ;
2011-10-24 16:49:25 +02:00
ret = il_send_cmd_sync ( il , & cmd ) ;
2011-02-21 11:11:05 -08:00
if ( ret )
2011-11-15 13:09:01 +01:00
clear_bit ( S_SCAN_HW , & il - > status ) ;
2011-02-21 11:11:05 -08:00
return ret ;
}
2011-11-15 14:45:59 +01:00
void
il3945_post_scan ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
/*
* Since setting the RXON may have been deferred while
* performing the scan , fire one off if needed
*/
2012-02-03 17:31:37 +01:00
if ( memcmp ( & il - > staging , & il - > active , sizeof ( il - > staging ) ) )
2012-02-03 17:31:57 +01:00
il3945_commit_rxon ( il ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_bg_restart ( struct work_struct * data )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = container_of ( data , struct il_priv , restart ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 13:09:01 +01:00
if ( test_bit ( S_EXIT_PENDING , & il - > status ) )
2011-02-21 11:11:05 -08:00
return ;
2011-11-15 13:09:01 +01:00
if ( test_and_clear_bit ( S_FW_ERROR , & il - > status ) ) {
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
il - > is_open = 0 ;
mutex_unlock ( & il - > mutex ) ;
il3945_down ( il ) ;
ieee80211_restart_hw ( il - > hw ) ;
2011-02-21 11:11:05 -08:00
} else {
2011-10-24 16:49:25 +02:00
il3945_down ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2011-11-15 13:09:01 +01:00
if ( test_bit ( S_EXIT_PENDING , & il - > status ) ) {
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
return ;
2011-04-28 11:51:32 +02:00
}
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
__il3945_up ( il ) ;
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
}
}
2011-11-15 14:45:59 +01:00
static void
il3945_bg_rx_replenish ( struct work_struct * data )
2011-02-21 11:11:05 -08:00
{
2011-11-15 14:45:59 +01:00
struct il_priv * il = container_of ( data , struct il_priv , rx_replenish ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2011-11-15 13:09:01 +01:00
if ( test_bit ( S_EXIT_PENDING , & il - > status ) )
2011-04-28 11:51:32 +02:00
goto out ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_rx_replenish ( il ) ;
2011-04-28 11:51:32 +02:00
out :
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
void
il3945_post_associate ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
int rc = 0 ;
struct ieee80211_conf * conf = NULL ;
2012-02-03 17:31:57 +01:00
if ( ! il - > vif | | ! il - > is_open )
2011-02-21 11:11:05 -08:00
return ;
2012-02-03 17:31:57 +01:00
D_ASSOC ( " Associated as %d to: %pM \n " , il - > vif - > bss_conf . aid ,
2012-02-03 17:31:37 +01:00
il - > active . bssid_addr ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 13:09:01 +01:00
if ( test_bit ( S_EXIT_PENDING , & il - > status ) )
2011-02-21 11:11:05 -08:00
return ;
2011-10-24 16:49:25 +02:00
il_scan_cancel_timeout ( il , 200 ) ;
2011-02-21 11:11:05 -08:00
2011-08-31 11:13:05 +02:00
conf = & il - > hw - > conf ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
il - > staging . filter_flags & = ~ RXON_FILTER_ASSOC_MSK ;
2012-02-03 17:31:57 +01:00
il3945_commit_rxon ( il ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:57 +01:00
rc = il_send_rxon_timing ( il ) ;
2011-02-21 11:11:05 -08:00
if ( rc )
2011-11-15 14:45:59 +01:00
IL_WARN ( " C_RXON_TIMING failed - " " Attempting to continue. \n " ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
il - > staging . filter_flags | = RXON_FILTER_ASSOC_MSK ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:57 +01:00
il - > staging . assoc_id = cpu_to_le16 ( il - > vif - > bss_conf . aid ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:57 +01:00
D_ASSOC ( " assoc id %d beacon interval %d \n " , il - > vif - > bss_conf . aid ,
il - > vif - > bss_conf . beacon_int ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:57 +01:00
if ( il - > vif - > bss_conf . use_short_preamble )
2012-02-03 17:31:37 +01:00
il - > staging . flags | = RXON_FLG_SHORT_PREAMBLE_MSK ;
2011-02-21 11:11:05 -08:00
else
2012-02-03 17:31:37 +01:00
il - > staging . flags & = ~ RXON_FLG_SHORT_PREAMBLE_MSK ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
if ( il - > staging . flags & RXON_FLG_BAND_24G_MSK ) {
2012-02-03 17:31:57 +01:00
if ( il - > vif - > bss_conf . use_short_slot )
2012-02-03 17:31:37 +01:00
il - > staging . flags | = RXON_FLG_SHORT_SLOT_MSK ;
2011-02-21 11:11:05 -08:00
else
2012-02-03 17:31:37 +01:00
il - > staging . flags & = ~ RXON_FLG_SHORT_SLOT_MSK ;
2011-02-21 11:11:05 -08:00
}
2012-02-03 17:31:57 +01:00
il3945_commit_rxon ( il ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:57 +01:00
switch ( il - > vif - > type ) {
2011-02-21 11:11:05 -08:00
case NL80211_IFTYPE_STATION :
2011-10-24 16:49:25 +02:00
il3945_rate_scale_init ( il - > hw , IL_AP_ID ) ;
2011-02-21 11:11:05 -08:00
break ;
case NL80211_IFTYPE_ADHOC :
2011-10-24 16:49:25 +02:00
il3945_send_beacon_cmd ( il ) ;
2011-02-21 11:11:05 -08:00
break ;
default :
2011-11-15 14:45:59 +01:00
IL_ERR ( " %s Should not be called in %d mode \n " , __func__ ,
2012-02-03 17:31:57 +01:00
il - > vif - > type ) ;
2011-02-21 11:11:05 -08:00
break ;
}
}
/*****************************************************************************
*
* mac80211 entry point functions
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define UCODE_READY_TIMEOUT (2 * HZ)
2011-11-15 14:45:59 +01:00
static int
il3945_mac_start ( struct ieee80211_hw * hw )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = hw - > priv ;
2011-02-21 11:11:05 -08:00
int ret ;
/* we should be verifying the device is ready to be opened */
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2012-02-13 11:23:21 +01:00
D_MAC80211 ( " enter \n " ) ;
2011-02-21 11:11:05 -08:00
/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
* ucode filename and max sizes are card - specific . */
2011-10-24 16:49:25 +02:00
if ( ! il - > ucode_code . len ) {
ret = il3945_read_ucode ( il ) ;
2011-02-21 11:11:05 -08:00
if ( ret ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Could not read microcode: %d \n " , ret ) ;
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
goto out_release_irq ;
}
}
2011-10-24 16:49:25 +02:00
ret = __il3945_up ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
if ( ret )
goto out_release_irq ;
2011-11-15 11:21:01 +01:00
D_INFO ( " Start UP work. \n " ) ;
2011-02-21 11:11:05 -08:00
/* Wait for START_ALIVE from ucode. Otherwise callbacks from
* mac80211 will not be run successfully . */
2011-10-24 16:49:25 +02:00
ret = wait_event_timeout ( il - > wait_command_queue ,
2011-11-15 14:45:59 +01:00
test_bit ( S_READY , & il - > status ) ,
UCODE_READY_TIMEOUT ) ;
2011-02-21 11:11:05 -08:00
if ( ! ret ) {
2011-11-15 13:09:01 +01:00
if ( ! test_bit ( S_READY , & il - > status ) ) {
2011-11-15 14:45:59 +01:00
IL_ERR ( " Wait for START_ALIVE timeout after %dms. \n " ,
jiffies_to_msecs ( UCODE_READY_TIMEOUT ) ) ;
2011-02-21 11:11:05 -08:00
ret = - ETIMEDOUT ;
goto out_release_irq ;
}
}
/* ucode is running and will send rfkill notifications,
* no need to poll the killswitch state anymore */
2011-10-24 16:49:25 +02:00
cancel_delayed_work ( & il - > _3945 . rfkill_poll ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > is_open = 1 ;
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " leave \n " ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
out_release_irq :
2011-10-24 16:49:25 +02:00
il - > is_open = 0 ;
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " leave - failed \n " ) ;
2011-02-21 11:11:05 -08:00
return ret ;
}
2011-11-15 14:45:59 +01:00
static void
il3945_mac_stop ( struct ieee80211_hw * hw )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = hw - > priv ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " enter \n " ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( ! il - > is_open ) {
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " leave - skip \n " ) ;
2011-02-21 11:11:05 -08:00
return ;
}
2011-10-24 16:49:25 +02:00
il - > is_open = 0 ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_down ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
flush_workqueue ( il - > workqueue ) ;
2011-02-21 11:11:05 -08:00
/* start polling the killswitch state again */
2011-10-24 16:49:25 +02:00
queue_delayed_work ( il - > workqueue , & il - > _3945 . rfkill_poll ,
2011-02-21 11:11:05 -08:00
round_jiffies_relative ( 2 * HZ ) ) ;
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " leave \n " ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
2012-07-23 21:33:42 +02:00
il3945_mac_tx ( struct ieee80211_hw * hw ,
struct ieee80211_tx_control * control ,
struct sk_buff * skb )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = hw - > priv ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " enter \n " ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:21:01 +01:00
D_TX ( " dev->xmit(%d bytes) at rate 0x%02x \n " , skb - > len ,
2011-11-15 14:45:59 +01:00
ieee80211_get_tx_rate ( hw , IEEE80211_SKB_CB ( skb ) ) - > bitrate ) ;
2011-02-21 11:11:05 -08:00
2012-07-23 21:33:42 +02:00
if ( il3945_tx_skb ( il , control - > sta , skb ) )
2011-02-21 11:11:05 -08:00
dev_kfree_skb_any ( skb ) ;
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " leave \n " ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
void
il3945_config_ap ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2012-02-03 17:31:57 +01:00
struct ieee80211_vif * vif = il - > vif ;
2011-02-21 11:11:05 -08:00
int rc = 0 ;
2011-11-15 13:09:01 +01:00
if ( test_bit ( S_EXIT_PENDING , & il - > status ) )
2011-02-21 11:11:05 -08:00
return ;
/* The following should be done only at AP bring up */
2011-11-15 11:29:04 +01:00
if ( ! ( il_is_associated ( il ) ) ) {
2011-02-21 11:11:05 -08:00
/* RXON - unassoc (to set timing command) */
2012-02-03 17:31:37 +01:00
il - > staging . filter_flags & = ~ RXON_FILTER_ASSOC_MSK ;
2012-02-03 17:31:57 +01:00
il3945_commit_rxon ( il ) ;
2011-02-21 11:11:05 -08:00
/* RXON Timing */
2012-02-03 17:31:57 +01:00
rc = il_send_rxon_timing ( il ) ;
2011-02-21 11:11:05 -08:00
if ( rc )
2011-08-30 15:26:35 +02:00
IL_WARN ( " C_RXON_TIMING failed - "
2011-11-15 14:45:59 +01:00
" Attempting to continue. \n " ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
il - > staging . assoc_id = 0 ;
2011-02-21 11:11:05 -08:00
if ( vif - > bss_conf . use_short_preamble )
2012-02-03 17:31:37 +01:00
il - > staging . flags | = RXON_FLG_SHORT_PREAMBLE_MSK ;
2011-02-21 11:11:05 -08:00
else
2012-02-03 17:31:37 +01:00
il - > staging . flags & = ~ RXON_FLG_SHORT_PREAMBLE_MSK ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
if ( il - > staging . flags & RXON_FLG_BAND_24G_MSK ) {
2011-02-21 11:11:05 -08:00
if ( vif - > bss_conf . use_short_slot )
2012-02-03 17:31:37 +01:00
il - > staging . flags | = RXON_FLG_SHORT_SLOT_MSK ;
2011-02-21 11:11:05 -08:00
else
2012-02-03 17:31:37 +01:00
il - > staging . flags & = ~ RXON_FLG_SHORT_SLOT_MSK ;
2011-02-21 11:11:05 -08:00
}
/* restore RXON assoc */
2012-02-03 17:31:37 +01:00
il - > staging . filter_flags | = RXON_FILTER_ASSOC_MSK ;
2012-02-03 17:31:57 +01:00
il3945_commit_rxon ( il ) ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 16:49:25 +02:00
il3945_send_beacon_cmd ( il ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static int
il3945_mac_set_key ( struct ieee80211_hw * hw , enum set_key_cmd cmd ,
struct ieee80211_vif * vif , struct ieee80211_sta * sta ,
struct ieee80211_key_conf * key )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = hw - > priv ;
2011-02-21 11:11:05 -08:00
int ret = 0 ;
2011-10-24 15:41:30 +02:00
u8 sta_id = IL_INVALID_STATION ;
2011-02-21 11:11:05 -08:00
u8 static_key ;
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " enter \n " ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
if ( il3945_mod_params . sw_crypto ) {
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " leave - hwcrypto disabled \n " ) ;
2011-02-21 11:11:05 -08:00
return - EOPNOTSUPP ;
}
/*
* To support IBSS RSN , don ' t program group keys in IBSS , the
* hardware will then not attempt to decrypt the frames .
*/
if ( vif - > type = = NL80211_IFTYPE_ADHOC & &
2012-02-13 11:23:21 +01:00
! ( key - > flags & IEEE80211_KEY_FLAG_PAIRWISE ) ) {
D_MAC80211 ( " leave - IBSS RSN \n " ) ;
2011-02-21 11:11:05 -08:00
return - EOPNOTSUPP ;
2012-02-13 11:23:21 +01:00
}
2011-02-21 11:11:05 -08:00
2011-11-15 11:29:04 +01:00
static_key = ! il_is_associated ( il ) ;
2011-02-21 11:11:05 -08:00
if ( ! static_key ) {
2012-02-03 17:31:57 +01:00
sta_id = il_sta_id_or_broadcast ( il , sta ) ;
2012-02-13 11:23:21 +01:00
if ( sta_id = = IL_INVALID_STATION ) {
D_MAC80211 ( " leave - station not found \n " ) ;
2011-02-21 11:11:05 -08:00
return - EINVAL ;
2012-02-13 11:23:21 +01:00
}
2011-02-21 11:11:05 -08:00
}
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
il_scan_cancel_timeout ( il , 100 ) ;
2011-02-21 11:11:05 -08:00
switch ( cmd ) {
case SET_KEY :
if ( static_key )
2011-10-24 16:49:25 +02:00
ret = il3945_set_static_key ( il , key ) ;
2011-02-21 11:11:05 -08:00
else
2011-10-24 16:49:25 +02:00
ret = il3945_set_dynamic_key ( il , key , sta_id ) ;
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " enable hwcrypto key \n " ) ;
2011-02-21 11:11:05 -08:00
break ;
case DISABLE_KEY :
if ( static_key )
2011-10-24 16:49:25 +02:00
ret = il3945_remove_static_key ( il ) ;
2011-02-21 11:11:05 -08:00
else
2011-10-24 16:49:25 +02:00
ret = il3945_clear_sta_key_info ( il , sta_id ) ;
2011-11-15 11:21:01 +01:00
D_MAC80211 ( " disable hwcrypto key \n " ) ;
2011-02-21 11:11:05 -08:00
break ;
default :
ret = - EINVAL ;
}
2012-02-13 11:23:21 +01:00
D_MAC80211 ( " leave ret %d \n " , ret ) ;
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
return ret ;
}
2011-11-15 14:45:59 +01:00
static int
il3945_mac_sta_add ( struct ieee80211_hw * hw , struct ieee80211_vif * vif ,
struct ieee80211_sta * sta )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = hw - > priv ;
2011-10-24 15:41:30 +02:00
struct il3945_sta_priv * sta_priv = ( void * ) sta - > drv_priv ;
2011-02-21 11:11:05 -08:00
int ret ;
bool is_ap = vif - > type = = NL80211_IFTYPE_STATION ;
u8 sta_id ;
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2012-02-13 11:23:21 +01:00
D_INFO ( " station %pM \n " , sta - > addr ) ;
2011-10-24 15:41:30 +02:00
sta_priv - > common . sta_id = IL_INVALID_STATION ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:57 +01:00
ret = il_add_station_common ( il , sta - > addr , is_ap , sta , & sta_id ) ;
2011-02-21 11:11:05 -08:00
if ( ret ) {
2011-11-15 14:45:59 +01:00
IL_ERR ( " Unable to add station %pM (%d) \n " , sta - > addr , ret ) ;
2011-02-21 11:11:05 -08:00
/* Should we return success if return code is EEXIST ? */
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
return ret ;
}
sta_priv - > common . sta_id = sta_id ;
/* Initialize rate scaling */
2011-11-15 14:45:59 +01:00
D_INFO ( " Initializing rate scaling for station %pM \n " , sta - > addr ) ;
2011-10-24 16:49:25 +02:00
il3945_rs_rate_init ( il , sta , sta_id ) ;
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
2011-11-15 14:45:59 +01:00
static void
il3945_configure_filter ( struct ieee80211_hw * hw , unsigned int changed_flags ,
unsigned int * total_flags , u64 multicast )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = hw - > priv ;
2011-02-21 11:11:05 -08:00
__le32 filter_or = 0 , filter_nand = 0 ;
# define CHK(test, flag) do { \
if ( * total_flags & ( test ) ) \
filter_or | = ( flag ) ; \
else \
filter_nand | = ( flag ) ; \
} while ( 0 )
2011-11-15 14:45:59 +01:00
D_MAC80211 ( " Enter: changed: 0x%x, total: 0x%x \n " , changed_flags ,
* total_flags ) ;
2011-02-21 11:11:05 -08:00
2015-04-22 14:40:58 +02:00
CHK ( FIF_OTHER_BSS , RXON_FILTER_PROMISC_MSK ) ;
2011-02-21 11:11:05 -08:00
CHK ( FIF_CONTROL , RXON_FILTER_CTL2HOST_MSK ) ;
CHK ( FIF_BCN_PRBRESP_PROMISC , RXON_FILTER_BCON_AWARE_MSK ) ;
# undef CHK
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
il - > staging . filter_flags & = ~ filter_nand ;
il - > staging . filter_flags | = filter_or ;
2011-02-21 11:11:05 -08:00
/*
* Not committing directly because hardware can perform a scan ,
* but even if hw is ready , committing here breaks for some reason ,
* we ' ll eventually commit the filter flags change anyway .
*/
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
/*
* Receiving all multicast frames is always enabled by the
2011-10-24 15:41:30 +02:00
* default flags setup in il_connection_init_rx_config ( )
2011-02-21 11:11:05 -08:00
* since we currently do not support programming multicast
* filters into the device .
*/
2011-11-15 14:45:59 +01:00
* total_flags & =
2015-04-22 14:40:58 +02:00
FIF_OTHER_BSS | FIF_ALLMULTI |
2011-11-15 14:45:59 +01:00
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL ;
2011-02-21 11:11:05 -08:00
}
/*****************************************************************************
*
* sysfs attributes
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-02-21 11:11:05 -08:00
/*
* The following adds a new attribute to the sysfs representation
* of this device driver ( i . e . a new file in / sys / bus / pci / drivers / iwl / )
* used for controlling the debug level .
*
* See the level definitions in iwl for details .
*
* The debug_level being managed using sysfs below is a per device debug
* level that is used instead of the global debug level if it ( the per
* device debug level ) is set .
*/
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_debug_level ( struct device * d , struct device_attribute * attr ,
char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
return sprintf ( buf , " 0x%08X \n " , il_get_debug_level ( il ) ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_store_debug_level ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t count )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
unsigned long val ;
int ret ;
2013-05-31 21:24:06 +00:00
ret = kstrtoul ( buf , 0 , & val ) ;
2011-02-21 11:11:05 -08:00
if ( ret )
2011-08-18 22:07:57 +02:00
IL_INFO ( " %s is not in hex or decimal form. \n " , buf ) ;
2012-02-13 11:23:20 +01:00
else
2011-10-24 16:49:25 +02:00
il - > debug_level = val ;
2012-02-13 11:23:20 +01:00
2011-02-21 11:11:05 -08:00
return strnlen ( buf , count ) ;
}
2011-11-15 14:45:59 +01:00
static DEVICE_ATTR ( debug_level , S_IWUSR | S_IRUGO , il3945_show_debug_level ,
il3945_store_debug_level ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 11:25:42 +01:00
# endif /* CONFIG_IWLEGACY_DEBUG */
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_temperature ( struct device * d , struct device_attribute * attr ,
char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( ! il_is_alive ( il ) )
2011-02-21 11:11:05 -08:00
return - EAGAIN ;
2011-10-24 16:49:25 +02:00
return sprintf ( buf , " %d \n " , il3945_hw_get_temperature ( il ) ) ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 15:41:30 +02:00
static DEVICE_ATTR ( temperature , S_IRUGO , il3945_show_temperature , NULL ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_tx_power ( struct device * d , struct device_attribute * attr , char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
return sprintf ( buf , " %d \n " , il - > tx_power_user_lmt ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_store_tx_power ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t count )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
char * p = ( char * ) buf ;
u32 val ;
val = simple_strtoul ( p , & p , 10 ) ;
if ( p = = buf )
2011-08-18 22:07:57 +02:00
IL_INFO ( " : %s is not in decimal form. \n " , buf ) ;
2011-02-21 11:11:05 -08:00
else
2011-10-24 16:49:25 +02:00
il3945_hw_reg_set_txpower ( il , val ) ;
2011-02-21 11:11:05 -08:00
return count ;
}
2011-11-15 14:45:59 +01:00
static DEVICE_ATTR ( tx_power , S_IWUSR | S_IRUGO , il3945_show_tx_power ,
il3945_store_tx_power ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_flags ( struct device * d , struct device_attribute * attr , char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
return sprintf ( buf , " 0x%04X \n " , il - > active . flags ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_store_flags ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t count )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
u32 flags = simple_strtoul ( buf , NULL , 0 ) ;
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2012-02-03 17:31:37 +01:00
if ( le32_to_cpu ( il - > staging . flags ) ! = flags ) {
2011-02-21 11:11:05 -08:00
/* Cancel any currently running scans... */
2011-10-24 16:49:25 +02:00
if ( il_scan_cancel_timeout ( il , 100 ) )
2011-08-18 22:07:57 +02:00
IL_WARN ( " Could not cancel scan. \n " ) ;
2011-02-21 11:11:05 -08:00
else {
2011-11-15 14:45:59 +01:00
D_INFO ( " Committing rxon.flags = 0x%04X \n " , flags ) ;
2012-02-03 17:31:37 +01:00
il - > staging . flags = cpu_to_le32 ( flags ) ;
2012-02-03 17:31:57 +01:00
il3945_commit_rxon ( il ) ;
2011-02-21 11:11:05 -08:00
}
}
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
return count ;
}
2011-11-15 14:45:59 +01:00
static DEVICE_ATTR ( flags , S_IWUSR | S_IRUGO , il3945_show_flags ,
il3945_store_flags ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_filter_flags ( struct device * d , struct device_attribute * attr ,
char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:37 +01:00
return sprintf ( buf , " 0x%04X \n " , le32_to_cpu ( il - > active . filter_flags ) ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_store_filter_flags ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t count )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
u32 filter_flags = simple_strtoul ( buf , NULL , 0 ) ;
2011-10-24 16:49:25 +02:00
mutex_lock ( & il - > mutex ) ;
2012-02-03 17:31:37 +01:00
if ( le32_to_cpu ( il - > staging . filter_flags ) ! = filter_flags ) {
2011-02-21 11:11:05 -08:00
/* Cancel any currently running scans... */
2011-10-24 16:49:25 +02:00
if ( il_scan_cancel_timeout ( il , 100 ) )
2011-08-18 22:07:57 +02:00
IL_WARN ( " Could not cancel scan. \n " ) ;
2011-02-21 11:11:05 -08:00
else {
2011-11-15 14:45:59 +01:00
D_INFO ( " Committing rxon.filter_flags = " " 0x%04X \n " ,
filter_flags ) ;
2012-02-03 17:31:37 +01:00
il - > staging . filter_flags = cpu_to_le32 ( filter_flags ) ;
2012-02-03 17:31:57 +01:00
il3945_commit_rxon ( il ) ;
2011-02-21 11:11:05 -08:00
}
}
2011-10-24 16:49:25 +02:00
mutex_unlock ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
return count ;
}
2011-10-24 15:41:30 +02:00
static DEVICE_ATTR ( filter_flags , S_IWUSR | S_IRUGO , il3945_show_filter_flags ,
il3945_store_filter_flags ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_measurement ( struct device * d , struct device_attribute * attr ,
char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-10-24 15:41:30 +02:00
struct il_spectrum_notification measure_report ;
2011-02-21 11:11:05 -08:00
u32 size = sizeof ( measure_report ) , len = 0 , ofs = 0 ;
2011-11-15 14:51:01 +01:00
u8 * data = ( u8 * ) & measure_report ;
2011-02-21 11:11:05 -08:00
unsigned long flags ;
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
if ( ! ( il - > measurement_status & MEASUREMENT_READY ) ) {
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
2011-10-24 16:49:25 +02:00
memcpy ( & measure_report , & il - > measure_report , size ) ;
il - > measurement_status = 0 ;
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
2011-08-26 10:45:16 +02:00
while ( size & & PAGE_SIZE - len ) {
2011-02-21 11:11:05 -08:00
hex_dump_to_buffer ( data + ofs , size , 16 , 1 , buf + len ,
iwlegacy: convert hex_dump_to_buffer() to %*ph
There is no need to use hex_dump_to_buffer() in the cases like this:
hexdump_to_buffer(buf, len, 16, 1, outbuf, outlen, false); /* len <= 16 */
sprintf("%s\n", outbuf);
since it maybe easily converted to simple:
sprintf("%*ph\n", len, buf);
Note: it seems in the case the output is groupped by 2 bytes and looks like a
typo. Thus, patch changes that to plain byte stream.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
2015-07-16 15:42:15 +03:00
PAGE_SIZE - len , true ) ;
2011-02-21 11:11:05 -08:00
len = strlen ( buf ) ;
if ( PAGE_SIZE - len )
buf [ len + + ] = ' \n ' ;
ofs + = 16 ;
size - = min ( size , 16U ) ;
}
return len ;
}
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_store_measurement ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t count )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
struct ieee80211_measurement_params params = {
2012-02-03 17:31:37 +01:00
. channel = le16_to_cpu ( il - > active . channel ) ,
2011-10-24 16:49:25 +02:00
. start_time = cpu_to_le64 ( il - > _3945 . last_tsf ) ,
2011-02-21 11:11:05 -08:00
. duration = cpu_to_le16 ( 1 ) ,
} ;
2011-10-24 15:41:30 +02:00
u8 type = IL_MEASURE_BASIC ;
2011-02-21 11:11:05 -08:00
u8 buffer [ 32 ] ;
u8 channel ;
if ( count ) {
char * p = buffer ;
2013-01-07 12:42:46 +08:00
strlcpy ( buffer , buf , sizeof ( buffer ) ) ;
2011-02-21 11:11:05 -08:00
channel = simple_strtoul ( p , NULL , 0 ) ;
if ( channel )
params . channel = channel ;
p = buffer ;
while ( * p & & * p ! = ' ' )
p + + ;
if ( * p )
type = simple_strtoul ( p + 1 , NULL , 0 ) ;
}
2011-11-15 14:45:59 +01:00
D_INFO ( " Invoking measurement of type %d on " " channel %d (for '%s') \n " ,
type , params . channel , buf ) ;
2011-10-24 16:49:25 +02:00
il3945_get_measurement ( il , & params , type ) ;
2011-02-21 11:11:05 -08:00
return count ;
}
2011-11-15 14:45:59 +01:00
static DEVICE_ATTR ( measurement , S_IRUSR | S_IWUSR , il3945_show_measurement ,
il3945_store_measurement ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_store_retry_rate ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t count )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > retry_rate = simple_strtoul ( buf , NULL , 0 ) ;
if ( il - > retry_rate < = 0 )
il - > retry_rate = 1 ;
2011-02-21 11:11:05 -08:00
return count ;
}
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_retry_rate ( struct device * d , struct device_attribute * attr ,
char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
return sprintf ( buf , " %d " , il - > retry_rate ) ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 15:41:30 +02:00
static DEVICE_ATTR ( retry_rate , S_IWUSR | S_IRUSR , il3945_show_retry_rate ,
il3945_store_retry_rate ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_channels ( struct device * d , struct device_attribute * attr , char * buf )
2011-02-21 11:11:05 -08:00
{
/* all this shit doesn't belong into sysfs anyway */
return 0 ;
}
2011-10-24 15:41:30 +02:00
static DEVICE_ATTR ( channels , S_IRUSR , il3945_show_channels , NULL ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_antenna ( struct device * d , struct device_attribute * attr , char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( ! il_is_alive ( il ) )
2011-02-21 11:11:05 -08:00
return - EAGAIN ;
2011-10-24 15:41:30 +02:00
return sprintf ( buf , " %d \n " , il3945_mod_params . antenna ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_store_antenna ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t count )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il __maybe_unused = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
int ant ;
if ( count = = 0 )
return 0 ;
if ( sscanf ( buf , " %1i " , & ant ) ! = 1 ) {
2011-11-15 11:21:01 +01:00
D_INFO ( " not in hex or decimal form. \n " ) ;
2011-02-21 11:11:05 -08:00
return count ;
}
2011-08-26 10:45:16 +02:00
if ( ant > = 0 & & ant < = 2 ) {
2011-11-15 11:21:01 +01:00
D_INFO ( " Setting antenna select to %d. \n " , ant ) ;
2011-10-24 15:41:30 +02:00
il3945_mod_params . antenna = ( enum il3945_antenna ) ant ;
2011-02-21 11:11:05 -08:00
} else
2011-11-15 11:21:01 +01:00
D_INFO ( " Bad antenna select value %d. \n " , ant ) ;
2011-02-21 11:11:05 -08:00
return count ;
}
2011-11-15 14:45:59 +01:00
static DEVICE_ATTR ( antenna , S_IWUSR | S_IRUGO , il3945_show_antenna ,
il3945_store_antenna ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_show_status ( struct device * d , struct device_attribute * attr , char * buf )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
if ( ! il_is_alive ( il ) )
2011-02-21 11:11:05 -08:00
return - EAGAIN ;
2011-10-24 16:49:25 +02:00
return sprintf ( buf , " 0x%08x \n " , ( int ) il - > status ) ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 15:41:30 +02:00
static DEVICE_ATTR ( status , S_IRUGO , il3945_show_status , NULL ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static ssize_t
il3945_dump_error_log ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t count )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = dev_get_drvdata ( d ) ;
2011-02-21 11:11:05 -08:00
char * p = ( char * ) buf ;
if ( p [ 0 ] = = ' 1 ' )
2011-10-24 16:49:25 +02:00
il3945_dump_nic_error_log ( il ) ;
2011-02-21 11:11:05 -08:00
return strnlen ( buf , count ) ;
}
2011-10-24 15:41:30 +02:00
static DEVICE_ATTR ( dump_errors , S_IWUSR , NULL , il3945_dump_error_log ) ;
2011-02-21 11:11:05 -08:00
/*****************************************************************************
*
* driver setup and tear down
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-11-15 14:45:59 +01:00
static void
il3945_setup_deferred_work ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
il - > workqueue = create_singlethread_workqueue ( DRV_NAME ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
init_waitqueue_head ( & il - > wait_command_queue ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
INIT_WORK ( & il - > restart , il3945_bg_restart ) ;
INIT_WORK ( & il - > rx_replenish , il3945_bg_rx_replenish ) ;
INIT_DELAYED_WORK ( & il - > init_alive_start , il3945_bg_init_alive_start ) ;
INIT_DELAYED_WORK ( & il - > alive_start , il3945_bg_alive_start ) ;
INIT_DELAYED_WORK ( & il - > _3945 . rfkill_poll , il3945_rfkill_poll ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_setup_scan_deferred_work ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_hw_setup_deferred_work ( il ) ;
2011-02-21 11:11:05 -08:00
2014-12-26 15:35:49 +01:00
setup_timer ( & il - > watchdog , il_bg_watchdog , ( unsigned long ) il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
tasklet_init ( & il - > irq_tasklet ,
( void ( * ) ( unsigned long ) ) il3945_irq_tasklet ,
( unsigned long ) il ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 14:45:59 +01:00
static void
il3945_cancel_deferred_work ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
il3945_hw_cancel_deferred_work ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
cancel_delayed_work_sync ( & il - > init_alive_start ) ;
cancel_delayed_work ( & il - > alive_start ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_cancel_scan_deferred_work ( il ) ;
2011-02-21 11:11:05 -08:00
}
2011-10-24 15:41:30 +02:00
static struct attribute * il3945_sysfs_entries [ ] = {
2011-02-21 11:11:05 -08:00
& dev_attr_antenna . attr ,
& dev_attr_channels . attr ,
& dev_attr_dump_errors . attr ,
& dev_attr_flags . attr ,
& dev_attr_filter_flags . attr ,
& dev_attr_measurement . attr ,
& dev_attr_retry_rate . attr ,
& dev_attr_status . attr ,
& dev_attr_temperature . attr ,
& dev_attr_tx_power . attr ,
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-02-21 11:11:05 -08:00
& dev_attr_debug_level . attr ,
# endif
NULL
} ;
2011-10-24 15:41:30 +02:00
static struct attribute_group il3945_attribute_group = {
2011-02-21 11:11:05 -08:00
. name = NULL , /* put in device directory */
2011-10-24 15:41:30 +02:00
. attrs = il3945_sysfs_entries ,
2011-02-21 11:11:05 -08:00
} ;
2013-03-08 11:12:56 -08:00
static struct ieee80211_ops il3945_mac_ops __read_mostly = {
2011-10-24 15:41:30 +02:00
. tx = il3945_mac_tx ,
. start = il3945_mac_start ,
. stop = il3945_mac_stop ,
. add_interface = il_mac_add_interface ,
. remove_interface = il_mac_remove_interface ,
. change_interface = il_mac_change_interface ,
. config = il_mac_config ,
. configure_filter = il3945_configure_filter ,
. set_key = il3945_mac_set_key ,
. conf_tx = il_mac_conf_tx ,
. reset_tsf = il_mac_reset_tsf ,
. bss_info_changed = il_mac_bss_info_changed ,
. hw_scan = il_mac_hw_scan ,
. sta_add = il3945_mac_sta_add ,
. sta_remove = il_mac_sta_remove ,
. tx_last_beacon = il_mac_tx_last_beacon ,
2012-12-20 14:31:51 +01:00
. flush = il_mac_flush ,
2011-02-21 11:11:05 -08:00
} ;
2011-11-15 14:45:59 +01:00
static int
il3945_init_drv ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
int ret ;
2011-10-24 16:49:25 +02:00
struct il3945_eeprom * eeprom = ( struct il3945_eeprom * ) il - > eeprom ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > retry_rate = 1 ;
il - > beacon_skb = NULL ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
spin_lock_init ( & il - > sta_lock ) ;
spin_lock_init ( & il - > hcmd_lock ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
INIT_LIST_HEAD ( & il - > free_frames ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
mutex_init ( & il - > mutex ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > ieee_channels = NULL ;
il - > ieee_rates = NULL ;
il - > band = IEEE80211_BAND_2GHZ ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il - > iw_mode = NL80211_IFTYPE_STATION ;
il - > missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF ;
2011-02-21 11:11:05 -08:00
/* initialize force reset */
2011-10-24 16:49:25 +02:00
il - > force_reset . reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD ;
2011-02-21 11:11:05 -08:00
if ( eeprom - > version < EEPROM_3945_EEPROM_VERSION ) {
2011-08-18 22:07:57 +02:00
IL_WARN ( " Unsupported EEPROM version: 0x%04X \n " ,
2011-11-15 14:45:59 +01:00
eeprom - > version ) ;
2011-02-21 11:11:05 -08:00
ret = - EINVAL ;
goto err ;
}
2011-10-24 16:49:25 +02:00
ret = il_init_channel_map ( il ) ;
2011-02-21 11:11:05 -08:00
if ( ret ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " initializing regulatory failed: %d \n " , ret ) ;
2011-02-21 11:11:05 -08:00
goto err ;
}
/* Set up txpower settings in driver for all channels */
2011-10-24 16:49:25 +02:00
if ( il3945_txpower_set_from_eeprom ( il ) ) {
2011-02-21 11:11:05 -08:00
ret = - EIO ;
goto err_free_channel_map ;
}
2011-10-24 16:49:25 +02:00
ret = il_init_geos ( il ) ;
2011-02-21 11:11:05 -08:00
if ( ret ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " initializing geos failed: %d \n " , ret ) ;
2011-02-21 11:11:05 -08:00
goto err_free_channel_map ;
}
2011-10-24 16:49:25 +02:00
il3945_init_hw_rates ( il , il - > ieee_rates ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
err_free_channel_map :
2011-10-24 16:49:25 +02:00
il_free_channel_map ( il ) ;
2011-02-21 11:11:05 -08:00
err :
return ret ;
}
2011-11-15 11:25:42 +01:00
# define IL3945_MAX_PROBE_REQUEST 200
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
static int
il3945_setup_mac ( struct il_priv * il )
2011-02-21 11:11:05 -08:00
{
int ret ;
2011-10-24 16:49:25 +02:00
struct ieee80211_hw * hw = il - > hw ;
2011-02-21 11:11:05 -08:00
hw - > rate_control_algorithm = " iwl-3945-rs " ;
2011-10-24 15:41:30 +02:00
hw - > sta_data_size = sizeof ( struct il3945_sta_priv ) ;
hw - > vif_data_size = sizeof ( struct il_vif_priv ) ;
2011-02-21 11:11:05 -08:00
/* Tell mac80211 our characteristics */
2015-06-02 21:39:54 +02:00
ieee80211_hw_set ( hw , SUPPORTS_DYNAMIC_PS ) ;
ieee80211_hw_set ( hw , SUPPORTS_PS ) ;
ieee80211_hw_set ( hw , SIGNAL_DBM ) ;
ieee80211_hw_set ( hw , SPECTRUM_MGMT ) ;
2011-02-21 11:11:05 -08:00
2012-02-03 17:31:50 +01:00
hw - > wiphy - > interface_modes =
BIT ( NL80211_IFTYPE_STATION ) | BIT ( NL80211_IFTYPE_ADHOC ) ;
2011-02-21 11:11:05 -08:00
2013-11-11 22:15:29 +01:00
hw - > wiphy - > flags | = WIPHY_FLAG_IBSS_RSN ;
hw - > wiphy - > regulatory_flags | = REGULATORY_CUSTOM_REG |
REGULATORY_DISABLE_BEACON_HINTS ;
2011-02-21 11:11:05 -08:00
2012-12-20 14:31:53 +01:00
hw - > wiphy - > flags & = ~ WIPHY_FLAG_PS_ON_BY_DEFAULT ;
2011-02-21 11:11:05 -08:00
hw - > wiphy - > max_scan_ssids = PROBE_OPTION_MAX_3945 ;
/* we create the 802.11 header and a zero-length SSID element */
2011-11-15 11:25:42 +01:00
hw - > wiphy - > max_scan_ie_len = IL3945_MAX_PROBE_REQUEST - 24 - 2 ;
2011-02-21 11:11:05 -08:00
/* Default value; 4 EDCA QOS priorities */
hw - > queues = 4 ;
2011-10-24 16:49:25 +02:00
if ( il - > bands [ IEEE80211_BAND_2GHZ ] . n_channels )
il - > hw - > wiphy - > bands [ IEEE80211_BAND_2GHZ ] =
2011-11-15 14:45:59 +01:00
& il - > bands [ IEEE80211_BAND_2GHZ ] ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( il - > bands [ IEEE80211_BAND_5GHZ ] . n_channels )
il - > hw - > wiphy - > bands [ IEEE80211_BAND_5GHZ ] =
2011-11-15 14:45:59 +01:00
& il - > bands [ IEEE80211_BAND_5GHZ ] ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_leds_init ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
ret = ieee80211_register_hw ( il - > hw ) ;
2011-02-21 11:11:05 -08:00
if ( ret ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Failed to register hw (error %d) \n " , ret ) ;
2011-02-21 11:11:05 -08:00
return ret ;
}
2011-10-24 16:49:25 +02:00
il - > mac80211_registered = 1 ;
2011-02-21 11:11:05 -08:00
return 0 ;
}
2011-11-15 14:45:59 +01:00
static int
il3945_pci_probe ( struct pci_dev * pdev , const struct pci_device_id * ent )
2011-02-21 11:11:05 -08:00
{
2011-11-15 11:29:04 +01:00
int err = 0 ;
2011-10-24 16:49:25 +02:00
struct il_priv * il ;
2011-02-21 11:11:05 -08:00
struct ieee80211_hw * hw ;
2011-10-24 15:41:30 +02:00
struct il_cfg * cfg = ( struct il_cfg * ) ( ent - > driver_data ) ;
struct il3945_eeprom * eeprom ;
2011-02-21 11:11:05 -08:00
unsigned long flags ;
/***********************
* 1. Allocating HW data
* * * * * * * * * * * * * * * * * * * * */
2012-02-03 17:31:58 +01:00
hw = ieee80211_alloc_hw ( sizeof ( struct il_priv ) , & il3945_mac_ops ) ;
if ( ! hw ) {
2011-02-21 11:11:05 -08:00
err = - ENOMEM ;
goto out ;
}
2011-10-24 16:49:25 +02:00
il = hw - > priv ;
2012-02-03 17:31:58 +01:00
il - > hw = hw ;
2011-02-21 11:11:05 -08:00
SET_IEEE80211_DEV ( hw , & pdev - > dev ) ;
2011-11-15 11:25:42 +01:00
il - > cmd_queue = IL39_CMD_QUEUE_NUM ;
2011-02-21 11:11:05 -08:00
/*
* Disabling hardware scan means that mac80211 will perform scans
* " the hard way " , rather than using device ' s scan .
*/
2011-10-24 15:41:30 +02:00
if ( il3945_mod_params . disable_hw_scan ) {
2011-11-15 11:21:01 +01:00
D_INFO ( " Disabling hw_scan \n " ) ;
2012-02-03 17:31:58 +01:00
il3945_mac_ops . hw_scan = NULL ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 11:21:01 +01:00
D_INFO ( " *** LOAD DRIVER *** \n " ) ;
2011-10-24 16:49:25 +02:00
il - > cfg = cfg ;
2012-02-03 17:31:58 +01:00
il - > ops = & il3945_ops ;
2012-02-13 11:23:14 +01:00
# ifdef CONFIG_IWLEGACY_DEBUGFS
il - > debugfs_ops = & il3945_debugfs_ops ;
# endif
2011-10-24 16:49:25 +02:00
il - > pci_dev = pdev ;
il - > inta_mask = CSR_INI_SET_MASK ;
2011-02-21 11:11:05 -08:00
/***************************
* 2. Initializing PCI bus
* * * * * * * * * * * * * * * * * * * * * * * * * */
2011-11-15 14:45:59 +01:00
pci_disable_link_state ( pdev ,
PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
PCIE_LINK_STATE_CLKPM ) ;
2011-02-21 11:11:05 -08:00
if ( pci_enable_device ( pdev ) ) {
err = - ENODEV ;
goto out_ieee80211_free_hw ;
}
pci_set_master ( pdev ) ;
err = pci_set_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ;
if ( ! err )
err = pci_set_consistent_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ;
if ( err ) {
2011-08-18 22:07:57 +02:00
IL_WARN ( " No suitable DMA available. \n " ) ;
2011-02-21 11:11:05 -08:00
goto out_pci_disable_device ;
}
2011-10-24 16:49:25 +02:00
pci_set_drvdata ( pdev , il ) ;
2011-02-21 11:11:05 -08:00
err = pci_request_regions ( pdev , DRV_NAME ) ;
if ( err )
goto out_pci_disable_device ;
/***********************
* 3. Read REV Register
* * * * * * * * * * * * * * * * * * * * */
2012-02-13 11:23:11 +01:00
il - > hw_base = pci_ioremap_bar ( pdev , 0 ) ;
2011-10-24 16:49:25 +02:00
if ( ! il - > hw_base ) {
2011-02-21 11:11:05 -08:00
err = - ENODEV ;
goto out_pci_release_regions ;
}
2011-11-15 11:21:01 +01:00
D_INFO ( " pci_resource_len = 0x%08llx \n " ,
2011-11-15 14:45:59 +01:00
( unsigned long long ) pci_resource_len ( pdev , 0 ) ) ;
2011-11-15 11:21:01 +01:00
D_INFO ( " pci_resource_base = %p \n " , il - > hw_base ) ;
2011-02-21 11:11:05 -08:00
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte ( pdev , 0x41 , 0x00 ) ;
2012-02-13 11:23:17 +01:00
/* these spin locks will be used in apm_init and EEPROM access
2011-02-21 11:11:05 -08:00
* we should init now
*/
2011-10-24 16:49:25 +02:00
spin_lock_init ( & il - > reg_lock ) ;
spin_lock_init ( & il - > lock ) ;
2011-02-21 11:11:05 -08:00
/*
* stop and reset the on - board processor just in case it is in a
* strange state . . . like being left stranded by a primary kernel
* and this is now the kdump kernel trying to start up
*/
2011-08-24 15:14:03 +02:00
_il_wr ( il , CSR_RESET , CSR_RESET_REG_FLAG_NEVO_RESET ) ;
2011-02-21 11:11:05 -08:00
/***********************
* 4. Read EEPROM
* * * * * * * * * * * * * * * * * * * * */
/* Read the EEPROM */
2011-10-24 16:49:25 +02:00
err = il_eeprom_init ( il ) ;
2011-02-21 11:11:05 -08:00
if ( err ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Unable to init EEPROM \n " ) ;
2011-02-21 11:11:05 -08:00
goto out_iounmap ;
}
/* MAC Address location in EEPROM same for 3945/4965 */
2011-10-24 16:49:25 +02:00
eeprom = ( struct il3945_eeprom * ) il - > eeprom ;
2011-11-15 11:21:01 +01:00
D_INFO ( " MAC address: %pM \n " , eeprom - > mac_address ) ;
2011-10-24 16:49:25 +02:00
SET_IEEE80211_PERM_ADDR ( il - > hw , eeprom - > mac_address ) ;
2011-02-21 11:11:05 -08:00
/***********************
* 5. Setup HW Constants
* * * * * * * * * * * * * * * * * * * * */
/* Device-specific setup */
2013-06-05 10:16:33 +08:00
err = il3945_hw_set_hw_params ( il ) ;
if ( err ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " failed to set hw settings \n " ) ;
2011-02-21 11:11:05 -08:00
goto out_eeprom_free ;
}
/***********************
2011-10-24 16:49:25 +02:00
* 6. Setup il
2011-02-21 11:11:05 -08:00
* * * * * * * * * * * * * * * * * * * * */
2011-10-24 16:49:25 +02:00
err = il3945_init_drv ( il ) ;
2011-02-21 11:11:05 -08:00
if ( err ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " initializing driver failed \n " ) ;
2011-02-21 11:11:05 -08:00
goto out_unset_hw_params ;
}
2011-11-15 14:45:59 +01:00
IL_INFO ( " Detected Intel Wireless WiFi Link %s \n " , il - > cfg - > name ) ;
2011-02-21 11:11:05 -08:00
/***********************
* 7. Setup Services
* * * * * * * * * * * * * * * * * * * * */
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
il_disable_interrupts ( il ) ;
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
pci_enable_msi ( il - > pci_dev ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 14:45:59 +01:00
err = request_irq ( il - > pci_dev - > irq , il_isr , IRQF_SHARED , DRV_NAME , il ) ;
2011-02-21 11:11:05 -08:00
if ( err ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " Error allocating IRQ %d \n " , il - > pci_dev - > irq ) ;
2011-02-21 11:11:05 -08:00
goto out_disable_msi ;
}
2011-10-24 15:41:30 +02:00
err = sysfs_create_group ( & pdev - > dev . kobj , & il3945_attribute_group ) ;
2011-02-21 11:11:05 -08:00
if ( err ) {
2011-08-18 22:07:57 +02:00
IL_ERR ( " failed to create sysfs device attributes \n " ) ;
2011-02-21 11:11:05 -08:00
goto out_release_irq ;
}
2012-02-03 17:31:57 +01:00
il_set_rxon_channel ( il , & il - > bands [ IEEE80211_BAND_2GHZ ] . channels [ 5 ] ) ;
2011-10-24 16:49:25 +02:00
il3945_setup_deferred_work ( il ) ;
2011-08-30 15:39:42 +02:00
il3945_setup_handlers ( il ) ;
2011-10-24 16:49:25 +02:00
il_power_initialize ( il ) ;
2011-02-21 11:11:05 -08:00
/*********************************
* 8. Setup and Register mac80211
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-10-24 16:49:25 +02:00
il_enable_interrupts ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
err = il3945_setup_mac ( il ) ;
2011-02-21 11:11:05 -08:00
if ( err )
2011-11-15 14:45:59 +01:00
goto out_remove_sysfs ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
err = il_dbgfs_register ( il , DRV_NAME ) ;
2011-02-21 11:11:05 -08:00
if ( err )
2011-11-15 14:45:59 +01:00
IL_ERR ( " failed to create debugfs files. Ignoring error: %d \n " ,
err ) ;
2011-02-21 11:11:05 -08:00
/* Start monitoring the killswitch */
2011-11-15 14:45:59 +01:00
queue_delayed_work ( il - > workqueue , & il - > _3945 . rfkill_poll , 2 * HZ ) ;
2011-02-21 11:11:05 -08:00
return 0 ;
2011-11-15 14:45:59 +01:00
out_remove_sysfs :
2011-10-24 16:49:25 +02:00
destroy_workqueue ( il - > workqueue ) ;
il - > workqueue = NULL ;
2011-10-24 15:41:30 +02:00
sysfs_remove_group ( & pdev - > dev . kobj , & il3945_attribute_group ) ;
2011-11-15 14:45:59 +01:00
out_release_irq :
2011-10-24 16:49:25 +02:00
free_irq ( il - > pci_dev - > irq , il ) ;
2011-11-15 14:45:59 +01:00
out_disable_msi :
2011-10-24 16:49:25 +02:00
pci_disable_msi ( il - > pci_dev ) ;
il_free_geos ( il ) ;
il_free_channel_map ( il ) ;
2011-11-15 14:45:59 +01:00
out_unset_hw_params :
2011-10-24 16:49:25 +02:00
il3945_unset_hw_params ( il ) ;
2011-11-15 14:45:59 +01:00
out_eeprom_free :
2011-10-24 16:49:25 +02:00
il_eeprom_free ( il ) ;
2011-11-15 14:45:59 +01:00
out_iounmap :
2012-02-13 11:23:11 +01:00
iounmap ( il - > hw_base ) ;
2011-11-15 14:45:59 +01:00
out_pci_release_regions :
2011-02-21 11:11:05 -08:00
pci_release_regions ( pdev ) ;
2011-11-15 14:45:59 +01:00
out_pci_disable_device :
2011-02-21 11:11:05 -08:00
pci_disable_device ( pdev ) ;
2011-11-15 14:45:59 +01:00
out_ieee80211_free_hw :
2011-10-24 16:49:25 +02:00
ieee80211_free_hw ( il - > hw ) ;
2011-11-15 14:45:59 +01:00
out :
2011-02-21 11:11:05 -08:00
return err ;
}
2012-12-03 09:56:33 -05:00
static void
2011-11-15 14:45:59 +01:00
il3945_pci_remove ( struct pci_dev * pdev )
2011-02-21 11:11:05 -08:00
{
2011-10-24 16:49:25 +02:00
struct il_priv * il = pci_get_drvdata ( pdev ) ;
2011-02-21 11:11:05 -08:00
unsigned long flags ;
2011-10-24 16:49:25 +02:00
if ( ! il )
2011-02-21 11:11:05 -08:00
return ;
2011-11-15 11:21:01 +01:00
D_INFO ( " *** UNLOAD DRIVER *** \n " ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_dbgfs_unregister ( il ) ;
2011-02-21 11:11:05 -08:00
2011-11-15 13:09:01 +01:00
set_bit ( S_EXIT_PENDING , & il - > status ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il_leds_exit ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( il - > mac80211_registered ) {
ieee80211_unregister_hw ( il - > hw ) ;
il - > mac80211_registered = 0 ;
2011-02-21 11:11:05 -08:00
} else {
2011-10-24 16:49:25 +02:00
il3945_down ( il ) ;
2011-02-21 11:11:05 -08:00
}
/*
* Make sure device is reset to low power before unloading driver .
2011-10-24 15:41:30 +02:00
* This may be redundant with il_down ( ) , but there are paths to
* run il_down ( ) without calling apm_ops . stop ( ) , and there are
* paths to avoid running il_down ( ) at all before leaving driver .
2011-02-21 11:11:05 -08:00
* This ( inexpensive ) call * makes sure * device is reset .
*/
2011-10-24 16:49:25 +02:00
il_apm_stop ( il ) ;
2011-02-21 11:11:05 -08:00
/* make sure we flush any pending irq or
* tasklet for the driver
*/
2011-10-24 16:49:25 +02:00
spin_lock_irqsave ( & il - > lock , flags ) ;
il_disable_interrupts ( il ) ;
spin_unlock_irqrestore ( & il - > lock , flags ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_synchronize_irq ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
sysfs_remove_group ( & pdev - > dev . kobj , & il3945_attribute_group ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
cancel_delayed_work_sync ( & il - > _3945 . rfkill_poll ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_dealloc_ucode_pci ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
if ( il - > rxq . bd )
il3945_rx_queue_free ( il , & il - > rxq ) ;
il3945_hw_txq_ctx_free ( il ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
il3945_unset_hw_params ( il ) ;
2011-02-21 11:11:05 -08:00
/*netif_stop_queue(dev); */
2011-10-24 16:49:25 +02:00
flush_workqueue ( il - > workqueue ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
/* ieee80211_unregister_hw calls il3945_mac_stop, which flushes
2011-10-24 16:49:25 +02:00
* il - > workqueue . . . so we can ' t take down the workqueue
2011-02-21 11:11:05 -08:00
* until now . . . */
2011-10-24 16:49:25 +02:00
destroy_workqueue ( il - > workqueue ) ;
il - > workqueue = NULL ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
free_irq ( pdev - > irq , il ) ;
2011-02-21 11:11:05 -08:00
pci_disable_msi ( pdev ) ;
2012-02-13 11:23:11 +01:00
iounmap ( il - > hw_base ) ;
2011-02-21 11:11:05 -08:00
pci_release_regions ( pdev ) ;
pci_disable_device ( pdev ) ;
2011-10-24 16:49:25 +02:00
il_free_channel_map ( il ) ;
il_free_geos ( il ) ;
kfree ( il - > scan_cmd ) ;
if ( il - > beacon_skb )
dev_kfree_skb ( il - > beacon_skb ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 16:49:25 +02:00
ieee80211_free_hw ( il - > hw ) ;
2011-02-21 11:11:05 -08:00
}
/*****************************************************************************
*
* driver and module entry point
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-10-24 15:41:30 +02:00
static struct pci_driver il3945_driver = {
2011-02-21 11:11:05 -08:00
. name = DRV_NAME ,
2011-10-24 15:41:30 +02:00
. id_table = il3945_hw_card_ids ,
. probe = il3945_pci_probe ,
2012-12-03 09:56:33 -05:00
. remove = il3945_pci_remove ,
2011-10-24 15:41:30 +02:00
. driver . pm = IL_LEGACY_PM_OPS ,
2011-02-21 11:11:05 -08:00
} ;
2011-11-15 14:45:59 +01:00
static int __init
il3945_init ( void )
2011-02-21 11:11:05 -08:00
{
int ret ;
pr_info ( DRV_DESCRIPTION " , " DRV_VERSION " \n " ) ;
pr_info ( DRV_COPYRIGHT " \n " ) ;
2011-10-24 15:41:30 +02:00
ret = il3945_rate_control_register ( ) ;
2011-02-21 11:11:05 -08:00
if ( ret ) {
pr_err ( " Unable to register rate control algorithm: %d \n " , ret ) ;
return ret ;
}
2011-10-24 15:41:30 +02:00
ret = pci_register_driver ( & il3945_driver ) ;
2011-02-21 11:11:05 -08:00
if ( ret ) {
pr_err ( " Unable to initialize PCI module \n " ) ;
goto error_register ;
}
return ret ;
error_register :
2011-10-24 15:41:30 +02:00
il3945_rate_control_unregister ( ) ;
2011-02-21 11:11:05 -08:00
return ret ;
}
2011-11-15 14:45:59 +01:00
static void __exit
il3945_exit ( void )
2011-02-21 11:11:05 -08:00
{
2011-10-24 15:41:30 +02:00
pci_unregister_driver ( & il3945_driver ) ;
il3945_rate_control_unregister ( ) ;
2011-02-21 11:11:05 -08:00
}
2011-11-15 11:25:42 +01:00
MODULE_FIRMWARE ( IL3945_MODULE_FIRMWARE ( IL3945_UCODE_API_MAX ) ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
module_param_named ( antenna , il3945_mod_params . antenna , int , S_IRUGO ) ;
2011-02-21 11:11:05 -08:00
MODULE_PARM_DESC ( antenna , " select antenna (1=Main, 2=Aux, default 0 [both]) " ) ;
2011-10-24 15:41:30 +02:00
module_param_named ( swcrypto , il3945_mod_params . sw_crypto , int , S_IRUGO ) ;
2011-11-15 14:45:59 +01:00
MODULE_PARM_DESC ( swcrypto , " using software crypto (default 1 [software]) " ) ;
module_param_named ( disable_hw_scan , il3945_mod_params . disable_hw_scan , int ,
S_IRUGO ) ;
2011-03-29 11:24:21 +02:00
MODULE_PARM_DESC ( disable_hw_scan , " disable hardware scanning (default 1) " ) ;
2011-11-15 11:25:42 +01:00
# ifdef CONFIG_IWLEGACY_DEBUG
2011-08-16 14:17:04 +02:00
module_param_named ( debug , il_debug_level , uint , S_IRUGO | S_IWUSR ) ;
2011-02-21 11:11:05 -08:00
MODULE_PARM_DESC ( debug , " debug output mask " ) ;
# endif
2011-10-24 15:41:30 +02:00
module_param_named ( fw_restart , il3945_mod_params . restart_fw , int , S_IRUGO ) ;
2011-02-21 11:27:26 -08:00
MODULE_PARM_DESC ( fw_restart , " restart firmware in case of error " ) ;
2011-02-21 11:11:05 -08:00
2011-10-24 15:41:30 +02:00
module_exit ( il3945_exit ) ;
module_init ( il3945_init ) ;