2007-09-26 04:54:57 +04:00
/******************************************************************************
*
2011-04-05 20:42:00 +04:00
* Copyright ( c ) 2003 - 2011 Intel Corporation . All rights reserved .
2007-09-26 04:54:57 +04: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 :
2008-12-09 22:28:58 +03:00
* Intel Linux Wireless < ilw @ linux . intel . com >
2007-09-26 04:54:57 +04:00
* Intel Corporation , 5200 N . E . Elam Young Parkway , Hillsboro , OR 97124 - 6497
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef __iwl_helpers_h__
# define __iwl_helpers_h__
# include <linux/ctype.h>
2010-01-21 17:21:10 +03:00
# include <net/mac80211.h>
# include "iwl-io.h"
2007-09-26 04:54:57 +04:00
2008-05-29 12:35:00 +04:00
# define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
2007-09-26 04:54:57 +04:00
static inline struct ieee80211_conf * ieee80211_get_hw_conf (
struct ieee80211_hw * hw )
{
return & hw - > conf ;
}
2008-03-07 04:36:53 +03:00
/**
* iwl_queue_inc_wrap - increment queue index , wrap back to beginning
* @ index - - current index
* @ n_bd - - total number of entries in queue ( must be power of 2 )
*/
static inline int iwl_queue_inc_wrap ( int index , int n_bd )
{
return + + index & ( n_bd - 1 ) ;
}
/**
* iwl_queue_dec_wrap - decrement queue index , wrap back to end
* @ index - - current index
* @ n_bd - - total number of entries in queue ( must be power of 2 )
*/
static inline int iwl_queue_dec_wrap ( int index , int n_bd )
{
return - - index & ( n_bd - 1 ) ;
}
2008-01-15 04:46:20 +03:00
/* TODO: Move fw_desc functions to iwl-pci.ko */
static inline void iwl_free_fw_desc ( struct pci_dev * pci_dev ,
struct fw_desc * desc )
{
if ( desc - > v_addr )
2010-02-10 16:07:45 +03:00
dma_free_coherent ( & pci_dev - > dev , desc - > len ,
desc - > v_addr , desc - > p_addr ) ;
2008-01-15 04:46:20 +03:00
desc - > v_addr = NULL ;
desc - > len = 0 ;
}
static inline int iwl_alloc_fw_desc ( struct pci_dev * pci_dev ,
struct fw_desc * desc )
{
2010-05-03 12:17:57 +04:00
if ( ! desc - > len ) {
desc - > v_addr = NULL ;
return - EINVAL ;
}
2010-02-10 16:07:45 +03:00
desc - > v_addr = dma_alloc_coherent ( & pci_dev - > dev , desc - > len ,
& desc - > p_addr , GFP_KERNEL ) ;
2008-01-15 04:46:20 +03:00
return ( desc - > v_addr ! = NULL ) ? 0 : - ENOMEM ;
}
2009-03-23 19:28:42 +03:00
/*
* we have 8 bits used like this :
*
* 7 6 5 4 3 2 1 0
* | | | | | | | |
* | | | | | | + - + - - - - - - - - AC queue ( 0 - 3 )
* | | | | | |
2010-11-11 05:25:45 +03:00
* | + - + - + - + - + - - - - - - - - - - - - HW queue ID
2009-03-23 19:28:42 +03:00
* |
2010-11-11 05:25:45 +03:00
* + - - - - - - - - - - - - - - - - - - - - - - unused
2009-03-23 19:28:42 +03:00
*/
2010-11-11 05:25:45 +03:00
static inline void iwl_set_swq_id ( struct iwl_tx_queue * txq , u8 ac , u8 hwq )
2009-03-23 19:28:42 +03:00
{
BUG_ON ( ac > 3 ) ; /* only have 2 bits */
2010-11-11 05:25:45 +03:00
BUG_ON ( hwq > 31 ) ; /* only use 5 bits */
2009-03-23 19:28:42 +03:00
2010-11-11 05:25:45 +03:00
txq - > swq_id = ( hwq < < 2 ) | ac ;
2009-03-23 19:28:42 +03:00
}
2010-11-11 05:25:44 +03:00
static inline void iwl_wake_queue ( struct iwl_priv * priv ,
struct iwl_tx_queue * txq )
2009-03-23 19:28:42 +03:00
{
2010-11-11 05:25:44 +03:00
u8 queue = txq - > swq_id ;
2010-11-11 05:25:45 +03:00
u8 ac = queue & 3 ;
u8 hwq = ( queue > > 2 ) & 0x1f ;
2009-03-23 19:28:42 +03:00
if ( test_and_clear_bit ( hwq , priv - > queue_stopped ) )
if ( atomic_dec_return ( & priv - > queue_stop_count [ ac ] ) < = 0 )
ieee80211_wake_queue ( priv - > hw , ac ) ;
}
2010-11-11 05:25:44 +03:00
static inline void iwl_stop_queue ( struct iwl_priv * priv ,
struct iwl_tx_queue * txq )
2009-03-23 19:28:42 +03:00
{
2010-11-11 05:25:44 +03:00
u8 queue = txq - > swq_id ;
2010-11-11 05:25:45 +03:00
u8 ac = queue & 3 ;
u8 hwq = ( queue > > 2 ) & 0x1f ;
2009-03-23 19:28:42 +03:00
if ( ! test_and_set_bit ( hwq , priv - > queue_stopped ) )
if ( atomic_inc_return ( & priv - > queue_stop_count [ ac ] ) > 0 )
ieee80211_stop_queue ( priv - > hw , ac ) ;
}
# define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
# define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
2009-07-17 20:30:27 +04:00
static inline void iwl_disable_interrupts ( struct iwl_priv * priv )
{
clear_bit ( STATUS_INT_ENABLED , & priv - > status ) ;
/* disable interrupts from uCode/NIC to host */
iwl_write32 ( priv , CSR_INT_MASK , 0x00000000 ) ;
/* acknowledge/clear/reset any interrupts still pending
* from uCode or flow handler ( Rx / Tx DMA ) */
iwl_write32 ( priv , CSR_INT , 0xffffffff ) ;
iwl_write32 ( priv , CSR_FH_INT_STATUS , 0xffffffff ) ;
IWL_DEBUG_ISR ( priv , " Disabled interrupts \n " ) ;
}
2010-12-23 14:38:21 +03:00
static inline void iwl_enable_rfkill_int ( struct iwl_priv * priv )
{
IWL_DEBUG_ISR ( priv , " Enabling rfkill interrupt \n " ) ;
iwl_write32 ( priv , CSR_INT_MASK , CSR_INT_BIT_RF_KILL ) ;
}
2009-07-17 20:30:27 +04:00
static inline void iwl_enable_interrupts ( struct iwl_priv * priv )
{
IWL_DEBUG_ISR ( priv , " Enabling interrupts \n " ) ;
set_bit ( STATUS_INT_ENABLED , & priv - > status ) ;
iwl_write32 ( priv , CSR_INT_MASK , priv - > inta_mask ) ;
}
2010-05-06 19:54:10 +04:00
/**
* iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
* @ priv - - pointer to iwl_priv data structure
* @ tsf_bits - - number of bits need to shift for masking )
*/
static inline u32 iwl_beacon_time_mask_low ( struct iwl_priv * priv ,
u16 tsf_bits )
{
return ( 1 < < tsf_bits ) - 1 ;
}
/**
* iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
* @ priv - - pointer to iwl_priv data structure
* @ tsf_bits - - number of bits need to shift for masking )
*/
static inline u32 iwl_beacon_time_mask_high ( struct iwl_priv * priv ,
u16 tsf_bits )
{
return ( ( 1 < < ( 32 - tsf_bits ) ) - 1 ) < < tsf_bits ;
}
2007-09-26 04:54:57 +04:00
# endif /* __iwl_helpers_h__ */