aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-io.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-04-05 12:42:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-07 15:52:28 -0400
commit02a7fa00a6d145037d549c779ad7692deb504acc (patch)
tree29ce5519266fc3287890a34ba4f90d4afc987544 /drivers/net/wireless/iwlwifi/iwl-io.c
parent519d8abd358afad825a1b919a2421d76779f23cd (diff)
iwlagn: move IO functions out of line
This generates a massive reduction in module size: with debug: text data bss dec hex filename 670300 13136 420 683856 a6f50 iwlagn.ko (before) 388347 13136 408 401891 621e3 iwlagn.ko (after) without debug: text data bss dec hex filename 528575 13072 420 542067 84573 iwlagn.ko (before) 294192 13072 408 307672 4b1d8 iwlagn.ko (after) This also removes all the IO debug functionality since it can easily be replaced by tracing, and makes the code unnecessarily complex. I haven't done any CPU utilisation measurements, but given that the hotpaths don't use much IO it is not likely to have a negative impact; in fact, the size reduction will reduce cache pressure which possibly improves performance. Finally, an unused function or two were removed. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-io.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
new file mode 100644
index 000000000000..51337416e4ca
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -0,0 +1,274 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
4 *
5 * Portions of this file are derived from the ipw3945 project.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * The full GNU General Public License is included in this distribution in the
21 * file called LICENSE.
22 *
23 * Contact Information:
24 * Intel Linux Wireless <ilw@linux.intel.com>
25 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26 *
27 *****************************************************************************/
28
29#include "iwl-io.h"
30
31#define IWL_POLL_INTERVAL 10 /* microseconds */
32
33static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
34{
35 iwl_write32(priv, reg, iwl_read32(priv, reg) | mask);
36}
37
38static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
39{
40 iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask);
41}
42
43void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
44{
45 unsigned long flags;
46
47 spin_lock_irqsave(&priv->reg_lock, flags);
48 __iwl_set_bit(priv, reg, mask);
49 spin_unlock_irqrestore(&priv->reg_lock, flags);
50}
51
52void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
53{
54 unsigned long flags;
55
56 spin_lock_irqsave(&priv->reg_lock, flags);
57 __iwl_clear_bit(priv, reg, mask);
58 spin_unlock_irqrestore(&priv->reg_lock, flags);
59}
60
61int iwl_poll_bit(struct iwl_priv *priv, u32 addr,
62 u32 bits, u32 mask, int timeout)
63{
64 int t = 0;
65
66 do {
67 if ((iwl_read32(priv, addr) & mask) == (bits & mask))
68 return t;
69 udelay(IWL_POLL_INTERVAL);
70 t += IWL_POLL_INTERVAL;
71 } while (t < timeout);
72
73 return -ETIMEDOUT;
74}
75
76int iwl_grab_nic_access(struct iwl_priv *priv)
77{
78 int ret;
79 u32 val;
80
81 lockdep_assert_held(&priv->reg_lock);
82
83 /* this bit wakes up the NIC */
84 __iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
85
86 /*
87 * These bits say the device is running, and should keep running for
88 * at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
89 * but they do not indicate that embedded SRAM is restored yet;
90 * 3945 and 4965 have volatile SRAM, and must save/restore contents
91 * to/from host DRAM when sleeping/waking for power-saving.
92 * Each direction takes approximately 1/4 millisecond; with this
93 * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
94 * series of register accesses are expected (e.g. reading Event Log),
95 * to keep device from sleeping.
96 *
97 * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
98 * SRAM is okay/restored. We don't check that here because this call
99 * is just for hardware register access; but GP1 MAC_SLEEP check is a
100 * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
101 *
102 * 5000 series and later (including 1000 series) have non-volatile SRAM,
103 * and do not save/restore SRAM when power cycling.
104 */
105 ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
106 CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
107 (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
108 CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
109 if (ret < 0) {
110 val = iwl_read32(priv, CSR_GP_CNTRL);
111 IWL_ERR(priv,
112 "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val);
113 iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
114 return -EIO;
115 }
116
117 return 0;
118}
119
120void iwl_release_nic_access(struct iwl_priv *priv)
121{
122 lockdep_assert_held(&priv->reg_lock);
123 __iwl_clear_bit(priv, CSR_GP_CNTRL,
124 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
125}
126
127u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg)
128{
129 u32 value;
130 unsigned long flags;
131
132 spin_lock_irqsave(&priv->reg_lock, flags);
133 iwl_grab_nic_access(priv);
134 value = iwl_read32(priv, reg);
135 iwl_release_nic_access(priv);
136 spin_unlock_irqrestore(&priv->reg_lock, flags);
137
138 return value;
139}
140
141void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value)
142{
143 unsigned long flags;
144
145 spin_lock_irqsave(&priv->reg_lock, flags);
146 if (!iwl_grab_nic_access(priv)) {
147 iwl_write32(priv, reg, value);
148 iwl_release_nic_access(priv);
149 }
150 spin_unlock_irqrestore(&priv->reg_lock, flags);
151}
152
153int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask,
154 int timeout)
155{
156 int t = 0;
157
158 do {
159 if ((iwl_read_direct32(priv, addr) & mask) == mask)
160 return t;
161 udelay(IWL_POLL_INTERVAL);
162 t += IWL_POLL_INTERVAL;
163 } while (t < timeout);
164
165 return -ETIMEDOUT;
166}
167
168static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg)
169{
170 iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
171 rmb();
172 return iwl_read32(priv, HBUS_TARG_PRPH_RDAT);
173}
174
175static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
176{
177 iwl_write32(priv, HBUS_TARG_PRPH_WADDR,
178 ((addr & 0x0000FFFF) | (3 << 24)));
179 wmb();
180 iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val);
181}
182
183u32 iwl_read_prph(struct iwl_priv *priv, u32 reg)
184{
185 unsigned long flags;
186 u32 val;
187
188 spin_lock_irqsave(&priv->reg_lock, flags);
189 iwl_grab_nic_access(priv);
190 val = __iwl_read_prph(priv, reg);
191 iwl_release_nic_access(priv);
192 spin_unlock_irqrestore(&priv->reg_lock, flags);
193 return val;
194}
195
196void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
197{
198 unsigned long flags;
199
200 spin_lock_irqsave(&priv->reg_lock, flags);
201 if (!iwl_grab_nic_access(priv)) {
202 __iwl_write_prph(priv, addr, val);
203 iwl_release_nic_access(priv);
204 }
205 spin_unlock_irqrestore(&priv->reg_lock, flags);
206}
207
208void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
209{
210 unsigned long flags;
211
212 spin_lock_irqsave(&priv->reg_lock, flags);
213 iwl_grab_nic_access(priv);
214 __iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask);
215 iwl_release_nic_access(priv);
216 spin_unlock_irqrestore(&priv->reg_lock, flags);
217}
218
219void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
220 u32 bits, u32 mask)
221{
222 unsigned long flags;
223
224 spin_lock_irqsave(&priv->reg_lock, flags);
225 iwl_grab_nic_access(priv);
226 __iwl_write_prph(priv, reg,
227 (__iwl_read_prph(priv, reg) & mask) | bits);
228 iwl_release_nic_access(priv);
229 spin_unlock_irqrestore(&priv->reg_lock, flags);
230}
231
232void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
233{
234 unsigned long flags;
235 u32 val;
236
237 spin_lock_irqsave(&priv->reg_lock, flags);
238 iwl_grab_nic_access(priv);
239 val = __iwl_read_prph(priv, reg);
240 __iwl_write_prph(priv, reg, (val & ~mask));
241 iwl_release_nic_access(priv);
242 spin_unlock_irqrestore(&priv->reg_lock, flags);
243}
244
245u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
246{
247 unsigned long flags;
248 u32 value;
249
250 spin_lock_irqsave(&priv->reg_lock, flags);
251 iwl_grab_nic_access(priv);
252
253 iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr);
254 rmb();
255 value = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
256
257 iwl_release_nic_access(priv);
258 spin_unlock_irqrestore(&priv->reg_lock, flags);
259 return value;
260}
261
262void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
263{
264 unsigned long flags;
265
266 spin_lock_irqsave(&priv->reg_lock, flags);
267 if (!iwl_grab_nic_access(priv)) {
268 iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr);
269 wmb();
270 iwl_write32(priv, HBUS_TARG_MEM_WDAT, val);
271 iwl_release_nic_access(priv);
272 }
273 spin_unlock_irqrestore(&priv->reg_lock, flags);
274}