1/****************************************************************************** 2 * 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. 4 * 5 * Portions of this file are derived from the ipw3945 project, as well 6 * as portions of the ieee80211 subsystem header files. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of version 2 of the GNU General Public License as 10 * published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along with 18 * this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 20 * 21 * The full GNU General Public License is included in this distribution in the 22 * file called LICENSE. 23 * 24 * Contact Information: 25 * Intel Linux Wireless <ilw@linux.intel.com> 26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 27 * 28 *****************************************************************************/ 29 30#ifndef __iwl_helpers_h__ 31#define __iwl_helpers_h__ 32 33#include <linux/ctype.h> 34#include <net/mac80211.h> 35 36#include "iwl-io.h" 37 38#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) 39 40 41static inline struct ieee80211_conf *ieee80211_get_hw_conf( 42 struct ieee80211_hw *hw) 43{ 44 return &hw->conf; 45} 46 47static inline int iwl_check_bits(unsigned long field, unsigned long mask) 48{ 49 return ((field & mask) == mask) ? 1 : 0; 50} 51 52static inline unsigned long elapsed_jiffies(unsigned long start, 53 unsigned long end) 54{ 55 if (end >= start) 56 return end - start; 57 58 return end + (MAX_JIFFY_OFFSET - start) + 1; 59} 60 61/** 62 * iwl_queue_inc_wrap - increment queue index, wrap back to beginning 63 * @index -- current index 64 * @n_bd -- total number of entries in queue (must be power of 2) 65 */ 66static inline int iwl_queue_inc_wrap(int index, int n_bd) 67{ 68 return ++index & (n_bd - 1); 69} 70 71/** 72 * iwl_queue_dec_wrap - decrement queue index, wrap back to end 73 * @index -- current index 74 * @n_bd -- total number of entries in queue (must be power of 2) 75 */ 76static inline int iwl_queue_dec_wrap(int index, int n_bd) 77{ 78 return --index & (n_bd - 1); 79} 80 81/* TODO: Move fw_desc functions to iwl-pci.ko */ 82static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, 83 struct fw_desc *desc) 84{ 85 if (desc->v_addr) 86 dma_free_coherent(&pci_dev->dev, desc->len, 87 desc->v_addr, desc->p_addr); 88 desc->v_addr = NULL; 89 desc->len = 0; 90} 91 92static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, 93 struct fw_desc *desc) 94{ 95 if (!desc->len) { 96 desc->v_addr = NULL; 97 return -EINVAL; 98 } 99 100 desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, 101 &desc->p_addr, GFP_KERNEL); 102 return (desc->v_addr != NULL) ? 0 : -ENOMEM; 103} 104 105/* 106 * we have 8 bits used like this: 107 * 108 * 7 6 5 4 3 2 1 0 109 * | | | | | | | | 110 * | | | | | | +-+-------- AC queue (0-3) 111 * | | | | | | 112 * | +-+-+-+-+------------ HW A-MPDU queue 113 * | 114 * +---------------------- indicates agg queue 115 */ 116static inline u8 iwl_virtual_agg_queue_num(u8 ac, u8 hwq) 117{ 118 BUG_ON(ac > 3); /* only have 2 bits */ 119 BUG_ON(hwq > 31); /* only have 5 bits */ 120 121 return 0x80 | (hwq << 2) | ac; 122} 123 124static inline void iwl_wake_queue(struct iwl_priv *priv, u8 queue) 125{ 126 u8 ac = queue; 127 u8 hwq = queue; 128 129 if (queue & 0x80) { 130 ac = queue & 3; 131 hwq = (queue >> 2) & 0x1f; 132 } 133 134 if (test_and_clear_bit(hwq, priv->queue_stopped)) 135 if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) 136 ieee80211_wake_queue(priv->hw, ac); 137} 138 139static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue) 140{ 141 u8 ac = queue; 142 u8 hwq = queue; 143 144 if (queue & 0x80) { 145 ac = queue & 3; 146 hwq = (queue >> 2) & 0x1f; 147 } 148 149 if (!test_and_set_bit(hwq, priv->queue_stopped)) 150 if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) 151 ieee80211_stop_queue(priv->hw, ac); 152} 153 154#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue 155#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue 156 157static inline void iwl_disable_interrupts(struct iwl_priv *priv) 158{ 159 clear_bit(STATUS_INT_ENABLED, &priv->status); 160 161 /* disable interrupts from uCode/NIC to host */ 162 iwl_write32(priv, CSR_INT_MASK, 0x00000000); 163 164 /* acknowledge/clear/reset any interrupts still pending 165 * from uCode or flow handler (Rx/Tx DMA) */ 166 iwl_write32(priv, CSR_INT, 0xffffffff); 167 iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); 168 IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); 169} 170 171static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) 172{ 173 IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); 174 iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); 175} 176 177static inline void iwl_enable_interrupts(struct iwl_priv *priv) 178{ 179 IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); 180 set_bit(STATUS_INT_ENABLED, &priv->status); 181 iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); 182} 183 184/** 185 * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time 186 * @priv -- pointer to iwl_priv data structure 187 * @tsf_bits -- number of bits need to shift for masking) 188 */ 189static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, 190 u16 tsf_bits) 191{ 192 return (1 << tsf_bits) - 1; 193} 194 195/** 196 * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time 197 * @priv -- pointer to iwl_priv data structure 198 * @tsf_bits -- number of bits need to shift for masking) 199 */ 200static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv, 201 u16 tsf_bits) 202{ 203 return ((1 << (32 - tsf_bits)) - 1) << tsf_bits; 204} 205 206#endif /* __iwl_helpers_h__ */ 207