diff options
author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-03-21 14:05:45 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-03-21 14:05:45 -0500 |
commit | d04cdb64212eb5ae6a98026a97dda626e40e8e9a (patch) | |
tree | b6a7dbb21ccfceb915844e9a330b3d3dfcaf3c5b /drivers/net/wireless/ipw2200.c | |
parent | 2f8600dff2b140096a7df781884e918a16aa90e0 (diff) | |
parent | ec1248e70edc5cf7b485efcc7b41e44e10f422e5 (diff) |
Merge ../linux-2.6
Diffstat (limited to 'drivers/net/wireless/ipw2200.c')
-rw-r--r-- | drivers/net/wireless/ipw2200.c | 1239 |
1 files changed, 596 insertions, 643 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 287676ad80df..9dce522526c5 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | 2 | ||
3 | Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. | 3 | Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved. |
4 | 4 | ||
5 | 802.11 status code portion of this file from ethereal-0.10.6: | 5 | 802.11 status code portion of this file from ethereal-0.10.6: |
6 | Copyright 2000, Axis Communications AB | 6 | Copyright 2000, Axis Communications AB |
@@ -33,9 +33,9 @@ | |||
33 | #include "ipw2200.h" | 33 | #include "ipw2200.h" |
34 | #include <linux/version.h> | 34 | #include <linux/version.h> |
35 | 35 | ||
36 | #define IPW2200_VERSION "git-1.0.8" | 36 | #define IPW2200_VERSION "git-1.1.1" |
37 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" | 37 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" |
38 | #define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" | 38 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" |
39 | #define DRV_VERSION IPW2200_VERSION | 39 | #define DRV_VERSION IPW2200_VERSION |
40 | 40 | ||
41 | #define ETH_P_80211_STATS (ETH_P_80211_RAW + 1) | 41 | #define ETH_P_80211_STATS (ETH_P_80211_RAW + 1) |
@@ -55,7 +55,9 @@ static int associate = 1; | |||
55 | static int auto_create = 1; | 55 | static int auto_create = 1; |
56 | static int led = 0; | 56 | static int led = 0; |
57 | static int disable = 0; | 57 | static int disable = 0; |
58 | static int hwcrypto = 1; | 58 | static int bt_coexist = 0; |
59 | static int hwcrypto = 0; | ||
60 | static int roaming = 1; | ||
59 | static const char ipw_modes[] = { | 61 | static const char ipw_modes[] = { |
60 | 'a', 'b', 'g', '?' | 62 | 'a', 'b', 'g', '?' |
61 | }; | 63 | }; |
@@ -151,12 +153,6 @@ static int init_supported_rates(struct ipw_priv *priv, | |||
151 | static void ipw_set_hwcrypto_keys(struct ipw_priv *); | 153 | static void ipw_set_hwcrypto_keys(struct ipw_priv *); |
152 | static void ipw_send_wep_keys(struct ipw_priv *, int); | 154 | static void ipw_send_wep_keys(struct ipw_priv *, int); |
153 | 155 | ||
154 | static int ipw_is_valid_channel(struct ieee80211_device *, u8); | ||
155 | static int ipw_channel_to_index(struct ieee80211_device *, u8); | ||
156 | static u8 ipw_freq_to_channel(struct ieee80211_device *, u32); | ||
157 | static int ipw_set_geo(struct ieee80211_device *, const struct ieee80211_geo *); | ||
158 | static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *); | ||
159 | |||
160 | static int snprint_line(char *buf, size_t count, | 156 | static int snprint_line(char *buf, size_t count, |
161 | const u8 * data, u32 len, u32 ofs) | 157 | const u8 * data, u32 len, u32 ofs) |
162 | { | 158 | { |
@@ -227,12 +223,15 @@ static int snprintk_buf(u8 * output, size_t size, const u8 * data, size_t len) | |||
227 | return total; | 223 | return total; |
228 | } | 224 | } |
229 | 225 | ||
226 | /* alias for 32-bit indirect read (for SRAM/reg above 4K), with debug wrapper */ | ||
230 | static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg); | 227 | static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg); |
231 | #define ipw_read_reg32(a, b) _ipw_read_reg32(a, b) | 228 | #define ipw_read_reg32(a, b) _ipw_read_reg32(a, b) |
232 | 229 | ||
230 | /* alias for 8-bit indirect read (for SRAM/reg above 4K), with debug wrapper */ | ||
233 | static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg); | 231 | static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg); |
234 | #define ipw_read_reg8(a, b) _ipw_read_reg8(a, b) | 232 | #define ipw_read_reg8(a, b) _ipw_read_reg8(a, b) |
235 | 233 | ||
234 | /* 8-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ | ||
236 | static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value); | 235 | static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value); |
237 | static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c) | 236 | static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c) |
238 | { | 237 | { |
@@ -241,6 +240,7 @@ static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c) | |||
241 | _ipw_write_reg8(a, b, c); | 240 | _ipw_write_reg8(a, b, c); |
242 | } | 241 | } |
243 | 242 | ||
243 | /* 16-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ | ||
244 | static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value); | 244 | static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value); |
245 | static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c) | 245 | static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c) |
246 | { | 246 | { |
@@ -249,6 +249,7 @@ static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c) | |||
249 | _ipw_write_reg16(a, b, c); | 249 | _ipw_write_reg16(a, b, c); |
250 | } | 250 | } |
251 | 251 | ||
252 | /* 32-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ | ||
252 | static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value); | 253 | static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value); |
253 | static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) | 254 | static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) |
254 | { | 255 | { |
@@ -257,48 +258,70 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) | |||
257 | _ipw_write_reg32(a, b, c); | 258 | _ipw_write_reg32(a, b, c); |
258 | } | 259 | } |
259 | 260 | ||
261 | /* 8-bit direct write (low 4K) */ | ||
260 | #define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs)) | 262 | #define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs)) |
263 | |||
264 | /* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ | ||
261 | #define ipw_write8(ipw, ofs, val) \ | 265 | #define ipw_write8(ipw, ofs, val) \ |
262 | IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ | 266 | IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ |
263 | _ipw_write8(ipw, ofs, val) | 267 | _ipw_write8(ipw, ofs, val) |
264 | 268 | ||
269 | /* 16-bit direct write (low 4K) */ | ||
265 | #define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs)) | 270 | #define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs)) |
271 | |||
272 | /* 16-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ | ||
266 | #define ipw_write16(ipw, ofs, val) \ | 273 | #define ipw_write16(ipw, ofs, val) \ |
267 | IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ | 274 | IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ |
268 | _ipw_write16(ipw, ofs, val) | 275 | _ipw_write16(ipw, ofs, val) |
269 | 276 | ||
277 | /* 32-bit direct write (low 4K) */ | ||
270 | #define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs)) | 278 | #define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs)) |
279 | |||
280 | /* 32-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ | ||
271 | #define ipw_write32(ipw, ofs, val) \ | 281 | #define ipw_write32(ipw, ofs, val) \ |
272 | IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ | 282 | IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ |
273 | _ipw_write32(ipw, ofs, val) | 283 | _ipw_write32(ipw, ofs, val) |
274 | 284 | ||
285 | /* 8-bit direct read (low 4K) */ | ||
275 | #define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs)) | 286 | #define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs)) |
287 | |||
288 | /* 8-bit direct read (low 4K), with debug wrapper */ | ||
276 | static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) | 289 | static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) |
277 | { | 290 | { |
278 | IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs)); | 291 | IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs)); |
279 | return _ipw_read8(ipw, ofs); | 292 | return _ipw_read8(ipw, ofs); |
280 | } | 293 | } |
281 | 294 | ||
295 | /* alias to 8-bit direct read (low 4K of SRAM/regs), with debug wrapper */ | ||
282 | #define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs) | 296 | #define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs) |
283 | 297 | ||
298 | /* 16-bit direct read (low 4K) */ | ||
284 | #define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs)) | 299 | #define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs)) |
300 | |||
301 | /* 16-bit direct read (low 4K), with debug wrapper */ | ||
285 | static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) | 302 | static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) |
286 | { | 303 | { |
287 | IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs)); | 304 | IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs)); |
288 | return _ipw_read16(ipw, ofs); | 305 | return _ipw_read16(ipw, ofs); |
289 | } | 306 | } |
290 | 307 | ||
308 | /* alias to 16-bit direct read (low 4K of SRAM/regs), with debug wrapper */ | ||
291 | #define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs) | 309 | #define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs) |
292 | 310 | ||
311 | /* 32-bit direct read (low 4K) */ | ||
293 | #define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs)) | 312 | #define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs)) |
313 | |||
314 | /* 32-bit direct read (low 4K), with debug wrapper */ | ||
294 | static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) | 315 | static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) |
295 | { | 316 | { |
296 | IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs)); | 317 | IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs)); |
297 | return _ipw_read32(ipw, ofs); | 318 | return _ipw_read32(ipw, ofs); |
298 | } | 319 | } |
299 | 320 | ||
321 | /* alias to 32-bit direct read (low 4K of SRAM/regs), with debug wrapper */ | ||
300 | #define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs) | 322 | #define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs) |
301 | 323 | ||
324 | /* multi-byte read (above 4K), with debug wrapper */ | ||
302 | static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int); | 325 | static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int); |
303 | static inline void __ipw_read_indirect(const char *f, int l, | 326 | static inline void __ipw_read_indirect(const char *f, int l, |
304 | struct ipw_priv *a, u32 b, u8 * c, int d) | 327 | struct ipw_priv *a, u32 b, u8 * c, int d) |
@@ -308,15 +331,17 @@ static inline void __ipw_read_indirect(const char *f, int l, | |||
308 | _ipw_read_indirect(a, b, c, d); | 331 | _ipw_read_indirect(a, b, c, d); |
309 | } | 332 | } |
310 | 333 | ||
334 | /* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */ | ||
311 | #define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d) | 335 | #define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d) |
312 | 336 | ||
337 | /* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */ | ||
313 | static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data, | 338 | static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data, |
314 | int num); | 339 | int num); |
315 | #define ipw_write_indirect(a, b, c, d) \ | 340 | #define ipw_write_indirect(a, b, c, d) \ |
316 | IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \ | 341 | IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \ |
317 | _ipw_write_indirect(a, b, c, d) | 342 | _ipw_write_indirect(a, b, c, d) |
318 | 343 | ||
319 | /* indirect write s */ | 344 | /* 32-bit indirect write (above 4K) */ |
320 | static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) | 345 | static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) |
321 | { | 346 | { |
322 | IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value); | 347 | IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value); |
@@ -324,22 +349,29 @@ static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) | |||
324 | _ipw_write32(priv, IPW_INDIRECT_DATA, value); | 349 | _ipw_write32(priv, IPW_INDIRECT_DATA, value); |
325 | } | 350 | } |
326 | 351 | ||
352 | /* 8-bit indirect write (above 4K) */ | ||
327 | static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) | 353 | static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) |
328 | { | 354 | { |
355 | u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ | ||
356 | u32 dif_len = reg - aligned_addr; | ||
357 | |||
329 | IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); | 358 | IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); |
330 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); | 359 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
331 | _ipw_write8(priv, IPW_INDIRECT_DATA, value); | 360 | _ipw_write8(priv, IPW_INDIRECT_DATA + dif_len, value); |
332 | } | 361 | } |
333 | 362 | ||
363 | /* 16-bit indirect write (above 4K) */ | ||
334 | static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) | 364 | static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) |
335 | { | 365 | { |
366 | u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ | ||
367 | u32 dif_len = (reg - aligned_addr) & (~0x1ul); | ||
368 | |||
336 | IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); | 369 | IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); |
337 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); | 370 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
338 | _ipw_write16(priv, IPW_INDIRECT_DATA, value); | 371 | _ipw_write16(priv, IPW_INDIRECT_DATA + dif_len, value); |
339 | } | 372 | } |
340 | 373 | ||
341 | /* indirect read s */ | 374 | /* 8-bit indirect read (above 4K) */ |
342 | |||
343 | static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) | 375 | static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) |
344 | { | 376 | { |
345 | u32 word; | 377 | u32 word; |
@@ -349,6 +381,7 @@ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) | |||
349 | return (word >> ((reg & 0x3) * 8)) & 0xff; | 381 | return (word >> ((reg & 0x3) * 8)) & 0xff; |
350 | } | 382 | } |
351 | 383 | ||
384 | /* 32-bit indirect read (above 4K) */ | ||
352 | static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) | 385 | static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) |
353 | { | 386 | { |
354 | u32 value; | 387 | u32 value; |
@@ -361,11 +394,12 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) | |||
361 | return value; | 394 | return value; |
362 | } | 395 | } |
363 | 396 | ||
364 | /* iterative/auto-increment 32 bit reads and writes */ | 397 | /* General purpose, no alignment requirement, iterative (multi-byte) read, */ |
398 | /* for area above 1st 4K of SRAM/reg space */ | ||
365 | static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | 399 | static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, |
366 | int num) | 400 | int num) |
367 | { | 401 | { |
368 | u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; | 402 | u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ |
369 | u32 dif_len = addr - aligned_addr; | 403 | u32 dif_len = addr - aligned_addr; |
370 | u32 i; | 404 | u32 i; |
371 | 405 | ||
@@ -375,7 +409,7 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | |||
375 | return; | 409 | return; |
376 | } | 410 | } |
377 | 411 | ||
378 | /* Read the first nibble byte by byte */ | 412 | /* Read the first dword (or portion) byte by byte */ |
379 | if (unlikely(dif_len)) { | 413 | if (unlikely(dif_len)) { |
380 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); | 414 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
381 | /* Start reading at aligned_addr + dif_len */ | 415 | /* Start reading at aligned_addr + dif_len */ |
@@ -384,11 +418,12 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | |||
384 | aligned_addr += 4; | 418 | aligned_addr += 4; |
385 | } | 419 | } |
386 | 420 | ||
421 | /* Read all of the middle dwords as dwords, with auto-increment */ | ||
387 | _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); | 422 | _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); |
388 | for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) | 423 | for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) |
389 | *(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA); | 424 | *(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA); |
390 | 425 | ||
391 | /* Copy the last nibble */ | 426 | /* Read the last dword (or portion) byte by byte */ |
392 | if (unlikely(num)) { | 427 | if (unlikely(num)) { |
393 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); | 428 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
394 | for (i = 0; num > 0; i++, num--) | 429 | for (i = 0; num > 0; i++, num--) |
@@ -396,10 +431,12 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | |||
396 | } | 431 | } |
397 | } | 432 | } |
398 | 433 | ||
434 | /* General purpose, no alignment requirement, iterative (multi-byte) write, */ | ||
435 | /* for area above 1st 4K of SRAM/reg space */ | ||
399 | static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | 436 | static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, |
400 | int num) | 437 | int num) |
401 | { | 438 | { |
402 | u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; | 439 | u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ |
403 | u32 dif_len = addr - aligned_addr; | 440 | u32 dif_len = addr - aligned_addr; |
404 | u32 i; | 441 | u32 i; |
405 | 442 | ||
@@ -409,20 +446,21 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | |||
409 | return; | 446 | return; |
410 | } | 447 | } |
411 | 448 | ||
412 | /* Write the first nibble byte by byte */ | 449 | /* Write the first dword (or portion) byte by byte */ |
413 | if (unlikely(dif_len)) { | 450 | if (unlikely(dif_len)) { |
414 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); | 451 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
415 | /* Start reading at aligned_addr + dif_len */ | 452 | /* Start writing at aligned_addr + dif_len */ |
416 | for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++) | 453 | for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++) |
417 | _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); | 454 | _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); |
418 | aligned_addr += 4; | 455 | aligned_addr += 4; |
419 | } | 456 | } |
420 | 457 | ||
458 | /* Write all of the middle dwords as dwords, with auto-increment */ | ||
421 | _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); | 459 | _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); |
422 | for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) | 460 | for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) |
423 | _ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf); | 461 | _ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf); |
424 | 462 | ||
425 | /* Copy the last nibble */ | 463 | /* Write the last dword (or portion) byte by byte */ |
426 | if (unlikely(num)) { | 464 | if (unlikely(num)) { |
427 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); | 465 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
428 | for (i = 0; num > 0; i++, num--, buf++) | 466 | for (i = 0; num > 0; i++, num--, buf++) |
@@ -430,17 +468,21 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | |||
430 | } | 468 | } |
431 | } | 469 | } |
432 | 470 | ||
471 | /* General purpose, no alignment requirement, iterative (multi-byte) write, */ | ||
472 | /* for 1st 4K of SRAM/regs space */ | ||
433 | static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf, | 473 | static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf, |
434 | int num) | 474 | int num) |
435 | { | 475 | { |
436 | memcpy_toio((priv->hw_base + addr), buf, num); | 476 | memcpy_toio((priv->hw_base + addr), buf, num); |
437 | } | 477 | } |
438 | 478 | ||
479 | /* Set bit(s) in low 4K of SRAM/regs */ | ||
439 | static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask) | 480 | static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask) |
440 | { | 481 | { |
441 | ipw_write32(priv, reg, ipw_read32(priv, reg) | mask); | 482 | ipw_write32(priv, reg, ipw_read32(priv, reg) | mask); |
442 | } | 483 | } |
443 | 484 | ||
485 | /* Clear bit(s) in low 4K of SRAM/regs */ | ||
444 | static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask) | 486 | static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask) |
445 | { | 487 | { |
446 | ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask); | 488 | ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask); |
@@ -701,7 +743,7 @@ static void ipw_init_ordinals(struct ipw_priv *priv) | |||
701 | 743 | ||
702 | } | 744 | } |
703 | 745 | ||
704 | u32 ipw_register_toggle(u32 reg) | 746 | static u32 ipw_register_toggle(u32 reg) |
705 | { | 747 | { |
706 | reg &= ~IPW_START_STANDBY; | 748 | reg &= ~IPW_START_STANDBY; |
707 | if (reg & IPW_GATE_ODMA) | 749 | if (reg & IPW_GATE_ODMA) |
@@ -722,11 +764,11 @@ u32 ipw_register_toggle(u32 reg) | |||
722 | * - On radio OFF, turn off any LEDs started during radio on | 764 | * - On radio OFF, turn off any LEDs started during radio on |
723 | * | 765 | * |
724 | */ | 766 | */ |
725 | #define LD_TIME_LINK_ON 300 | 767 | #define LD_TIME_LINK_ON msecs_to_jiffies(300) |
726 | #define LD_TIME_LINK_OFF 2700 | 768 | #define LD_TIME_LINK_OFF msecs_to_jiffies(2700) |
727 | #define LD_TIME_ACT_ON 250 | 769 | #define LD_TIME_ACT_ON msecs_to_jiffies(250) |
728 | 770 | ||
729 | void ipw_led_link_on(struct ipw_priv *priv) | 771 | static void ipw_led_link_on(struct ipw_priv *priv) |
730 | { | 772 | { |
731 | unsigned long flags; | 773 | unsigned long flags; |
732 | u32 led; | 774 | u32 led; |
@@ -764,12 +806,12 @@ void ipw_led_link_on(struct ipw_priv *priv) | |||
764 | static void ipw_bg_led_link_on(void *data) | 806 | static void ipw_bg_led_link_on(void *data) |
765 | { | 807 | { |
766 | struct ipw_priv *priv = data; | 808 | struct ipw_priv *priv = data; |
767 | down(&priv->sem); | 809 | mutex_lock(&priv->mutex); |
768 | ipw_led_link_on(data); | 810 | ipw_led_link_on(data); |
769 | up(&priv->sem); | 811 | mutex_unlock(&priv->mutex); |
770 | } | 812 | } |
771 | 813 | ||
772 | void ipw_led_link_off(struct ipw_priv *priv) | 814 | static void ipw_led_link_off(struct ipw_priv *priv) |
773 | { | 815 | { |
774 | unsigned long flags; | 816 | unsigned long flags; |
775 | u32 led; | 817 | u32 led; |
@@ -808,9 +850,9 @@ void ipw_led_link_off(struct ipw_priv *priv) | |||
808 | static void ipw_bg_led_link_off(void *data) | 850 | static void ipw_bg_led_link_off(void *data) |
809 | { | 851 | { |
810 | struct ipw_priv *priv = data; | 852 | struct ipw_priv *priv = data; |
811 | down(&priv->sem); | 853 | mutex_lock(&priv->mutex); |
812 | ipw_led_link_off(data); | 854 | ipw_led_link_off(data); |
813 | up(&priv->sem); | 855 | mutex_unlock(&priv->mutex); |
814 | } | 856 | } |
815 | 857 | ||
816 | static void __ipw_led_activity_on(struct ipw_priv *priv) | 858 | static void __ipw_led_activity_on(struct ipw_priv *priv) |
@@ -847,6 +889,7 @@ static void __ipw_led_activity_on(struct ipw_priv *priv) | |||
847 | } | 889 | } |
848 | } | 890 | } |
849 | 891 | ||
892 | #if 0 | ||
850 | void ipw_led_activity_on(struct ipw_priv *priv) | 893 | void ipw_led_activity_on(struct ipw_priv *priv) |
851 | { | 894 | { |
852 | unsigned long flags; | 895 | unsigned long flags; |
@@ -854,8 +897,9 @@ void ipw_led_activity_on(struct ipw_priv *priv) | |||
854 | __ipw_led_activity_on(priv); | 897 | __ipw_led_activity_on(priv); |
855 | spin_unlock_irqrestore(&priv->lock, flags); | 898 | spin_unlock_irqrestore(&priv->lock, flags); |
856 | } | 899 | } |
900 | #endif /* 0 */ | ||
857 | 901 | ||
858 | void ipw_led_activity_off(struct ipw_priv *priv) | 902 | static void ipw_led_activity_off(struct ipw_priv *priv) |
859 | { | 903 | { |
860 | unsigned long flags; | 904 | unsigned long flags; |
861 | u32 led; | 905 | u32 led; |
@@ -885,12 +929,12 @@ void ipw_led_activity_off(struct ipw_priv *priv) | |||
885 | static void ipw_bg_led_activity_off(void *data) | 929 | static void ipw_bg_led_activity_off(void *data) |
886 | { | 930 | { |
887 | struct ipw_priv *priv = data; | 931 | struct ipw_priv *priv = data; |
888 | down(&priv->sem); | 932 | mutex_lock(&priv->mutex); |
889 | ipw_led_activity_off(data); | 933 | ipw_led_activity_off(data); |
890 | up(&priv->sem); | 934 | mutex_unlock(&priv->mutex); |
891 | } | 935 | } |
892 | 936 | ||
893 | void ipw_led_band_on(struct ipw_priv *priv) | 937 | static void ipw_led_band_on(struct ipw_priv *priv) |
894 | { | 938 | { |
895 | unsigned long flags; | 939 | unsigned long flags; |
896 | u32 led; | 940 | u32 led; |
@@ -925,7 +969,7 @@ void ipw_led_band_on(struct ipw_priv *priv) | |||
925 | spin_unlock_irqrestore(&priv->lock, flags); | 969 | spin_unlock_irqrestore(&priv->lock, flags); |
926 | } | 970 | } |
927 | 971 | ||
928 | void ipw_led_band_off(struct ipw_priv *priv) | 972 | static void ipw_led_band_off(struct ipw_priv *priv) |
929 | { | 973 | { |
930 | unsigned long flags; | 974 | unsigned long flags; |
931 | u32 led; | 975 | u32 led; |
@@ -948,24 +992,24 @@ void ipw_led_band_off(struct ipw_priv *priv) | |||
948 | spin_unlock_irqrestore(&priv->lock, flags); | 992 | spin_unlock_irqrestore(&priv->lock, flags); |
949 | } | 993 | } |
950 | 994 | ||
951 | void ipw_led_radio_on(struct ipw_priv *priv) | 995 | static void ipw_led_radio_on(struct ipw_priv *priv) |
952 | { | 996 | { |
953 | ipw_led_link_on(priv); | 997 | ipw_led_link_on(priv); |
954 | } | 998 | } |
955 | 999 | ||
956 | void ipw_led_radio_off(struct ipw_priv *priv) | 1000 | static void ipw_led_radio_off(struct ipw_priv *priv) |
957 | { | 1001 | { |
958 | ipw_led_activity_off(priv); | 1002 | ipw_led_activity_off(priv); |
959 | ipw_led_link_off(priv); | 1003 | ipw_led_link_off(priv); |
960 | } | 1004 | } |
961 | 1005 | ||
962 | void ipw_led_link_up(struct ipw_priv *priv) | 1006 | static void ipw_led_link_up(struct ipw_priv *priv) |
963 | { | 1007 | { |
964 | /* Set the Link Led on for all nic types */ | 1008 | /* Set the Link Led on for all nic types */ |
965 | ipw_led_link_on(priv); | 1009 | ipw_led_link_on(priv); |
966 | } | 1010 | } |
967 | 1011 | ||
968 | void ipw_led_link_down(struct ipw_priv *priv) | 1012 | static void ipw_led_link_down(struct ipw_priv *priv) |
969 | { | 1013 | { |
970 | ipw_led_activity_off(priv); | 1014 | ipw_led_activity_off(priv); |
971 | ipw_led_link_off(priv); | 1015 | ipw_led_link_off(priv); |
@@ -974,7 +1018,7 @@ void ipw_led_link_down(struct ipw_priv *priv) | |||
974 | ipw_led_radio_off(priv); | 1018 | ipw_led_radio_off(priv); |
975 | } | 1019 | } |
976 | 1020 | ||
977 | void ipw_led_init(struct ipw_priv *priv) | 1021 | static void ipw_led_init(struct ipw_priv *priv) |
978 | { | 1022 | { |
979 | priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE]; | 1023 | priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE]; |
980 | 1024 | ||
@@ -1025,7 +1069,7 @@ void ipw_led_init(struct ipw_priv *priv) | |||
1025 | } | 1069 | } |
1026 | } | 1070 | } |
1027 | 1071 | ||
1028 | void ipw_led_shutdown(struct ipw_priv *priv) | 1072 | static void ipw_led_shutdown(struct ipw_priv *priv) |
1029 | { | 1073 | { |
1030 | ipw_led_activity_off(priv); | 1074 | ipw_led_activity_off(priv); |
1031 | ipw_led_link_off(priv); | 1075 | ipw_led_link_off(priv); |
@@ -1074,6 +1118,7 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, | |||
1074 | 1118 | ||
1075 | static inline u32 ipw_get_event_log_len(struct ipw_priv *priv) | 1119 | static inline u32 ipw_get_event_log_len(struct ipw_priv *priv) |
1076 | { | 1120 | { |
1121 | /* length = 1st dword in log */ | ||
1077 | return ipw_read_reg32(priv, ipw_read32(priv, IPW_EVENT_LOG)); | 1122 | return ipw_read_reg32(priv, ipw_read32(priv, IPW_EVENT_LOG)); |
1078 | } | 1123 | } |
1079 | 1124 | ||
@@ -1603,7 +1648,7 @@ static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr, | |||
1603 | break; | 1648 | break; |
1604 | } | 1649 | } |
1605 | 1650 | ||
1606 | if (ipw_is_valid_channel(priv->ieee, channel)) | 1651 | if (ieee80211_is_valid_channel(priv->ieee, channel)) |
1607 | priv->speed_scan[pos++] = channel; | 1652 | priv->speed_scan[pos++] = channel; |
1608 | else | 1653 | else |
1609 | IPW_WARNING("Skipping invalid channel request: %d\n", | 1654 | IPW_WARNING("Skipping invalid channel request: %d\n", |
@@ -1751,9 +1796,9 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1751 | } | 1796 | } |
1752 | 1797 | ||
1753 | if (inta & IPW_INTA_BIT_FATAL_ERROR) { | 1798 | if (inta & IPW_INTA_BIT_FATAL_ERROR) { |
1754 | IPW_ERROR("Firmware error detected. Restarting.\n"); | 1799 | IPW_WARNING("Firmware error detected. Restarting.\n"); |
1755 | if (priv->error) { | 1800 | if (priv->error) { |
1756 | IPW_ERROR("Sysfs 'error' log already exists.\n"); | 1801 | IPW_DEBUG_FW("Sysfs 'error' log already exists.\n"); |
1757 | #ifdef CONFIG_IPW2200_DEBUG | 1802 | #ifdef CONFIG_IPW2200_DEBUG |
1758 | if (ipw_debug_level & IPW_DL_FW_ERRORS) { | 1803 | if (ipw_debug_level & IPW_DL_FW_ERRORS) { |
1759 | struct ipw_fw_error *error = | 1804 | struct ipw_fw_error *error = |
@@ -1766,10 +1811,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1766 | } else { | 1811 | } else { |
1767 | priv->error = ipw_alloc_error_log(priv); | 1812 | priv->error = ipw_alloc_error_log(priv); |
1768 | if (priv->error) | 1813 | if (priv->error) |
1769 | IPW_ERROR("Sysfs 'error' log captured.\n"); | 1814 | IPW_DEBUG_FW("Sysfs 'error' log captured.\n"); |
1770 | else | 1815 | else |
1771 | IPW_ERROR("Error allocating sysfs 'error' " | 1816 | IPW_DEBUG_FW("Error allocating sysfs 'error' " |
1772 | "log.\n"); | 1817 | "log.\n"); |
1773 | #ifdef CONFIG_IPW2200_DEBUG | 1818 | #ifdef CONFIG_IPW2200_DEBUG |
1774 | if (ipw_debug_level & IPW_DL_FW_ERRORS) | 1819 | if (ipw_debug_level & IPW_DL_FW_ERRORS) |
1775 | ipw_dump_error_log(priv, priv->error); | 1820 | ipw_dump_error_log(priv, priv->error); |
@@ -1870,7 +1915,8 @@ static char *get_cmd_string(u8 cmd) | |||
1870 | } | 1915 | } |
1871 | 1916 | ||
1872 | #define HOST_COMPLETE_TIMEOUT HZ | 1917 | #define HOST_COMPLETE_TIMEOUT HZ |
1873 | static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) | 1918 | |
1919 | static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) | ||
1874 | { | 1920 | { |
1875 | int rc = 0; | 1921 | int rc = 0; |
1876 | unsigned long flags; | 1922 | unsigned long flags; |
@@ -1897,9 +1943,15 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) | |||
1897 | IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n", | 1943 | IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n", |
1898 | get_cmd_string(cmd->cmd), cmd->cmd, cmd->len, | 1944 | get_cmd_string(cmd->cmd), cmd->cmd, cmd->len, |
1899 | priv->status); | 1945 | priv->status); |
1900 | printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); | ||
1901 | 1946 | ||
1902 | rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0); | 1947 | #ifndef DEBUG_CMD_WEP_KEY |
1948 | if (cmd->cmd == IPW_CMD_WEP_KEY) | ||
1949 | IPW_DEBUG_HC("WEP_KEY command masked out for secure.\n"); | ||
1950 | else | ||
1951 | #endif | ||
1952 | printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); | ||
1953 | |||
1954 | rc = ipw_queue_tx_hcmd(priv, cmd->cmd, cmd->param, cmd->len, 0); | ||
1903 | if (rc) { | 1955 | if (rc) { |
1904 | priv->status &= ~STATUS_HCMD_ACTIVE; | 1956 | priv->status &= ~STATUS_HCMD_ACTIVE; |
1905 | IPW_ERROR("Failed to send %s: Reason %d\n", | 1957 | IPW_ERROR("Failed to send %s: Reason %d\n", |
@@ -1942,61 +1994,62 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) | |||
1942 | return rc; | 1994 | return rc; |
1943 | } | 1995 | } |
1944 | 1996 | ||
1945 | static int ipw_send_host_complete(struct ipw_priv *priv) | 1997 | static int ipw_send_cmd_simple(struct ipw_priv *priv, u8 command) |
1998 | { | ||
1999 | struct host_cmd cmd = { | ||
2000 | .cmd = command, | ||
2001 | }; | ||
2002 | |||
2003 | return __ipw_send_cmd(priv, &cmd); | ||
2004 | } | ||
2005 | |||
2006 | static int ipw_send_cmd_pdu(struct ipw_priv *priv, u8 command, u8 len, | ||
2007 | void *data) | ||
1946 | { | 2008 | { |
1947 | struct host_cmd cmd = { | 2009 | struct host_cmd cmd = { |
1948 | .cmd = IPW_CMD_HOST_COMPLETE, | 2010 | .cmd = command, |
1949 | .len = 0 | 2011 | .len = len, |
2012 | .param = data, | ||
1950 | }; | 2013 | }; |
1951 | 2014 | ||
2015 | return __ipw_send_cmd(priv, &cmd); | ||
2016 | } | ||
2017 | |||
2018 | static int ipw_send_host_complete(struct ipw_priv *priv) | ||
2019 | { | ||
1952 | if (!priv) { | 2020 | if (!priv) { |
1953 | IPW_ERROR("Invalid args\n"); | 2021 | IPW_ERROR("Invalid args\n"); |
1954 | return -1; | 2022 | return -1; |
1955 | } | 2023 | } |
1956 | 2024 | ||
1957 | return ipw_send_cmd(priv, &cmd); | 2025 | return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE); |
1958 | } | 2026 | } |
1959 | 2027 | ||
1960 | static int ipw_send_system_config(struct ipw_priv *priv, | 2028 | static int ipw_send_system_config(struct ipw_priv *priv, |
1961 | struct ipw_sys_config *config) | 2029 | struct ipw_sys_config *config) |
1962 | { | 2030 | { |
1963 | struct host_cmd cmd = { | ||
1964 | .cmd = IPW_CMD_SYSTEM_CONFIG, | ||
1965 | .len = sizeof(*config) | ||
1966 | }; | ||
1967 | |||
1968 | if (!priv || !config) { | 2031 | if (!priv || !config) { |
1969 | IPW_ERROR("Invalid args\n"); | 2032 | IPW_ERROR("Invalid args\n"); |
1970 | return -1; | 2033 | return -1; |
1971 | } | 2034 | } |
1972 | 2035 | ||
1973 | memcpy(cmd.param, config, sizeof(*config)); | 2036 | return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config), |
1974 | return ipw_send_cmd(priv, &cmd); | 2037 | config); |
1975 | } | 2038 | } |
1976 | 2039 | ||
1977 | static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) | 2040 | static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) |
1978 | { | 2041 | { |
1979 | struct host_cmd cmd = { | ||
1980 | .cmd = IPW_CMD_SSID, | ||
1981 | .len = min(len, IW_ESSID_MAX_SIZE) | ||
1982 | }; | ||
1983 | |||
1984 | if (!priv || !ssid) { | 2042 | if (!priv || !ssid) { |
1985 | IPW_ERROR("Invalid args\n"); | 2043 | IPW_ERROR("Invalid args\n"); |
1986 | return -1; | 2044 | return -1; |
1987 | } | 2045 | } |
1988 | 2046 | ||
1989 | memcpy(cmd.param, ssid, cmd.len); | 2047 | return ipw_send_cmd_pdu(priv, IPW_CMD_SSID, min(len, IW_ESSID_MAX_SIZE), |
1990 | return ipw_send_cmd(priv, &cmd); | 2048 | ssid); |
1991 | } | 2049 | } |
1992 | 2050 | ||
1993 | static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) | 2051 | static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) |
1994 | { | 2052 | { |
1995 | struct host_cmd cmd = { | ||
1996 | .cmd = IPW_CMD_ADAPTER_ADDRESS, | ||
1997 | .len = ETH_ALEN | ||
1998 | }; | ||
1999 | |||
2000 | if (!priv || !mac) { | 2053 | if (!priv || !mac) { |
2001 | IPW_ERROR("Invalid args\n"); | 2054 | IPW_ERROR("Invalid args\n"); |
2002 | return -1; | 2055 | return -1; |
@@ -2005,8 +2058,7 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) | |||
2005 | IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n", | 2058 | IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n", |
2006 | priv->net_dev->name, MAC_ARG(mac)); | 2059 | priv->net_dev->name, MAC_ARG(mac)); |
2007 | 2060 | ||
2008 | memcpy(cmd.param, mac, ETH_ALEN); | 2061 | return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac); |
2009 | return ipw_send_cmd(priv, &cmd); | ||
2010 | } | 2062 | } |
2011 | 2063 | ||
2012 | /* | 2064 | /* |
@@ -2036,9 +2088,9 @@ static void ipw_adapter_restart(void *adapter) | |||
2036 | static void ipw_bg_adapter_restart(void *data) | 2088 | static void ipw_bg_adapter_restart(void *data) |
2037 | { | 2089 | { |
2038 | struct ipw_priv *priv = data; | 2090 | struct ipw_priv *priv = data; |
2039 | down(&priv->sem); | 2091 | mutex_lock(&priv->mutex); |
2040 | ipw_adapter_restart(data); | 2092 | ipw_adapter_restart(data); |
2041 | up(&priv->sem); | 2093 | mutex_unlock(&priv->mutex); |
2042 | } | 2094 | } |
2043 | 2095 | ||
2044 | #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) | 2096 | #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) |
@@ -2048,8 +2100,8 @@ static void ipw_scan_check(void *data) | |||
2048 | struct ipw_priv *priv = data; | 2100 | struct ipw_priv *priv = data; |
2049 | if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { | 2101 | if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { |
2050 | IPW_DEBUG_SCAN("Scan completion watchdog resetting " | 2102 | IPW_DEBUG_SCAN("Scan completion watchdog resetting " |
2051 | "adapter (%dms).\n", | 2103 | "adapter after (%dms).\n", |
2052 | IPW_SCAN_CHECK_WATCHDOG / 100); | 2104 | jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); |
2053 | queue_work(priv->workqueue, &priv->adapter_restart); | 2105 | queue_work(priv->workqueue, &priv->adapter_restart); |
2054 | } | 2106 | } |
2055 | } | 2107 | } |
@@ -2057,59 +2109,48 @@ static void ipw_scan_check(void *data) | |||
2057 | static void ipw_bg_scan_check(void *data) | 2109 | static void ipw_bg_scan_check(void *data) |
2058 | { | 2110 | { |
2059 | struct ipw_priv *priv = data; | 2111 | struct ipw_priv *priv = data; |
2060 | down(&priv->sem); | 2112 | mutex_lock(&priv->mutex); |
2061 | ipw_scan_check(data); | 2113 | ipw_scan_check(data); |
2062 | up(&priv->sem); | 2114 | mutex_unlock(&priv->mutex); |
2063 | } | 2115 | } |
2064 | 2116 | ||
2065 | static int ipw_send_scan_request_ext(struct ipw_priv *priv, | 2117 | static int ipw_send_scan_request_ext(struct ipw_priv *priv, |
2066 | struct ipw_scan_request_ext *request) | 2118 | struct ipw_scan_request_ext *request) |
2067 | { | 2119 | { |
2068 | struct host_cmd cmd = { | 2120 | return ipw_send_cmd_pdu(priv, IPW_CMD_SCAN_REQUEST_EXT, |
2069 | .cmd = IPW_CMD_SCAN_REQUEST_EXT, | 2121 | sizeof(*request), request); |
2070 | .len = sizeof(*request) | ||
2071 | }; | ||
2072 | |||
2073 | memcpy(cmd.param, request, sizeof(*request)); | ||
2074 | return ipw_send_cmd(priv, &cmd); | ||
2075 | } | 2122 | } |
2076 | 2123 | ||
2077 | static int ipw_send_scan_abort(struct ipw_priv *priv) | 2124 | static int ipw_send_scan_abort(struct ipw_priv *priv) |
2078 | { | 2125 | { |
2079 | struct host_cmd cmd = { | ||
2080 | .cmd = IPW_CMD_SCAN_ABORT, | ||
2081 | .len = 0 | ||
2082 | }; | ||
2083 | |||
2084 | if (!priv) { | 2126 | if (!priv) { |
2085 | IPW_ERROR("Invalid args\n"); | 2127 | IPW_ERROR("Invalid args\n"); |
2086 | return -1; | 2128 | return -1; |
2087 | } | 2129 | } |
2088 | 2130 | ||
2089 | return ipw_send_cmd(priv, &cmd); | 2131 | return ipw_send_cmd_simple(priv, IPW_CMD_SCAN_ABORT); |
2090 | } | 2132 | } |
2091 | 2133 | ||
2092 | static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) | 2134 | static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) |
2093 | { | 2135 | { |
2094 | struct host_cmd cmd = { | 2136 | struct ipw_sensitivity_calib calib = { |
2095 | .cmd = IPW_CMD_SENSITIVITY_CALIB, | 2137 | .beacon_rssi_raw = sens, |
2096 | .len = sizeof(struct ipw_sensitivity_calib) | ||
2097 | }; | 2138 | }; |
2098 | struct ipw_sensitivity_calib *calib = (struct ipw_sensitivity_calib *) | 2139 | |
2099 | &cmd.param; | 2140 | return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib), |
2100 | calib->beacon_rssi_raw = sens; | 2141 | &calib); |
2101 | return ipw_send_cmd(priv, &cmd); | ||
2102 | } | 2142 | } |
2103 | 2143 | ||
2104 | static int ipw_send_associate(struct ipw_priv *priv, | 2144 | static int ipw_send_associate(struct ipw_priv *priv, |
2105 | struct ipw_associate *associate) | 2145 | struct ipw_associate *associate) |
2106 | { | 2146 | { |
2107 | struct host_cmd cmd = { | ||
2108 | .cmd = IPW_CMD_ASSOCIATE, | ||
2109 | .len = sizeof(*associate) | ||
2110 | }; | ||
2111 | |||
2112 | struct ipw_associate tmp_associate; | 2147 | struct ipw_associate tmp_associate; |
2148 | |||
2149 | if (!priv || !associate) { | ||
2150 | IPW_ERROR("Invalid args\n"); | ||
2151 | return -1; | ||
2152 | } | ||
2153 | |||
2113 | memcpy(&tmp_associate, associate, sizeof(*associate)); | 2154 | memcpy(&tmp_associate, associate, sizeof(*associate)); |
2114 | tmp_associate.policy_support = | 2155 | tmp_associate.policy_support = |
2115 | cpu_to_le16(tmp_associate.policy_support); | 2156 | cpu_to_le16(tmp_associate.policy_support); |
@@ -2122,85 +2163,60 @@ static int ipw_send_associate(struct ipw_priv *priv, | |||
2122 | cpu_to_le16(tmp_associate.beacon_interval); | 2163 | cpu_to_le16(tmp_associate.beacon_interval); |
2123 | tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window); | 2164 | tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window); |
2124 | 2165 | ||
2125 | if (!priv || !associate) { | 2166 | return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(tmp_associate), |
2126 | IPW_ERROR("Invalid args\n"); | 2167 | &tmp_associate); |
2127 | return -1; | ||
2128 | } | ||
2129 | |||
2130 | memcpy(cmd.param, &tmp_associate, sizeof(*associate)); | ||
2131 | return ipw_send_cmd(priv, &cmd); | ||
2132 | } | 2168 | } |
2133 | 2169 | ||
2134 | static int ipw_send_supported_rates(struct ipw_priv *priv, | 2170 | static int ipw_send_supported_rates(struct ipw_priv *priv, |
2135 | struct ipw_supported_rates *rates) | 2171 | struct ipw_supported_rates *rates) |
2136 | { | 2172 | { |
2137 | struct host_cmd cmd = { | ||
2138 | .cmd = IPW_CMD_SUPPORTED_RATES, | ||
2139 | .len = sizeof(*rates) | ||
2140 | }; | ||
2141 | |||
2142 | if (!priv || !rates) { | 2173 | if (!priv || !rates) { |
2143 | IPW_ERROR("Invalid args\n"); | 2174 | IPW_ERROR("Invalid args\n"); |
2144 | return -1; | 2175 | return -1; |
2145 | } | 2176 | } |
2146 | 2177 | ||
2147 | memcpy(cmd.param, rates, sizeof(*rates)); | 2178 | return ipw_send_cmd_pdu(priv, IPW_CMD_SUPPORTED_RATES, sizeof(*rates), |
2148 | return ipw_send_cmd(priv, &cmd); | 2179 | rates); |
2149 | } | 2180 | } |
2150 | 2181 | ||
2151 | static int ipw_set_random_seed(struct ipw_priv *priv) | 2182 | static int ipw_set_random_seed(struct ipw_priv *priv) |
2152 | { | 2183 | { |
2153 | struct host_cmd cmd = { | 2184 | u32 val; |
2154 | .cmd = IPW_CMD_SEED_NUMBER, | ||
2155 | .len = sizeof(u32) | ||
2156 | }; | ||
2157 | 2185 | ||
2158 | if (!priv) { | 2186 | if (!priv) { |
2159 | IPW_ERROR("Invalid args\n"); | 2187 | IPW_ERROR("Invalid args\n"); |
2160 | return -1; | 2188 | return -1; |
2161 | } | 2189 | } |
2162 | 2190 | ||
2163 | get_random_bytes(&cmd.param, sizeof(u32)); | 2191 | get_random_bytes(&val, sizeof(val)); |
2164 | 2192 | ||
2165 | return ipw_send_cmd(priv, &cmd); | 2193 | return ipw_send_cmd_pdu(priv, IPW_CMD_SEED_NUMBER, sizeof(val), &val); |
2166 | } | 2194 | } |
2167 | 2195 | ||
2168 | static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) | 2196 | static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) |
2169 | { | 2197 | { |
2170 | struct host_cmd cmd = { | ||
2171 | .cmd = IPW_CMD_CARD_DISABLE, | ||
2172 | .len = sizeof(u32) | ||
2173 | }; | ||
2174 | |||
2175 | if (!priv) { | 2198 | if (!priv) { |
2176 | IPW_ERROR("Invalid args\n"); | 2199 | IPW_ERROR("Invalid args\n"); |
2177 | return -1; | 2200 | return -1; |
2178 | } | 2201 | } |
2179 | 2202 | ||
2180 | *((u32 *) & cmd.param) = phy_off; | 2203 | return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off), |
2181 | 2204 | &phy_off); | |
2182 | return ipw_send_cmd(priv, &cmd); | ||
2183 | } | 2205 | } |
2184 | 2206 | ||
2185 | static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) | 2207 | static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) |
2186 | { | 2208 | { |
2187 | struct host_cmd cmd = { | ||
2188 | .cmd = IPW_CMD_TX_POWER, | ||
2189 | .len = sizeof(*power) | ||
2190 | }; | ||
2191 | |||
2192 | if (!priv || !power) { | 2209 | if (!priv || !power) { |
2193 | IPW_ERROR("Invalid args\n"); | 2210 | IPW_ERROR("Invalid args\n"); |
2194 | return -1; | 2211 | return -1; |
2195 | } | 2212 | } |
2196 | 2213 | ||
2197 | memcpy(cmd.param, power, sizeof(*power)); | 2214 | return ipw_send_cmd_pdu(priv, IPW_CMD_TX_POWER, sizeof(*power), power); |
2198 | return ipw_send_cmd(priv, &cmd); | ||
2199 | } | 2215 | } |
2200 | 2216 | ||
2201 | static int ipw_set_tx_power(struct ipw_priv *priv) | 2217 | static int ipw_set_tx_power(struct ipw_priv *priv) |
2202 | { | 2218 | { |
2203 | const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); | 2219 | const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); |
2204 | struct ipw_tx_power tx_power; | 2220 | struct ipw_tx_power tx_power; |
2205 | s8 max_power; | 2221 | s8 max_power; |
2206 | int i; | 2222 | int i; |
@@ -2247,18 +2263,14 @@ static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) | |||
2247 | struct ipw_rts_threshold rts_threshold = { | 2263 | struct ipw_rts_threshold rts_threshold = { |
2248 | .rts_threshold = rts, | 2264 | .rts_threshold = rts, |
2249 | }; | 2265 | }; |
2250 | struct host_cmd cmd = { | ||
2251 | .cmd = IPW_CMD_RTS_THRESHOLD, | ||
2252 | .len = sizeof(rts_threshold) | ||
2253 | }; | ||
2254 | 2266 | ||
2255 | if (!priv) { | 2267 | if (!priv) { |
2256 | IPW_ERROR("Invalid args\n"); | 2268 | IPW_ERROR("Invalid args\n"); |
2257 | return -1; | 2269 | return -1; |
2258 | } | 2270 | } |
2259 | 2271 | ||
2260 | memcpy(cmd.param, &rts_threshold, sizeof(rts_threshold)); | 2272 | return ipw_send_cmd_pdu(priv, IPW_CMD_RTS_THRESHOLD, |
2261 | return ipw_send_cmd(priv, &cmd); | 2273 | sizeof(rts_threshold), &rts_threshold); |
2262 | } | 2274 | } |
2263 | 2275 | ||
2264 | static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) | 2276 | static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) |
@@ -2266,27 +2278,19 @@ static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) | |||
2266 | struct ipw_frag_threshold frag_threshold = { | 2278 | struct ipw_frag_threshold frag_threshold = { |
2267 | .frag_threshold = frag, | 2279 | .frag_threshold = frag, |
2268 | }; | 2280 | }; |
2269 | struct host_cmd cmd = { | ||
2270 | .cmd = IPW_CMD_FRAG_THRESHOLD, | ||
2271 | .len = sizeof(frag_threshold) | ||
2272 | }; | ||
2273 | 2281 | ||
2274 | if (!priv) { | 2282 | if (!priv) { |
2275 | IPW_ERROR("Invalid args\n"); | 2283 | IPW_ERROR("Invalid args\n"); |
2276 | return -1; | 2284 | return -1; |
2277 | } | 2285 | } |
2278 | 2286 | ||
2279 | memcpy(cmd.param, &frag_threshold, sizeof(frag_threshold)); | 2287 | return ipw_send_cmd_pdu(priv, IPW_CMD_FRAG_THRESHOLD, |
2280 | return ipw_send_cmd(priv, &cmd); | 2288 | sizeof(frag_threshold), &frag_threshold); |
2281 | } | 2289 | } |
2282 | 2290 | ||
2283 | static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) | 2291 | static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) |
2284 | { | 2292 | { |
2285 | struct host_cmd cmd = { | 2293 | u32 param; |
2286 | .cmd = IPW_CMD_POWER_MODE, | ||
2287 | .len = sizeof(u32) | ||
2288 | }; | ||
2289 | u32 *param = (u32 *) (&cmd.param); | ||
2290 | 2294 | ||
2291 | if (!priv) { | 2295 | if (!priv) { |
2292 | IPW_ERROR("Invalid args\n"); | 2296 | IPW_ERROR("Invalid args\n"); |
@@ -2297,17 +2301,18 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) | |||
2297 | * level */ | 2301 | * level */ |
2298 | switch (mode) { | 2302 | switch (mode) { |
2299 | case IPW_POWER_BATTERY: | 2303 | case IPW_POWER_BATTERY: |
2300 | *param = IPW_POWER_INDEX_3; | 2304 | param = IPW_POWER_INDEX_3; |
2301 | break; | 2305 | break; |
2302 | case IPW_POWER_AC: | 2306 | case IPW_POWER_AC: |
2303 | *param = IPW_POWER_MODE_CAM; | 2307 | param = IPW_POWER_MODE_CAM; |
2304 | break; | 2308 | break; |
2305 | default: | 2309 | default: |
2306 | *param = mode; | 2310 | param = mode; |
2307 | break; | 2311 | break; |
2308 | } | 2312 | } |
2309 | 2313 | ||
2310 | return ipw_send_cmd(priv, &cmd); | 2314 | return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param), |
2315 | ¶m); | ||
2311 | } | 2316 | } |
2312 | 2317 | ||
2313 | static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) | 2318 | static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) |
@@ -2316,18 +2321,14 @@ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) | |||
2316 | .short_retry_limit = slimit, | 2321 | .short_retry_limit = slimit, |
2317 | .long_retry_limit = llimit | 2322 | .long_retry_limit = llimit |
2318 | }; | 2323 | }; |
2319 | struct host_cmd cmd = { | ||
2320 | .cmd = IPW_CMD_RETRY_LIMIT, | ||
2321 | .len = sizeof(retry_limit) | ||
2322 | }; | ||
2323 | 2324 | ||
2324 | if (!priv) { | 2325 | if (!priv) { |
2325 | IPW_ERROR("Invalid args\n"); | 2326 | IPW_ERROR("Invalid args\n"); |
2326 | return -1; | 2327 | return -1; |
2327 | } | 2328 | } |
2328 | 2329 | ||
2329 | memcpy(cmd.param, &retry_limit, sizeof(retry_limit)); | 2330 | return ipw_send_cmd_pdu(priv, IPW_CMD_RETRY_LIMIT, sizeof(retry_limit), |
2330 | return ipw_send_cmd(priv, &cmd); | 2331 | &retry_limit); |
2331 | } | 2332 | } |
2332 | 2333 | ||
2333 | /* | 2334 | /* |
@@ -2454,7 +2455,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) | |||
2454 | /* | 2455 | /* |
2455 | If the data looks correct, then copy it to our private | 2456 | If the data looks correct, then copy it to our private |
2456 | copy. Otherwise let the firmware know to perform the operation | 2457 | copy. Otherwise let the firmware know to perform the operation |
2457 | on it's own | 2458 | on its own. |
2458 | */ | 2459 | */ |
2459 | if (priv->eeprom[EEPROM_VERSION] != 0) { | 2460 | if (priv->eeprom[EEPROM_VERSION] != 0) { |
2460 | IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n"); | 2461 | IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n"); |
@@ -2707,22 +2708,25 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, | |||
2707 | 2708 | ||
2708 | static int ipw_fw_dma_wait(struct ipw_priv *priv) | 2709 | static int ipw_fw_dma_wait(struct ipw_priv *priv) |
2709 | { | 2710 | { |
2710 | u32 current_index = 0; | 2711 | u32 current_index = 0, previous_index; |
2711 | u32 watchdog = 0; | 2712 | u32 watchdog = 0; |
2712 | 2713 | ||
2713 | IPW_DEBUG_FW(">> : \n"); | 2714 | IPW_DEBUG_FW(">> : \n"); |
2714 | 2715 | ||
2715 | current_index = ipw_fw_dma_command_block_index(priv); | 2716 | current_index = ipw_fw_dma_command_block_index(priv); |
2716 | IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%8X\n", | 2717 | IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n", |
2717 | (int)priv->sram_desc.last_cb_index); | 2718 | (int)priv->sram_desc.last_cb_index); |
2718 | 2719 | ||
2719 | while (current_index < priv->sram_desc.last_cb_index) { | 2720 | while (current_index < priv->sram_desc.last_cb_index) { |
2720 | udelay(50); | 2721 | udelay(50); |
2722 | previous_index = current_index; | ||
2721 | current_index = ipw_fw_dma_command_block_index(priv); | 2723 | current_index = ipw_fw_dma_command_block_index(priv); |
2722 | 2724 | ||
2723 | watchdog++; | 2725 | if (previous_index < current_index) { |
2724 | 2726 | watchdog = 0; | |
2725 | if (watchdog > 400) { | 2727 | continue; |
2728 | } | ||
2729 | if (++watchdog > 400) { | ||
2726 | IPW_DEBUG_FW_INFO("Timeout\n"); | 2730 | IPW_DEBUG_FW_INFO("Timeout\n"); |
2727 | ipw_fw_dma_dump_command_block(priv); | 2731 | ipw_fw_dma_dump_command_block(priv); |
2728 | ipw_fw_dma_abort(priv); | 2732 | ipw_fw_dma_abort(priv); |
@@ -2772,6 +2776,7 @@ static inline int ipw_alive(struct ipw_priv *priv) | |||
2772 | return ipw_read32(priv, 0x90) == 0xd55555d5; | 2776 | return ipw_read32(priv, 0x90) == 0xd55555d5; |
2773 | } | 2777 | } |
2774 | 2778 | ||
2779 | /* timeout in msec, attempted in 10-msec quanta */ | ||
2775 | static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, | 2780 | static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, |
2776 | int timeout) | 2781 | int timeout) |
2777 | { | 2782 | { |
@@ -2800,10 +2805,11 @@ static int ipw_stop_master(struct ipw_priv *priv) | |||
2800 | /* stop master. typical delay - 0 */ | 2805 | /* stop master. typical delay - 0 */ |
2801 | ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); | 2806 | ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); |
2802 | 2807 | ||
2808 | /* timeout is in msec, polled in 10-msec quanta */ | ||
2803 | rc = ipw_poll_bit(priv, IPW_RESET_REG, | 2809 | rc = ipw_poll_bit(priv, IPW_RESET_REG, |
2804 | IPW_RESET_REG_MASTER_DISABLED, 100); | 2810 | IPW_RESET_REG_MASTER_DISABLED, 100); |
2805 | if (rc < 0) { | 2811 | if (rc < 0) { |
2806 | IPW_ERROR("stop master failed in 10ms\n"); | 2812 | IPW_ERROR("wait for stop master failed after 100ms\n"); |
2807 | return -1; | 2813 | return -1; |
2808 | } | 2814 | } |
2809 | 2815 | ||
@@ -2823,33 +2829,11 @@ static void ipw_arc_release(struct ipw_priv *priv) | |||
2823 | mdelay(5); | 2829 | mdelay(5); |
2824 | } | 2830 | } |
2825 | 2831 | ||
2826 | struct fw_header { | ||
2827 | u32 version; | ||
2828 | u32 mode; | ||
2829 | }; | ||
2830 | |||
2831 | struct fw_chunk { | 2832 | struct fw_chunk { |
2832 | u32 address; | 2833 | u32 address; |
2833 | u32 length; | 2834 | u32 length; |
2834 | }; | 2835 | }; |
2835 | 2836 | ||
2836 | #define IPW_FW_MAJOR_VERSION 2 | ||
2837 | #define IPW_FW_MINOR_VERSION 4 | ||
2838 | |||
2839 | #define IPW_FW_MINOR(x) ((x & 0xff) >> 8) | ||
2840 | #define IPW_FW_MAJOR(x) (x & 0xff) | ||
2841 | |||
2842 | #define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | IPW_FW_MAJOR_VERSION) | ||
2843 | |||
2844 | #define IPW_FW_PREFIX "ipw-" __stringify(IPW_FW_MAJOR_VERSION) \ | ||
2845 | "." __stringify(IPW_FW_MINOR_VERSION) "-" | ||
2846 | |||
2847 | #if IPW_FW_MAJOR_VERSION >= 2 && IPW_FW_MINOR_VERSION > 0 | ||
2848 | #define IPW_FW_NAME(x) IPW_FW_PREFIX "" x ".fw" | ||
2849 | #else | ||
2850 | #define IPW_FW_NAME(x) "ipw2200_" x ".fw" | ||
2851 | #endif | ||
2852 | |||
2853 | static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | 2837 | static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) |
2854 | { | 2838 | { |
2855 | int rc = 0, i, addr; | 2839 | int rc = 0, i, addr; |
@@ -2890,8 +2874,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
2890 | mdelay(1); | 2874 | mdelay(1); |
2891 | 2875 | ||
2892 | /* enable ucode store */ | 2876 | /* enable ucode store */ |
2893 | ipw_write_reg8(priv, DINO_CONTROL_REG, 0x0); | 2877 | ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0x0); |
2894 | ipw_write_reg8(priv, DINO_CONTROL_REG, DINO_ENABLE_CS); | 2878 | ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, DINO_ENABLE_CS); |
2895 | mdelay(1); | 2879 | mdelay(1); |
2896 | 2880 | ||
2897 | /* write ucode */ | 2881 | /* write ucode */ |
@@ -3036,7 +3020,7 @@ static int ipw_stop_nic(struct ipw_priv *priv) | |||
3036 | rc = ipw_poll_bit(priv, IPW_RESET_REG, | 3020 | rc = ipw_poll_bit(priv, IPW_RESET_REG, |
3037 | IPW_RESET_REG_MASTER_DISABLED, 500); | 3021 | IPW_RESET_REG_MASTER_DISABLED, 500); |
3038 | if (rc < 0) { | 3022 | if (rc < 0) { |
3039 | IPW_ERROR("wait for reg master disabled failed\n"); | 3023 | IPW_ERROR("wait for reg master disabled failed after 500ms\n"); |
3040 | return rc; | 3024 | return rc; |
3041 | } | 3025 | } |
3042 | 3026 | ||
@@ -3118,33 +3102,47 @@ static int ipw_reset_nic(struct ipw_priv *priv) | |||
3118 | return rc; | 3102 | return rc; |
3119 | } | 3103 | } |
3120 | 3104 | ||
3105 | |||
3106 | struct ipw_fw { | ||
3107 | u32 ver; | ||
3108 | u32 boot_size; | ||
3109 | u32 ucode_size; | ||
3110 | u32 fw_size; | ||
3111 | u8 data[0]; | ||
3112 | }; | ||
3113 | |||
3121 | static int ipw_get_fw(struct ipw_priv *priv, | 3114 | static int ipw_get_fw(struct ipw_priv *priv, |
3122 | const struct firmware **fw, const char *name) | 3115 | const struct firmware **raw, const char *name) |
3123 | { | 3116 | { |
3124 | struct fw_header *header; | 3117 | struct ipw_fw *fw; |
3125 | int rc; | 3118 | int rc; |
3126 | 3119 | ||
3127 | /* ask firmware_class module to get the boot firmware off disk */ | 3120 | /* ask firmware_class module to get the boot firmware off disk */ |
3128 | rc = request_firmware(fw, name, &priv->pci_dev->dev); | 3121 | rc = request_firmware(raw, name, &priv->pci_dev->dev); |
3129 | if (rc < 0) { | 3122 | if (rc < 0) { |
3130 | IPW_ERROR("%s load failed: Reason %d\n", name, rc); | 3123 | IPW_ERROR("%s request_firmware failed: Reason %d\n", name, rc); |
3131 | return rc; | 3124 | return rc; |
3132 | } | 3125 | } |
3133 | 3126 | ||
3134 | header = (struct fw_header *)(*fw)->data; | 3127 | if ((*raw)->size < sizeof(*fw)) { |
3135 | if (IPW_FW_MAJOR(le32_to_cpu(header->version)) != IPW_FW_MAJOR_VERSION) { | 3128 | IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size); |
3136 | IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n", | 3129 | return -EINVAL; |
3137 | name, | 3130 | } |
3138 | IPW_FW_MAJOR(le32_to_cpu(header->version)), | 3131 | |
3139 | IPW_FW_MAJOR_VERSION); | 3132 | fw = (void *)(*raw)->data; |
3133 | |||
3134 | if ((*raw)->size < sizeof(*fw) + | ||
3135 | fw->boot_size + fw->ucode_size + fw->fw_size) { | ||
3136 | IPW_ERROR("%s is too small or corrupt (%zd)\n", | ||
3137 | name, (*raw)->size); | ||
3140 | return -EINVAL; | 3138 | return -EINVAL; |
3141 | } | 3139 | } |
3142 | 3140 | ||
3143 | IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n", | 3141 | IPW_DEBUG_INFO("Read firmware '%s' image v%d.%d (%zd bytes)\n", |
3144 | name, | 3142 | name, |
3145 | IPW_FW_MAJOR(le32_to_cpu(header->version)), | 3143 | le32_to_cpu(fw->ver) >> 16, |
3146 | IPW_FW_MINOR(le32_to_cpu(header->version)), | 3144 | le32_to_cpu(fw->ver) & 0xff, |
3147 | (*fw)->size - sizeof(struct fw_header)); | 3145 | (*raw)->size - sizeof(*fw)); |
3148 | return 0; | 3146 | return 0; |
3149 | } | 3147 | } |
3150 | 3148 | ||
@@ -3184,17 +3182,13 @@ static void ipw_rx_queue_reset(struct ipw_priv *priv, | |||
3184 | 3182 | ||
3185 | #ifdef CONFIG_PM | 3183 | #ifdef CONFIG_PM |
3186 | static int fw_loaded = 0; | 3184 | static int fw_loaded = 0; |
3187 | static const struct firmware *bootfw = NULL; | 3185 | static const struct firmware *raw = NULL; |
3188 | static const struct firmware *firmware = NULL; | ||
3189 | static const struct firmware *ucode = NULL; | ||
3190 | 3186 | ||
3191 | static void free_firmware(void) | 3187 | static void free_firmware(void) |
3192 | { | 3188 | { |
3193 | if (fw_loaded) { | 3189 | if (fw_loaded) { |
3194 | release_firmware(bootfw); | 3190 | release_firmware(raw); |
3195 | release_firmware(ucode); | 3191 | raw = NULL; |
3196 | release_firmware(firmware); | ||
3197 | bootfw = ucode = firmware = NULL; | ||
3198 | fw_loaded = 0; | 3192 | fw_loaded = 0; |
3199 | } | 3193 | } |
3200 | } | 3194 | } |
@@ -3205,60 +3199,50 @@ static void free_firmware(void) | |||
3205 | static int ipw_load(struct ipw_priv *priv) | 3199 | static int ipw_load(struct ipw_priv *priv) |
3206 | { | 3200 | { |
3207 | #ifndef CONFIG_PM | 3201 | #ifndef CONFIG_PM |
3208 | const struct firmware *bootfw = NULL; | 3202 | const struct firmware *raw = NULL; |
3209 | const struct firmware *firmware = NULL; | ||
3210 | const struct firmware *ucode = NULL; | ||
3211 | #endif | 3203 | #endif |
3204 | struct ipw_fw *fw; | ||
3205 | u8 *boot_img, *ucode_img, *fw_img; | ||
3206 | u8 *name = NULL; | ||
3212 | int rc = 0, retries = 3; | 3207 | int rc = 0, retries = 3; |
3213 | 3208 | ||
3214 | #ifdef CONFIG_PM | 3209 | switch (priv->ieee->iw_mode) { |
3215 | if (!fw_loaded) { | 3210 | case IW_MODE_ADHOC: |
3216 | #endif | 3211 | name = "ipw2200-ibss.fw"; |
3217 | rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot")); | 3212 | break; |
3218 | if (rc) | ||
3219 | goto error; | ||
3220 | |||
3221 | switch (priv->ieee->iw_mode) { | ||
3222 | case IW_MODE_ADHOC: | ||
3223 | rc = ipw_get_fw(priv, &ucode, | ||
3224 | IPW_FW_NAME("ibss_ucode")); | ||
3225 | if (rc) | ||
3226 | goto error; | ||
3227 | |||
3228 | rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss")); | ||
3229 | break; | ||
3230 | |||
3231 | #ifdef CONFIG_IPW2200_MONITOR | 3213 | #ifdef CONFIG_IPW2200_MONITOR |
3232 | case IW_MODE_MONITOR: | 3214 | case IW_MODE_MONITOR: |
3233 | rc = ipw_get_fw(priv, &ucode, | 3215 | name = "ipw2200-sniffer.fw"; |
3234 | IPW_FW_NAME("sniffer_ucode")); | 3216 | break; |
3235 | if (rc) | ||
3236 | goto error; | ||
3237 | |||
3238 | rc = ipw_get_fw(priv, &firmware, | ||
3239 | IPW_FW_NAME("sniffer")); | ||
3240 | break; | ||
3241 | #endif | 3217 | #endif |
3242 | case IW_MODE_INFRA: | 3218 | case IW_MODE_INFRA: |
3243 | rc = ipw_get_fw(priv, &ucode, IPW_FW_NAME("bss_ucode")); | 3219 | name = "ipw2200-bss.fw"; |
3244 | if (rc) | 3220 | break; |
3245 | goto error; | 3221 | } |
3246 | |||
3247 | rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("bss")); | ||
3248 | break; | ||
3249 | 3222 | ||
3250 | default: | 3223 | if (!name) { |
3251 | rc = -EINVAL; | 3224 | rc = -EINVAL; |
3252 | } | 3225 | goto error; |
3226 | } | ||
3253 | 3227 | ||
3254 | if (rc) | 3228 | #ifdef CONFIG_PM |
3229 | if (!fw_loaded) { | ||
3230 | #endif | ||
3231 | rc = ipw_get_fw(priv, &raw, name); | ||
3232 | if (rc < 0) | ||
3255 | goto error; | 3233 | goto error; |
3256 | |||
3257 | #ifdef CONFIG_PM | 3234 | #ifdef CONFIG_PM |
3258 | fw_loaded = 1; | ||
3259 | } | 3235 | } |
3260 | #endif | 3236 | #endif |
3261 | 3237 | ||
3238 | fw = (void *)raw->data; | ||
3239 | boot_img = &fw->data[0]; | ||
3240 | ucode_img = &fw->data[fw->boot_size]; | ||
3241 | fw_img = &fw->data[fw->boot_size + fw->ucode_size]; | ||
3242 | |||
3243 | if (rc < 0) | ||
3244 | goto error; | ||
3245 | |||
3262 | if (!priv->rxq) | 3246 | if (!priv->rxq) |
3263 | priv->rxq = ipw_rx_queue_alloc(priv); | 3247 | priv->rxq = ipw_rx_queue_alloc(priv); |
3264 | else | 3248 | else |
@@ -3279,7 +3263,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3279 | ipw_stop_nic(priv); | 3263 | ipw_stop_nic(priv); |
3280 | 3264 | ||
3281 | rc = ipw_reset_nic(priv); | 3265 | rc = ipw_reset_nic(priv); |
3282 | if (rc) { | 3266 | if (rc < 0) { |
3283 | IPW_ERROR("Unable to reset NIC\n"); | 3267 | IPW_ERROR("Unable to reset NIC\n"); |
3284 | goto error; | 3268 | goto error; |
3285 | } | 3269 | } |
@@ -3288,8 +3272,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3288 | IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); | 3272 | IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); |
3289 | 3273 | ||
3290 | /* DMA the initial boot firmware into the device */ | 3274 | /* DMA the initial boot firmware into the device */ |
3291 | rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), | 3275 | rc = ipw_load_firmware(priv, boot_img, fw->boot_size); |
3292 | bootfw->size - sizeof(struct fw_header)); | ||
3293 | if (rc < 0) { | 3276 | if (rc < 0) { |
3294 | IPW_ERROR("Unable to load boot firmware: %d\n", rc); | 3277 | IPW_ERROR("Unable to load boot firmware: %d\n", rc); |
3295 | goto error; | 3278 | goto error; |
@@ -3298,7 +3281,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3298 | /* kick start the device */ | 3281 | /* kick start the device */ |
3299 | ipw_start_nic(priv); | 3282 | ipw_start_nic(priv); |
3300 | 3283 | ||
3301 | /* wait for the device to finish it's initial startup sequence */ | 3284 | /* wait for the device to finish its initial startup sequence */ |
3302 | rc = ipw_poll_bit(priv, IPW_INTA_RW, | 3285 | rc = ipw_poll_bit(priv, IPW_INTA_RW, |
3303 | IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); | 3286 | IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); |
3304 | if (rc < 0) { | 3287 | if (rc < 0) { |
@@ -3311,8 +3294,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3311 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); | 3294 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); |
3312 | 3295 | ||
3313 | /* DMA the ucode into the device */ | 3296 | /* DMA the ucode into the device */ |
3314 | rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), | 3297 | rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size); |
3315 | ucode->size - sizeof(struct fw_header)); | ||
3316 | if (rc < 0) { | 3298 | if (rc < 0) { |
3317 | IPW_ERROR("Unable to load ucode: %d\n", rc); | 3299 | IPW_ERROR("Unable to load ucode: %d\n", rc); |
3318 | goto error; | 3300 | goto error; |
@@ -3322,18 +3304,19 @@ static int ipw_load(struct ipw_priv *priv) | |||
3322 | ipw_stop_nic(priv); | 3304 | ipw_stop_nic(priv); |
3323 | 3305 | ||
3324 | /* DMA bss firmware into the device */ | 3306 | /* DMA bss firmware into the device */ |
3325 | rc = ipw_load_firmware(priv, firmware->data + | 3307 | rc = ipw_load_firmware(priv, fw_img, fw->fw_size); |
3326 | sizeof(struct fw_header), | ||
3327 | firmware->size - sizeof(struct fw_header)); | ||
3328 | if (rc < 0) { | 3308 | if (rc < 0) { |
3329 | IPW_ERROR("Unable to load firmware: %d\n", rc); | 3309 | IPW_ERROR("Unable to load firmware: %d\n", rc); |
3330 | goto error; | 3310 | goto error; |
3331 | } | 3311 | } |
3312 | #ifdef CONFIG_PM | ||
3313 | fw_loaded = 1; | ||
3314 | #endif | ||
3332 | 3315 | ||
3333 | ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0); | 3316 | ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0); |
3334 | 3317 | ||
3335 | rc = ipw_queue_reset(priv); | 3318 | rc = ipw_queue_reset(priv); |
3336 | if (rc) { | 3319 | if (rc < 0) { |
3337 | IPW_ERROR("Unable to initialize queues\n"); | 3320 | IPW_ERROR("Unable to initialize queues\n"); |
3338 | goto error; | 3321 | goto error; |
3339 | } | 3322 | } |
@@ -3362,7 +3345,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3362 | rc = ipw_poll_bit(priv, IPW_INTA_RW, | 3345 | rc = ipw_poll_bit(priv, IPW_INTA_RW, |
3363 | IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); | 3346 | IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); |
3364 | if (rc < 0) { | 3347 | if (rc < 0) { |
3365 | IPW_ERROR("device failed to start after 500ms\n"); | 3348 | IPW_ERROR("device failed to start within 500ms\n"); |
3366 | goto error; | 3349 | goto error; |
3367 | } | 3350 | } |
3368 | IPW_DEBUG_INFO("device response after %dms\n", rc); | 3351 | IPW_DEBUG_INFO("device response after %dms\n", rc); |
@@ -3386,9 +3369,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3386 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); | 3369 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); |
3387 | 3370 | ||
3388 | #ifndef CONFIG_PM | 3371 | #ifndef CONFIG_PM |
3389 | release_firmware(bootfw); | 3372 | release_firmware(raw); |
3390 | release_firmware(ucode); | ||
3391 | release_firmware(firmware); | ||
3392 | #endif | 3373 | #endif |
3393 | return 0; | 3374 | return 0; |
3394 | 3375 | ||
@@ -3398,15 +3379,11 @@ static int ipw_load(struct ipw_priv *priv) | |||
3398 | priv->rxq = NULL; | 3379 | priv->rxq = NULL; |
3399 | } | 3380 | } |
3400 | ipw_tx_queue_free(priv); | 3381 | ipw_tx_queue_free(priv); |
3401 | if (bootfw) | 3382 | if (raw) |
3402 | release_firmware(bootfw); | 3383 | release_firmware(raw); |
3403 | if (ucode) | ||
3404 | release_firmware(ucode); | ||
3405 | if (firmware) | ||
3406 | release_firmware(firmware); | ||
3407 | #ifdef CONFIG_PM | 3384 | #ifdef CONFIG_PM |
3408 | fw_loaded = 0; | 3385 | fw_loaded = 0; |
3409 | bootfw = ucode = firmware = NULL; | 3386 | raw = NULL; |
3410 | #endif | 3387 | #endif |
3411 | 3388 | ||
3412 | return rc; | 3389 | return rc; |
@@ -3715,9 +3692,9 @@ static int ipw_disassociate(void *data) | |||
3715 | static void ipw_bg_disassociate(void *data) | 3692 | static void ipw_bg_disassociate(void *data) |
3716 | { | 3693 | { |
3717 | struct ipw_priv *priv = data; | 3694 | struct ipw_priv *priv = data; |
3718 | down(&priv->sem); | 3695 | mutex_lock(&priv->mutex); |
3719 | ipw_disassociate(data); | 3696 | ipw_disassociate(data); |
3720 | up(&priv->sem); | 3697 | mutex_unlock(&priv->mutex); |
3721 | } | 3698 | } |
3722 | 3699 | ||
3723 | static void ipw_system_config(void *data) | 3700 | static void ipw_system_config(void *data) |
@@ -4077,9 +4054,9 @@ static void ipw_gather_stats(struct ipw_priv *priv) | |||
4077 | static void ipw_bg_gather_stats(void *data) | 4054 | static void ipw_bg_gather_stats(void *data) |
4078 | { | 4055 | { |
4079 | struct ipw_priv *priv = data; | 4056 | struct ipw_priv *priv = data; |
4080 | down(&priv->sem); | 4057 | mutex_lock(&priv->mutex); |
4081 | ipw_gather_stats(data); | 4058 | ipw_gather_stats(data); |
4082 | up(&priv->sem); | 4059 | mutex_unlock(&priv->mutex); |
4083 | } | 4060 | } |
4084 | 4061 | ||
4085 | /* Missed beacon behavior: | 4062 | /* Missed beacon behavior: |
@@ -4121,8 +4098,9 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, | |||
4121 | return; | 4098 | return; |
4122 | } | 4099 | } |
4123 | 4100 | ||
4124 | if (missed_count > priv->roaming_threshold && | 4101 | if (roaming && |
4125 | missed_count <= priv->disassociate_threshold) { | 4102 | (missed_count > priv->roaming_threshold && |
4103 | missed_count <= priv->disassociate_threshold)) { | ||
4126 | /* If we are not already roaming, set the ROAM | 4104 | /* If we are not already roaming, set the ROAM |
4127 | * bit in the status and kick off a scan. | 4105 | * bit in the status and kick off a scan. |
4128 | * This can happen several times before we reach | 4106 | * This can happen several times before we reach |
@@ -4150,7 +4128,6 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, | |||
4150 | } | 4128 | } |
4151 | 4129 | ||
4152 | IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count); | 4130 | IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count); |
4153 | |||
4154 | } | 4131 | } |
4155 | 4132 | ||
4156 | /** | 4133 | /** |
@@ -4527,10 +4504,9 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4527 | 4504 | ||
4528 | if (notif->size == sizeof(*x)) { | 4505 | if (notif->size == sizeof(*x)) { |
4529 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, | 4506 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, |
4530 | "link deterioration: '%s' " MAC_FMT | 4507 | "link deterioration: type %d, cnt %d\n", |
4531 | " \n", escape_essid(priv->essid, | 4508 | x->silence_notification_type, |
4532 | priv->essid_len), | 4509 | x->silence_count); |
4533 | MAC_ARG(priv->bssid)); | ||
4534 | memcpy(&priv->last_link_deterioration, x, | 4510 | memcpy(&priv->last_link_deterioration, x, |
4535 | sizeof(*x)); | 4511 | sizeof(*x)); |
4536 | } else { | 4512 | } else { |
@@ -4911,13 +4887,13 @@ static void ipw_rx_queue_replenish(void *data) | |||
4911 | static void ipw_bg_rx_queue_replenish(void *data) | 4887 | static void ipw_bg_rx_queue_replenish(void *data) |
4912 | { | 4888 | { |
4913 | struct ipw_priv *priv = data; | 4889 | struct ipw_priv *priv = data; |
4914 | down(&priv->sem); | 4890 | mutex_lock(&priv->mutex); |
4915 | ipw_rx_queue_replenish(data); | 4891 | ipw_rx_queue_replenish(data); |
4916 | up(&priv->sem); | 4892 | mutex_unlock(&priv->mutex); |
4917 | } | 4893 | } |
4918 | 4894 | ||
4919 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | 4895 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. |
4920 | * If an SKB has been detached, the POOL needs to have it's SKB set to NULL | 4896 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL |
4921 | * This free routine walks the list of POOL entries and if SKB is set to | 4897 | * This free routine walks the list of POOL entries and if SKB is set to |
4922 | * non NULL it is unmapped and freed | 4898 | * non NULL it is unmapped and freed |
4923 | */ | 4899 | */ |
@@ -5257,10 +5233,11 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5257 | if (priv->ieee->scan_age != 0 && | 5233 | if (priv->ieee->scan_age != 0 && |
5258 | time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { | 5234 | time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { |
5259 | IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " | 5235 | IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " |
5260 | "because of age: %lums.\n", | 5236 | "because of age: %ums.\n", |
5261 | escape_essid(network->ssid, network->ssid_len), | 5237 | escape_essid(network->ssid, network->ssid_len), |
5262 | MAC_ARG(network->bssid), | 5238 | MAC_ARG(network->bssid), |
5263 | 1000 * (jiffies - network->last_scanned) / HZ); | 5239 | jiffies_to_msecs(jiffies - |
5240 | network->last_scanned)); | ||
5264 | return 0; | 5241 | return 0; |
5265 | } | 5242 | } |
5266 | 5243 | ||
@@ -5369,7 +5346,7 @@ static void ipw_merge_adhoc_network(void *data) | |||
5369 | return; | 5346 | return; |
5370 | } | 5347 | } |
5371 | 5348 | ||
5372 | down(&priv->sem); | 5349 | mutex_lock(&priv->mutex); |
5373 | if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { | 5350 | if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { |
5374 | IPW_DEBUG_MERGE("remove network %s\n", | 5351 | IPW_DEBUG_MERGE("remove network %s\n", |
5375 | escape_essid(priv->essid, | 5352 | escape_essid(priv->essid, |
@@ -5379,7 +5356,7 @@ static void ipw_merge_adhoc_network(void *data) | |||
5379 | 5356 | ||
5380 | ipw_disassociate(priv); | 5357 | ipw_disassociate(priv); |
5381 | priv->assoc_network = match.network; | 5358 | priv->assoc_network = match.network; |
5382 | up(&priv->sem); | 5359 | mutex_unlock(&priv->mutex); |
5383 | return; | 5360 | return; |
5384 | } | 5361 | } |
5385 | } | 5362 | } |
@@ -5467,11 +5444,12 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5467 | if (network->last_associate && | 5444 | if (network->last_associate && |
5468 | time_after(network->last_associate + (HZ * 3UL), jiffies)) { | 5445 | time_after(network->last_associate + (HZ * 3UL), jiffies)) { |
5469 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " | 5446 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " |
5470 | "because of storming (%lus since last " | 5447 | "because of storming (%ums since last " |
5471 | "assoc attempt).\n", | 5448 | "assoc attempt).\n", |
5472 | escape_essid(network->ssid, network->ssid_len), | 5449 | escape_essid(network->ssid, network->ssid_len), |
5473 | MAC_ARG(network->bssid), | 5450 | MAC_ARG(network->bssid), |
5474 | (jiffies - network->last_associate) / HZ); | 5451 | jiffies_to_msecs(jiffies - |
5452 | network->last_associate)); | ||
5475 | return 0; | 5453 | return 0; |
5476 | } | 5454 | } |
5477 | 5455 | ||
@@ -5479,10 +5457,11 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5479 | if (priv->ieee->scan_age != 0 && | 5457 | if (priv->ieee->scan_age != 0 && |
5480 | time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { | 5458 | time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { |
5481 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " | 5459 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " |
5482 | "because of age: %lums.\n", | 5460 | "because of age: %ums.\n", |
5483 | escape_essid(network->ssid, network->ssid_len), | 5461 | escape_essid(network->ssid, network->ssid_len), |
5484 | MAC_ARG(network->bssid), | 5462 | MAC_ARG(network->bssid), |
5485 | 1000 * (jiffies - network->last_scanned) / HZ); | 5463 | jiffies_to_msecs(jiffies - |
5464 | network->last_scanned)); | ||
5486 | return 0; | 5465 | return 0; |
5487 | } | 5466 | } |
5488 | 5467 | ||
@@ -5510,15 +5489,6 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5510 | return 0; | 5489 | return 0; |
5511 | } | 5490 | } |
5512 | 5491 | ||
5513 | if (!priv->ieee->wpa_enabled && (network->wpa_ie_len > 0 || | ||
5514 | network->rsn_ie_len > 0)) { | ||
5515 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " | ||
5516 | "because of WPA capability mismatch.\n", | ||
5517 | escape_essid(network->ssid, network->ssid_len), | ||
5518 | MAC_ARG(network->bssid)); | ||
5519 | return 0; | ||
5520 | } | ||
5521 | |||
5522 | if ((priv->config & CFG_STATIC_BSSID) && | 5492 | if ((priv->config & CFG_STATIC_BSSID) && |
5523 | memcmp(network->bssid, priv->bssid, ETH_ALEN)) { | 5493 | memcmp(network->bssid, priv->bssid, ETH_ALEN)) { |
5524 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " | 5494 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " |
@@ -5539,7 +5509,7 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5539 | } | 5509 | } |
5540 | 5510 | ||
5541 | /* Filter out invalid channel in current GEO */ | 5511 | /* Filter out invalid channel in current GEO */ |
5542 | if (!ipw_is_valid_channel(priv->ieee, network->channel)) { | 5512 | if (!ieee80211_is_valid_channel(priv->ieee, network->channel)) { |
5543 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " | 5513 | IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " |
5544 | "because of invalid channel in current GEO\n", | 5514 | "because of invalid channel in current GEO\n", |
5545 | escape_essid(network->ssid, network->ssid_len), | 5515 | escape_essid(network->ssid, network->ssid_len), |
@@ -5584,7 +5554,7 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5584 | static void ipw_adhoc_create(struct ipw_priv *priv, | 5554 | static void ipw_adhoc_create(struct ipw_priv *priv, |
5585 | struct ieee80211_network *network) | 5555 | struct ieee80211_network *network) |
5586 | { | 5556 | { |
5587 | const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); | 5557 | const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); |
5588 | int i; | 5558 | int i; |
5589 | 5559 | ||
5590 | /* | 5560 | /* |
@@ -5599,10 +5569,10 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5599 | * FW fatal error. | 5569 | * FW fatal error. |
5600 | * | 5570 | * |
5601 | */ | 5571 | */ |
5602 | switch (ipw_is_valid_channel(priv->ieee, priv->channel)) { | 5572 | switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { |
5603 | case IEEE80211_52GHZ_BAND: | 5573 | case IEEE80211_52GHZ_BAND: |
5604 | network->mode = IEEE_A; | 5574 | network->mode = IEEE_A; |
5605 | i = ipw_channel_to_index(priv->ieee, priv->channel); | 5575 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); |
5606 | if (i == -1) | 5576 | if (i == -1) |
5607 | BUG(); | 5577 | BUG(); |
5608 | if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { | 5578 | if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { |
@@ -5616,7 +5586,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5616 | network->mode = IEEE_G; | 5586 | network->mode = IEEE_G; |
5617 | else | 5587 | else |
5618 | network->mode = IEEE_B; | 5588 | network->mode = IEEE_B; |
5619 | i = ipw_channel_to_index(priv->ieee, priv->channel); | 5589 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); |
5620 | if (i == -1) | 5590 | if (i == -1) |
5621 | BUG(); | 5591 | BUG(); |
5622 | if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { | 5592 | if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { |
@@ -5671,54 +5641,44 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5671 | 5641 | ||
5672 | static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index) | 5642 | static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index) |
5673 | { | 5643 | { |
5674 | struct ipw_tgi_tx_key *key; | 5644 | struct ipw_tgi_tx_key key; |
5675 | struct host_cmd cmd = { | ||
5676 | .cmd = IPW_CMD_TGI_TX_KEY, | ||
5677 | .len = sizeof(*key) | ||
5678 | }; | ||
5679 | 5645 | ||
5680 | if (!(priv->ieee->sec.flags & (1 << index))) | 5646 | if (!(priv->ieee->sec.flags & (1 << index))) |
5681 | return; | 5647 | return; |
5682 | 5648 | ||
5683 | key = (struct ipw_tgi_tx_key *)&cmd.param; | 5649 | key.key_id = index; |
5684 | key->key_id = index; | 5650 | memcpy(key.key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH); |
5685 | memcpy(key->key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH); | 5651 | key.security_type = type; |
5686 | key->security_type = type; | 5652 | key.station_index = 0; /* always 0 for BSS */ |
5687 | key->station_index = 0; /* always 0 for BSS */ | 5653 | key.flags = 0; |
5688 | key->flags = 0; | ||
5689 | /* 0 for new key; previous value of counter (after fatal error) */ | 5654 | /* 0 for new key; previous value of counter (after fatal error) */ |
5690 | key->tx_counter[0] = 0; | 5655 | key.tx_counter[0] = 0; |
5691 | key->tx_counter[1] = 0; | 5656 | key.tx_counter[1] = 0; |
5692 | 5657 | ||
5693 | ipw_send_cmd(priv, &cmd); | 5658 | ipw_send_cmd_pdu(priv, IPW_CMD_TGI_TX_KEY, sizeof(key), &key); |
5694 | } | 5659 | } |
5695 | 5660 | ||
5696 | static void ipw_send_wep_keys(struct ipw_priv *priv, int type) | 5661 | static void ipw_send_wep_keys(struct ipw_priv *priv, int type) |
5697 | { | 5662 | { |
5698 | struct ipw_wep_key *key; | 5663 | struct ipw_wep_key key; |
5699 | int i; | 5664 | int i; |
5700 | struct host_cmd cmd = { | ||
5701 | .cmd = IPW_CMD_WEP_KEY, | ||
5702 | .len = sizeof(*key) | ||
5703 | }; | ||
5704 | 5665 | ||
5705 | key = (struct ipw_wep_key *)&cmd.param; | 5666 | key.cmd_id = DINO_CMD_WEP_KEY; |
5706 | key->cmd_id = DINO_CMD_WEP_KEY; | 5667 | key.seq_num = 0; |
5707 | key->seq_num = 0; | ||
5708 | 5668 | ||
5709 | /* Note: AES keys cannot be set for multiple times. | 5669 | /* Note: AES keys cannot be set for multiple times. |
5710 | * Only set it at the first time. */ | 5670 | * Only set it at the first time. */ |
5711 | for (i = 0; i < 4; i++) { | 5671 | for (i = 0; i < 4; i++) { |
5712 | key->key_index = i | type; | 5672 | key.key_index = i | type; |
5713 | if (!(priv->ieee->sec.flags & (1 << i))) { | 5673 | if (!(priv->ieee->sec.flags & (1 << i))) { |
5714 | key->key_size = 0; | 5674 | key.key_size = 0; |
5715 | continue; | 5675 | continue; |
5716 | } | 5676 | } |
5717 | 5677 | ||
5718 | key->key_size = priv->ieee->sec.key_sizes[i]; | 5678 | key.key_size = priv->ieee->sec.key_sizes[i]; |
5719 | memcpy(key->key, priv->ieee->sec.keys[i], key->key_size); | 5679 | memcpy(key.key, priv->ieee->sec.keys[i], key.key_size); |
5720 | 5680 | ||
5721 | ipw_send_cmd(priv, &cmd); | 5681 | ipw_send_cmd_pdu(priv, IPW_CMD_WEP_KEY, sizeof(key), &key); |
5722 | } | 5682 | } |
5723 | } | 5683 | } |
5724 | 5684 | ||
@@ -5822,9 +5782,9 @@ static void ipw_adhoc_check(void *data) | |||
5822 | static void ipw_bg_adhoc_check(void *data) | 5782 | static void ipw_bg_adhoc_check(void *data) |
5823 | { | 5783 | { |
5824 | struct ipw_priv *priv = data; | 5784 | struct ipw_priv *priv = data; |
5825 | down(&priv->sem); | 5785 | mutex_lock(&priv->mutex); |
5826 | ipw_adhoc_check(data); | 5786 | ipw_adhoc_check(data); |
5827 | up(&priv->sem); | 5787 | mutex_unlock(&priv->mutex); |
5828 | } | 5788 | } |
5829 | 5789 | ||
5830 | #ifdef CONFIG_IPW2200_DEBUG | 5790 | #ifdef CONFIG_IPW2200_DEBUG |
@@ -5950,7 +5910,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, | |||
5950 | const struct ieee80211_geo *geo; | 5910 | const struct ieee80211_geo *geo; |
5951 | int i; | 5911 | int i; |
5952 | 5912 | ||
5953 | geo = ipw_get_geo(priv->ieee); | 5913 | geo = ieee80211_get_geo(priv->ieee); |
5954 | 5914 | ||
5955 | if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { | 5915 | if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { |
5956 | int start = channel_index; | 5916 | int start = channel_index; |
@@ -6010,7 +5970,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, | |||
6010 | channel_index++; | 5970 | channel_index++; |
6011 | scan->channels_list[channel_index] = channel; | 5971 | scan->channels_list[channel_index] = channel; |
6012 | index = | 5972 | index = |
6013 | ipw_channel_to_index(priv->ieee, channel); | 5973 | ieee80211_channel_to_index(priv->ieee, channel); |
6014 | ipw_set_scan_type(scan, channel_index, | 5974 | ipw_set_scan_type(scan, channel_index, |
6015 | geo->bg[index]. | 5975 | geo->bg[index]. |
6016 | flags & | 5976 | flags & |
@@ -6051,7 +6011,7 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
6051 | (priv->status & STATUS_EXIT_PENDING)) | 6011 | (priv->status & STATUS_EXIT_PENDING)) |
6052 | return 0; | 6012 | return 0; |
6053 | 6013 | ||
6054 | down(&priv->sem); | 6014 | mutex_lock(&priv->mutex); |
6055 | 6015 | ||
6056 | if (priv->status & STATUS_SCANNING) { | 6016 | if (priv->status & STATUS_SCANNING) { |
6057 | IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); | 6017 | IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); |
@@ -6092,7 +6052,7 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
6092 | u8 channel; | 6052 | u8 channel; |
6093 | u8 band = 0; | 6053 | u8 band = 0; |
6094 | 6054 | ||
6095 | switch (ipw_is_valid_channel(priv->ieee, priv->channel)) { | 6055 | switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { |
6096 | case IEEE80211_52GHZ_BAND: | 6056 | case IEEE80211_52GHZ_BAND: |
6097 | band = (u8) (IPW_A_MODE << 6) | 1; | 6057 | band = (u8) (IPW_A_MODE << 6) | 1; |
6098 | channel = priv->channel; | 6058 | channel = priv->channel; |
@@ -6159,16 +6119,16 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
6159 | queue_delayed_work(priv->workqueue, &priv->scan_check, | 6119 | queue_delayed_work(priv->workqueue, &priv->scan_check, |
6160 | IPW_SCAN_CHECK_WATCHDOG); | 6120 | IPW_SCAN_CHECK_WATCHDOG); |
6161 | done: | 6121 | done: |
6162 | up(&priv->sem); | 6122 | mutex_unlock(&priv->mutex); |
6163 | return err; | 6123 | return err; |
6164 | } | 6124 | } |
6165 | 6125 | ||
6166 | static void ipw_bg_abort_scan(void *data) | 6126 | static void ipw_bg_abort_scan(void *data) |
6167 | { | 6127 | { |
6168 | struct ipw_priv *priv = data; | 6128 | struct ipw_priv *priv = data; |
6169 | down(&priv->sem); | 6129 | mutex_lock(&priv->mutex); |
6170 | ipw_abort_scan(data); | 6130 | ipw_abort_scan(data); |
6171 | up(&priv->sem); | 6131 | mutex_unlock(&priv->mutex); |
6172 | } | 6132 | } |
6173 | 6133 | ||
6174 | static int ipw_wpa_enable(struct ipw_priv *priv, int value) | 6134 | static int ipw_wpa_enable(struct ipw_priv *priv, int value) |
@@ -6193,6 +6153,9 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) | |||
6193 | } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { | 6153 | } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { |
6194 | sec.auth_mode = WLAN_AUTH_OPEN; | 6154 | sec.auth_mode = WLAN_AUTH_OPEN; |
6195 | ieee->open_wep = 1; | 6155 | ieee->open_wep = 1; |
6156 | } else if (value & IW_AUTH_ALG_LEAP) { | ||
6157 | sec.auth_mode = WLAN_AUTH_LEAP; | ||
6158 | ieee->open_wep = 1; | ||
6196 | } else | 6159 | } else |
6197 | return -EINVAL; | 6160 | return -EINVAL; |
6198 | 6161 | ||
@@ -6204,7 +6167,8 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) | |||
6204 | return ret; | 6167 | return ret; |
6205 | } | 6168 | } |
6206 | 6169 | ||
6207 | void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len) | 6170 | static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, |
6171 | int wpa_ie_len) | ||
6208 | { | 6172 | { |
6209 | /* make sure WPA is enabled */ | 6173 | /* make sure WPA is enabled */ |
6210 | ipw_wpa_enable(priv, 1); | 6174 | ipw_wpa_enable(priv, 1); |
@@ -6215,15 +6179,10 @@ void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len) | |||
6215 | static int ipw_set_rsn_capa(struct ipw_priv *priv, | 6179 | static int ipw_set_rsn_capa(struct ipw_priv *priv, |
6216 | char *capabilities, int length) | 6180 | char *capabilities, int length) |
6217 | { | 6181 | { |
6218 | struct host_cmd cmd = { | ||
6219 | .cmd = IPW_CMD_RSN_CAPABILITIES, | ||
6220 | .len = length, | ||
6221 | }; | ||
6222 | |||
6223 | IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); | 6182 | IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); |
6224 | 6183 | ||
6225 | memcpy(cmd.param, capabilities, length); | 6184 | return ipw_send_cmd_pdu(priv, IPW_CMD_RSN_CAPABILITIES, length, |
6226 | return ipw_send_cmd(priv, &cmd); | 6185 | capabilities); |
6227 | } | 6186 | } |
6228 | 6187 | ||
6229 | /* | 6188 | /* |
@@ -6244,7 +6203,7 @@ static int ipw_wx_set_genie(struct net_device *dev, | |||
6244 | (wrqu->data.length && extra == NULL)) | 6203 | (wrqu->data.length && extra == NULL)) |
6245 | return -EINVAL; | 6204 | return -EINVAL; |
6246 | 6205 | ||
6247 | //down(&priv->sem); | 6206 | //mutex_lock(&priv->mutex); |
6248 | 6207 | ||
6249 | //if (!ieee->wpa_enabled) { | 6208 | //if (!ieee->wpa_enabled) { |
6250 | // err = -EOPNOTSUPP; | 6209 | // err = -EOPNOTSUPP; |
@@ -6270,7 +6229,7 @@ static int ipw_wx_set_genie(struct net_device *dev, | |||
6270 | 6229 | ||
6271 | ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); | 6230 | ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); |
6272 | out: | 6231 | out: |
6273 | //up(&priv->sem); | 6232 | //mutex_unlock(&priv->mutex); |
6274 | return err; | 6233 | return err; |
6275 | } | 6234 | } |
6276 | 6235 | ||
@@ -6283,7 +6242,7 @@ static int ipw_wx_get_genie(struct net_device *dev, | |||
6283 | struct ieee80211_device *ieee = priv->ieee; | 6242 | struct ieee80211_device *ieee = priv->ieee; |
6284 | int err = 0; | 6243 | int err = 0; |
6285 | 6244 | ||
6286 | //down(&priv->sem); | 6245 | //mutex_lock(&priv->mutex); |
6287 | 6246 | ||
6288 | //if (!ieee->wpa_enabled) { | 6247 | //if (!ieee->wpa_enabled) { |
6289 | // err = -EOPNOTSUPP; | 6248 | // err = -EOPNOTSUPP; |
@@ -6304,7 +6263,7 @@ static int ipw_wx_get_genie(struct net_device *dev, | |||
6304 | memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); | 6263 | memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); |
6305 | 6264 | ||
6306 | out: | 6265 | out: |
6307 | //up(&priv->sem); | 6266 | //mutex_unlock(&priv->mutex); |
6308 | return err; | 6267 | return err; |
6309 | } | 6268 | } |
6310 | 6269 | ||
@@ -6556,7 +6515,7 @@ static int ipw_wx_set_mlme(struct net_device *dev, | |||
6556 | * get the modulation type of the current network or | 6515 | * get the modulation type of the current network or |
6557 | * the card current mode | 6516 | * the card current mode |
6558 | */ | 6517 | */ |
6559 | u8 ipw_qos_current_mode(struct ipw_priv * priv) | 6518 | static u8 ipw_qos_current_mode(struct ipw_priv * priv) |
6560 | { | 6519 | { |
6561 | u8 mode = 0; | 6520 | u8 mode = 0; |
6562 | 6521 | ||
@@ -6964,12 +6923,12 @@ static void ipw_bg_qos_activate(void *data) | |||
6964 | if (priv == NULL) | 6923 | if (priv == NULL) |
6965 | return; | 6924 | return; |
6966 | 6925 | ||
6967 | down(&priv->sem); | 6926 | mutex_lock(&priv->mutex); |
6968 | 6927 | ||
6969 | if (priv->status & STATUS_ASSOCIATED) | 6928 | if (priv->status & STATUS_ASSOCIATED) |
6970 | ipw_qos_activate(priv, &(priv->assoc_network->qos_data)); | 6929 | ipw_qos_activate(priv, &(priv->assoc_network->qos_data)); |
6971 | 6930 | ||
6972 | up(&priv->sem); | 6931 | mutex_unlock(&priv->mutex); |
6973 | } | 6932 | } |
6974 | 6933 | ||
6975 | static int ipw_handle_probe_response(struct net_device *dev, | 6934 | static int ipw_handle_probe_response(struct net_device *dev, |
@@ -7010,25 +6969,15 @@ static int ipw_handle_assoc_response(struct net_device *dev, | |||
7010 | static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters | 6969 | static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters |
7011 | *qos_param) | 6970 | *qos_param) |
7012 | { | 6971 | { |
7013 | struct host_cmd cmd = { | 6972 | return ipw_send_cmd_pdu(priv, IPW_CMD_QOS_PARAMETERS, |
7014 | .cmd = IPW_CMD_QOS_PARAMETERS, | 6973 | sizeof(*qos_param) * 3, qos_param); |
7015 | .len = (sizeof(struct ieee80211_qos_parameters) * 3) | ||
7016 | }; | ||
7017 | |||
7018 | memcpy(cmd.param, qos_param, sizeof(*qos_param) * 3); | ||
7019 | return ipw_send_cmd(priv, &cmd); | ||
7020 | } | 6974 | } |
7021 | 6975 | ||
7022 | static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element | 6976 | static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element |
7023 | *qos_param) | 6977 | *qos_param) |
7024 | { | 6978 | { |
7025 | struct host_cmd cmd = { | 6979 | return ipw_send_cmd_pdu(priv, IPW_CMD_WME_INFO, sizeof(*qos_param), |
7026 | .cmd = IPW_CMD_WME_INFO, | 6980 | qos_param); |
7027 | .len = sizeof(*qos_param) | ||
7028 | }; | ||
7029 | |||
7030 | memcpy(cmd.param, qos_param, sizeof(*qos_param)); | ||
7031 | return ipw_send_cmd(priv, &cmd); | ||
7032 | } | 6981 | } |
7033 | 6982 | ||
7034 | #endif /* CONFIG_IPW_QOS */ | 6983 | #endif /* CONFIG_IPW_QOS */ |
@@ -7052,19 +7001,21 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
7052 | 7001 | ||
7053 | memset(&priv->assoc_request, 0, sizeof(priv->assoc_request)); | 7002 | memset(&priv->assoc_request, 0, sizeof(priv->assoc_request)); |
7054 | priv->assoc_request.channel = network->channel; | 7003 | priv->assoc_request.channel = network->channel; |
7004 | priv->assoc_request.auth_key = 0; | ||
7005 | |||
7055 | if ((priv->capability & CAP_PRIVACY_ON) && | 7006 | if ((priv->capability & CAP_PRIVACY_ON) && |
7056 | (priv->capability & CAP_SHARED_KEY)) { | 7007 | (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)) { |
7057 | priv->assoc_request.auth_type = AUTH_SHARED_KEY; | 7008 | priv->assoc_request.auth_type = AUTH_SHARED_KEY; |
7058 | priv->assoc_request.auth_key = priv->ieee->sec.active_key; | 7009 | priv->assoc_request.auth_key = priv->ieee->sec.active_key; |
7059 | 7010 | ||
7060 | if ((priv->capability & CAP_PRIVACY_ON) && | 7011 | if (priv->ieee->sec.level == SEC_LEVEL_1) |
7061 | (priv->ieee->sec.level == SEC_LEVEL_1) && | ||
7062 | !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) | ||
7063 | ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); | 7012 | ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); |
7064 | } else { | 7013 | |
7014 | } else if ((priv->capability & CAP_PRIVACY_ON) && | ||
7015 | (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP)) | ||
7016 | priv->assoc_request.auth_type = AUTH_LEAP; | ||
7017 | else | ||
7065 | priv->assoc_request.auth_type = AUTH_OPEN; | 7018 | priv->assoc_request.auth_type = AUTH_OPEN; |
7066 | priv->assoc_request.auth_key = 0; | ||
7067 | } | ||
7068 | 7019 | ||
7069 | if (priv->ieee->wpa_ie_len) { | 7020 | if (priv->ieee->wpa_ie_len) { |
7070 | priv->assoc_request.policy_support = 0x02; /* RSN active */ | 7021 | priv->assoc_request.policy_support = 0x02; /* RSN active */ |
@@ -7278,9 +7229,9 @@ static void ipw_roam(void *data) | |||
7278 | static void ipw_bg_roam(void *data) | 7229 | static void ipw_bg_roam(void *data) |
7279 | { | 7230 | { |
7280 | struct ipw_priv *priv = data; | 7231 | struct ipw_priv *priv = data; |
7281 | down(&priv->sem); | 7232 | mutex_lock(&priv->mutex); |
7282 | ipw_roam(data); | 7233 | ipw_roam(data); |
7283 | up(&priv->sem); | 7234 | mutex_unlock(&priv->mutex); |
7284 | } | 7235 | } |
7285 | 7236 | ||
7286 | static int ipw_associate(void *data) | 7237 | static int ipw_associate(void *data) |
@@ -7375,9 +7326,9 @@ static int ipw_associate(void *data) | |||
7375 | static void ipw_bg_associate(void *data) | 7326 | static void ipw_bg_associate(void *data) |
7376 | { | 7327 | { |
7377 | struct ipw_priv *priv = data; | 7328 | struct ipw_priv *priv = data; |
7378 | down(&priv->sem); | 7329 | mutex_lock(&priv->mutex); |
7379 | ipw_associate(data); | 7330 | ipw_associate(data); |
7380 | up(&priv->sem); | 7331 | mutex_unlock(&priv->mutex); |
7381 | } | 7332 | } |
7382 | 7333 | ||
7383 | static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, | 7334 | static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, |
@@ -7811,12 +7762,10 @@ static void ipw_rx(struct ipw_priv *priv) | |||
7811 | 7762 | ||
7812 | while (i != r) { | 7763 | while (i != r) { |
7813 | rxb = priv->rxq->queue[i]; | 7764 | rxb = priv->rxq->queue[i]; |
7814 | #ifdef CONFIG_IPW2200_DEBUG | ||
7815 | if (unlikely(rxb == NULL)) { | 7765 | if (unlikely(rxb == NULL)) { |
7816 | printk(KERN_CRIT "Queue not allocated!\n"); | 7766 | printk(KERN_CRIT "Queue not allocated!\n"); |
7817 | break; | 7767 | break; |
7818 | } | 7768 | } |
7819 | #endif | ||
7820 | priv->rxq->queue[i] = NULL; | 7769 | priv->rxq->queue[i] = NULL; |
7821 | 7770 | ||
7822 | pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, | 7771 | pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, |
@@ -7835,7 +7784,8 @@ static void ipw_rx(struct ipw_priv *priv) | |||
7835 | le16_to_cpu(pkt->u.frame.rssi_dbm) - | 7784 | le16_to_cpu(pkt->u.frame.rssi_dbm) - |
7836 | IPW_RSSI_TO_DBM, | 7785 | IPW_RSSI_TO_DBM, |
7837 | .signal = | 7786 | .signal = |
7838 | le16_to_cpu(pkt->u.frame.signal), | 7787 | le16_to_cpu(pkt->u.frame.rssi_dbm) - |
7788 | IPW_RSSI_TO_DBM + 0x100, | ||
7839 | .noise = | 7789 | .noise = |
7840 | le16_to_cpu(pkt->u.frame.noise), | 7790 | le16_to_cpu(pkt->u.frame.noise), |
7841 | .rate = pkt->u.frame.rate, | 7791 | .rate = pkt->u.frame.rate, |
@@ -7899,7 +7849,8 @@ static void ipw_rx(struct ipw_priv *priv) | |||
7899 | le16_to_cpu(pkt->u.frame.length)); | 7849 | le16_to_cpu(pkt->u.frame.length)); |
7900 | 7850 | ||
7901 | if (le16_to_cpu(pkt->u.frame.length) < | 7851 | if (le16_to_cpu(pkt->u.frame.length) < |
7902 | frame_hdr_len(header)) { | 7852 | ieee80211_get_hdrlen(le16_to_cpu( |
7853 | header->frame_ctl))) { | ||
7903 | IPW_DEBUG_DROP | 7854 | IPW_DEBUG_DROP |
7904 | ("Received packet is too small. " | 7855 | ("Received packet is too small. " |
7905 | "Dropping.\n"); | 7856 | "Dropping.\n"); |
@@ -7989,7 +7940,14 @@ static void ipw_rx(struct ipw_priv *priv) | |||
7989 | #define DEFAULT_SHORT_RETRY_LIMIT 7U | 7940 | #define DEFAULT_SHORT_RETRY_LIMIT 7U |
7990 | #define DEFAULT_LONG_RETRY_LIMIT 4U | 7941 | #define DEFAULT_LONG_RETRY_LIMIT 4U |
7991 | 7942 | ||
7992 | static int ipw_sw_reset(struct ipw_priv *priv, int init) | 7943 | /** |
7944 | * ipw_sw_reset | ||
7945 | * @option: options to control different reset behaviour | ||
7946 | * 0 = reset everything except the 'disable' module_param | ||
7947 | * 1 = reset everything and print out driver info (for probe only) | ||
7948 | * 2 = reset everything | ||
7949 | */ | ||
7950 | static int ipw_sw_reset(struct ipw_priv *priv, int option) | ||
7993 | { | 7951 | { |
7994 | int band, modulation; | 7952 | int band, modulation; |
7995 | int old_mode = priv->ieee->iw_mode; | 7953 | int old_mode = priv->ieee->iw_mode; |
@@ -8016,7 +7974,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) | |||
8016 | priv->essid_len = 0; | 7974 | priv->essid_len = 0; |
8017 | memset(priv->essid, 0, IW_ESSID_MAX_SIZE); | 7975 | memset(priv->essid, 0, IW_ESSID_MAX_SIZE); |
8018 | 7976 | ||
8019 | if (disable) { | 7977 | if (disable && option) { |
8020 | priv->status |= STATUS_RF_KILL_SW; | 7978 | priv->status |= STATUS_RF_KILL_SW; |
8021 | IPW_DEBUG_INFO("Radio disabled.\n"); | 7979 | IPW_DEBUG_INFO("Radio disabled.\n"); |
8022 | } | 7980 | } |
@@ -8068,7 +8026,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) | |||
8068 | 8026 | ||
8069 | if ((priv->pci_dev->device == 0x4223) || | 8027 | if ((priv->pci_dev->device == 0x4223) || |
8070 | (priv->pci_dev->device == 0x4224)) { | 8028 | (priv->pci_dev->device == 0x4224)) { |
8071 | if (init) | 8029 | if (option == 1) |
8072 | printk(KERN_INFO DRV_NAME | 8030 | printk(KERN_INFO DRV_NAME |
8073 | ": Detected Intel PRO/Wireless 2915ABG Network " | 8031 | ": Detected Intel PRO/Wireless 2915ABG Network " |
8074 | "Connection\n"); | 8032 | "Connection\n"); |
@@ -8079,7 +8037,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) | |||
8079 | priv->adapter = IPW_2915ABG; | 8037 | priv->adapter = IPW_2915ABG; |
8080 | priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; | 8038 | priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; |
8081 | } else { | 8039 | } else { |
8082 | if (init) | 8040 | if (option == 1) |
8083 | printk(KERN_INFO DRV_NAME | 8041 | printk(KERN_INFO DRV_NAME |
8084 | ": Detected Intel PRO/Wireless 2200BG Network " | 8042 | ": Detected Intel PRO/Wireless 2200BG Network " |
8085 | "Connection\n"); | 8043 | "Connection\n"); |
@@ -8126,7 +8084,7 @@ static int ipw_wx_get_name(struct net_device *dev, | |||
8126 | union iwreq_data *wrqu, char *extra) | 8084 | union iwreq_data *wrqu, char *extra) |
8127 | { | 8085 | { |
8128 | struct ipw_priv *priv = ieee80211_priv(dev); | 8086 | struct ipw_priv *priv = ieee80211_priv(dev); |
8129 | down(&priv->sem); | 8087 | mutex_lock(&priv->mutex); |
8130 | if (priv->status & STATUS_RF_KILL_MASK) | 8088 | if (priv->status & STATUS_RF_KILL_MASK) |
8131 | strcpy(wrqu->name, "radio off"); | 8089 | strcpy(wrqu->name, "radio off"); |
8132 | else if (!(priv->status & STATUS_ASSOCIATED)) | 8090 | else if (!(priv->status & STATUS_ASSOCIATED)) |
@@ -8135,7 +8093,7 @@ static int ipw_wx_get_name(struct net_device *dev, | |||
8135 | snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", | 8093 | snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", |
8136 | ipw_modes[priv->assoc_request.ieee_mode]); | 8094 | ipw_modes[priv->assoc_request.ieee_mode]); |
8137 | IPW_DEBUG_WX("Name: %s\n", wrqu->name); | 8095 | IPW_DEBUG_WX("Name: %s\n", wrqu->name); |
8138 | up(&priv->sem); | 8096 | mutex_unlock(&priv->mutex); |
8139 | return 0; | 8097 | return 0; |
8140 | } | 8098 | } |
8141 | 8099 | ||
@@ -8196,7 +8154,7 @@ static int ipw_wx_set_freq(struct net_device *dev, | |||
8196 | union iwreq_data *wrqu, char *extra) | 8154 | union iwreq_data *wrqu, char *extra) |
8197 | { | 8155 | { |
8198 | struct ipw_priv *priv = ieee80211_priv(dev); | 8156 | struct ipw_priv *priv = ieee80211_priv(dev); |
8199 | const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); | 8157 | const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); |
8200 | struct iw_freq *fwrq = &wrqu->freq; | 8158 | struct iw_freq *fwrq = &wrqu->freq; |
8201 | int ret = 0, i; | 8159 | int ret = 0, i; |
8202 | u8 channel, flags; | 8160 | u8 channel, flags; |
@@ -8204,24 +8162,24 @@ static int ipw_wx_set_freq(struct net_device *dev, | |||
8204 | 8162 | ||
8205 | if (fwrq->m == 0) { | 8163 | if (fwrq->m == 0) { |
8206 | IPW_DEBUG_WX("SET Freq/Channel -> any\n"); | 8164 | IPW_DEBUG_WX("SET Freq/Channel -> any\n"); |
8207 | down(&priv->sem); | 8165 | mutex_lock(&priv->mutex); |
8208 | ret = ipw_set_channel(priv, 0); | 8166 | ret = ipw_set_channel(priv, 0); |
8209 | up(&priv->sem); | 8167 | mutex_unlock(&priv->mutex); |
8210 | return ret; | 8168 | return ret; |
8211 | } | 8169 | } |
8212 | /* if setting by freq convert to channel */ | 8170 | /* if setting by freq convert to channel */ |
8213 | if (fwrq->e == 1) { | 8171 | if (fwrq->e == 1) { |
8214 | channel = ipw_freq_to_channel(priv->ieee, fwrq->m); | 8172 | channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m); |
8215 | if (channel == 0) | 8173 | if (channel == 0) |
8216 | return -EINVAL; | 8174 | return -EINVAL; |
8217 | } else | 8175 | } else |
8218 | channel = fwrq->m; | 8176 | channel = fwrq->m; |
8219 | 8177 | ||
8220 | if (!(band = ipw_is_valid_channel(priv->ieee, channel))) | 8178 | if (!(band = ieee80211_is_valid_channel(priv->ieee, channel))) |
8221 | return -EINVAL; | 8179 | return -EINVAL; |
8222 | 8180 | ||
8223 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) { | 8181 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) { |
8224 | i = ipw_channel_to_index(priv->ieee, channel); | 8182 | i = ieee80211_channel_to_index(priv->ieee, channel); |
8225 | if (i == -1) | 8183 | if (i == -1) |
8226 | return -EINVAL; | 8184 | return -EINVAL; |
8227 | 8185 | ||
@@ -8234,9 +8192,9 @@ static int ipw_wx_set_freq(struct net_device *dev, | |||
8234 | } | 8192 | } |
8235 | 8193 | ||
8236 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); | 8194 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); |
8237 | down(&priv->sem); | 8195 | mutex_lock(&priv->mutex); |
8238 | ret = ipw_set_channel(priv, channel); | 8196 | ret = ipw_set_channel(priv, channel); |
8239 | up(&priv->sem); | 8197 | mutex_unlock(&priv->mutex); |
8240 | return ret; | 8198 | return ret; |
8241 | } | 8199 | } |
8242 | 8200 | ||
@@ -8250,14 +8208,14 @@ static int ipw_wx_get_freq(struct net_device *dev, | |||
8250 | 8208 | ||
8251 | /* If we are associated, trying to associate, or have a statically | 8209 | /* If we are associated, trying to associate, or have a statically |
8252 | * configured CHANNEL then return that; otherwise return ANY */ | 8210 | * configured CHANNEL then return that; otherwise return ANY */ |
8253 | down(&priv->sem); | 8211 | mutex_lock(&priv->mutex); |
8254 | if (priv->config & CFG_STATIC_CHANNEL || | 8212 | if (priv->config & CFG_STATIC_CHANNEL || |
8255 | priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) | 8213 | priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) |
8256 | wrqu->freq.m = priv->channel; | 8214 | wrqu->freq.m = priv->channel; |
8257 | else | 8215 | else |
8258 | wrqu->freq.m = 0; | 8216 | wrqu->freq.m = 0; |
8259 | 8217 | ||
8260 | up(&priv->sem); | 8218 | mutex_unlock(&priv->mutex); |
8261 | IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); | 8219 | IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); |
8262 | return 0; | 8220 | return 0; |
8263 | } | 8221 | } |
@@ -8287,7 +8245,7 @@ static int ipw_wx_set_mode(struct net_device *dev, | |||
8287 | if (wrqu->mode == priv->ieee->iw_mode) | 8245 | if (wrqu->mode == priv->ieee->iw_mode) |
8288 | return 0; | 8246 | return 0; |
8289 | 8247 | ||
8290 | down(&priv->sem); | 8248 | mutex_lock(&priv->mutex); |
8291 | 8249 | ||
8292 | ipw_sw_reset(priv, 0); | 8250 | ipw_sw_reset(priv, 0); |
8293 | 8251 | ||
@@ -8310,7 +8268,7 @@ static int ipw_wx_set_mode(struct net_device *dev, | |||
8310 | priv->ieee->iw_mode = wrqu->mode; | 8268 | priv->ieee->iw_mode = wrqu->mode; |
8311 | 8269 | ||
8312 | queue_work(priv->workqueue, &priv->adapter_restart); | 8270 | queue_work(priv->workqueue, &priv->adapter_restart); |
8313 | up(&priv->sem); | 8271 | mutex_unlock(&priv->mutex); |
8314 | return err; | 8272 | return err; |
8315 | } | 8273 | } |
8316 | 8274 | ||
@@ -8319,10 +8277,10 @@ static int ipw_wx_get_mode(struct net_device *dev, | |||
8319 | union iwreq_data *wrqu, char *extra) | 8277 | union iwreq_data *wrqu, char *extra) |
8320 | { | 8278 | { |
8321 | struct ipw_priv *priv = ieee80211_priv(dev); | 8279 | struct ipw_priv *priv = ieee80211_priv(dev); |
8322 | down(&priv->sem); | 8280 | mutex_lock(&priv->mutex); |
8323 | wrqu->mode = priv->ieee->iw_mode; | 8281 | wrqu->mode = priv->ieee->iw_mode; |
8324 | IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode); | 8282 | IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode); |
8325 | up(&priv->sem); | 8283 | mutex_unlock(&priv->mutex); |
8326 | return 0; | 8284 | return 0; |
8327 | } | 8285 | } |
8328 | 8286 | ||
@@ -8349,7 +8307,7 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
8349 | { | 8307 | { |
8350 | struct ipw_priv *priv = ieee80211_priv(dev); | 8308 | struct ipw_priv *priv = ieee80211_priv(dev); |
8351 | struct iw_range *range = (struct iw_range *)extra; | 8309 | struct iw_range *range = (struct iw_range *)extra; |
8352 | const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); | 8310 | const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); |
8353 | int i = 0, j; | 8311 | int i = 0, j; |
8354 | 8312 | ||
8355 | wrqu->data.length = sizeof(*range); | 8313 | wrqu->data.length = sizeof(*range); |
@@ -8361,7 +8319,7 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
8361 | range->max_qual.qual = 100; | 8319 | range->max_qual.qual = 100; |
8362 | /* TODO: Find real max RSSI and stick here */ | 8320 | /* TODO: Find real max RSSI and stick here */ |
8363 | range->max_qual.level = 0; | 8321 | range->max_qual.level = 0; |
8364 | range->max_qual.noise = priv->ieee->worst_rssi + 0x100; | 8322 | range->max_qual.noise = 0; |
8365 | range->max_qual.updated = 7; /* Updated all three */ | 8323 | range->max_qual.updated = 7; /* Updated all three */ |
8366 | 8324 | ||
8367 | range->avg_qual.qual = 70; | 8325 | range->avg_qual.qual = 70; |
@@ -8369,7 +8327,7 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
8369 | range->avg_qual.level = 0; /* FIXME to real average level */ | 8327 | range->avg_qual.level = 0; /* FIXME to real average level */ |
8370 | range->avg_qual.noise = 0; | 8328 | range->avg_qual.noise = 0; |
8371 | range->avg_qual.updated = 7; /* Updated all three */ | 8329 | range->avg_qual.updated = 7; /* Updated all three */ |
8372 | down(&priv->sem); | 8330 | mutex_lock(&priv->mutex); |
8373 | range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES); | 8331 | range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES); |
8374 | 8332 | ||
8375 | for (i = 0; i < range->num_bitrates; i++) | 8333 | for (i = 0; i < range->num_bitrates; i++) |
@@ -8387,31 +8345,39 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
8387 | 8345 | ||
8388 | /* Set the Wireless Extension versions */ | 8346 | /* Set the Wireless Extension versions */ |
8389 | range->we_version_compiled = WIRELESS_EXT; | 8347 | range->we_version_compiled = WIRELESS_EXT; |
8390 | range->we_version_source = 16; | 8348 | range->we_version_source = 18; |
8391 | 8349 | ||
8392 | i = 0; | 8350 | i = 0; |
8393 | if (priv->ieee->mode & (IEEE_B | IEEE_G)) { | 8351 | if (priv->ieee->mode & (IEEE_B | IEEE_G)) { |
8394 | for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; | 8352 | for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; j++) { |
8395 | i++, j++) { | 8353 | if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && |
8354 | (geo->bg[j].flags & IEEE80211_CH_PASSIVE_ONLY)) | ||
8355 | continue; | ||
8356 | |||
8396 | range->freq[i].i = geo->bg[j].channel; | 8357 | range->freq[i].i = geo->bg[j].channel; |
8397 | range->freq[i].m = geo->bg[j].freq * 100000; | 8358 | range->freq[i].m = geo->bg[j].freq * 100000; |
8398 | range->freq[i].e = 1; | 8359 | range->freq[i].e = 1; |
8360 | i++; | ||
8399 | } | 8361 | } |
8400 | } | 8362 | } |
8401 | 8363 | ||
8402 | if (priv->ieee->mode & IEEE_A) { | 8364 | if (priv->ieee->mode & IEEE_A) { |
8403 | for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; | 8365 | for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; j++) { |
8404 | i++, j++) { | 8366 | if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && |
8367 | (geo->a[j].flags & IEEE80211_CH_PASSIVE_ONLY)) | ||
8368 | continue; | ||
8369 | |||
8405 | range->freq[i].i = geo->a[j].channel; | 8370 | range->freq[i].i = geo->a[j].channel; |
8406 | range->freq[i].m = geo->a[j].freq * 100000; | 8371 | range->freq[i].m = geo->a[j].freq * 100000; |
8407 | range->freq[i].e = 1; | 8372 | range->freq[i].e = 1; |
8373 | i++; | ||
8408 | } | 8374 | } |
8409 | } | 8375 | } |
8410 | 8376 | ||
8411 | range->num_channels = i; | 8377 | range->num_channels = i; |
8412 | range->num_frequency = i; | 8378 | range->num_frequency = i; |
8413 | 8379 | ||
8414 | up(&priv->sem); | 8380 | mutex_unlock(&priv->mutex); |
8415 | 8381 | ||
8416 | /* Event capability (kernel + driver) */ | 8382 | /* Event capability (kernel + driver) */ |
8417 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | | 8383 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | |
@@ -8419,6 +8385,9 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
8419 | IW_EVENT_CAPA_MASK(SIOCGIWAP)); | 8385 | IW_EVENT_CAPA_MASK(SIOCGIWAP)); |
8420 | range->event_capa[1] = IW_EVENT_CAPA_K_1; | 8386 | range->event_capa[1] = IW_EVENT_CAPA_K_1; |
8421 | 8387 | ||
8388 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | ||
8389 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; | ||
8390 | |||
8422 | IPW_DEBUG_WX("GET Range\n"); | 8391 | IPW_DEBUG_WX("GET Range\n"); |
8423 | return 0; | 8392 | return 0; |
8424 | } | 8393 | } |
@@ -8438,7 +8407,7 @@ static int ipw_wx_set_wap(struct net_device *dev, | |||
8438 | 8407 | ||
8439 | if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) | 8408 | if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) |
8440 | return -EINVAL; | 8409 | return -EINVAL; |
8441 | down(&priv->sem); | 8410 | mutex_lock(&priv->mutex); |
8442 | if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || | 8411 | if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || |
8443 | !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { | 8412 | !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { |
8444 | /* we disable mandatory BSSID association */ | 8413 | /* we disable mandatory BSSID association */ |
@@ -8447,14 +8416,14 @@ static int ipw_wx_set_wap(struct net_device *dev, | |||
8447 | IPW_DEBUG_ASSOC("Attempting to associate with new " | 8416 | IPW_DEBUG_ASSOC("Attempting to associate with new " |
8448 | "parameters.\n"); | 8417 | "parameters.\n"); |
8449 | ipw_associate(priv); | 8418 | ipw_associate(priv); |
8450 | up(&priv->sem); | 8419 | mutex_unlock(&priv->mutex); |
8451 | return 0; | 8420 | return 0; |
8452 | } | 8421 | } |
8453 | 8422 | ||
8454 | priv->config |= CFG_STATIC_BSSID; | 8423 | priv->config |= CFG_STATIC_BSSID; |
8455 | if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) { | 8424 | if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) { |
8456 | IPW_DEBUG_WX("BSSID set to current BSSID.\n"); | 8425 | IPW_DEBUG_WX("BSSID set to current BSSID.\n"); |
8457 | up(&priv->sem); | 8426 | mutex_unlock(&priv->mutex); |
8458 | return 0; | 8427 | return 0; |
8459 | } | 8428 | } |
8460 | 8429 | ||
@@ -8468,7 +8437,7 @@ static int ipw_wx_set_wap(struct net_device *dev, | |||
8468 | if (!ipw_disassociate(priv)) | 8437 | if (!ipw_disassociate(priv)) |
8469 | ipw_associate(priv); | 8438 | ipw_associate(priv); |
8470 | 8439 | ||
8471 | up(&priv->sem); | 8440 | mutex_unlock(&priv->mutex); |
8472 | return 0; | 8441 | return 0; |
8473 | } | 8442 | } |
8474 | 8443 | ||
@@ -8479,7 +8448,7 @@ static int ipw_wx_get_wap(struct net_device *dev, | |||
8479 | struct ipw_priv *priv = ieee80211_priv(dev); | 8448 | struct ipw_priv *priv = ieee80211_priv(dev); |
8480 | /* If we are associated, trying to associate, or have a statically | 8449 | /* If we are associated, trying to associate, or have a statically |
8481 | * configured BSSID then return that; otherwise return ANY */ | 8450 | * configured BSSID then return that; otherwise return ANY */ |
8482 | down(&priv->sem); | 8451 | mutex_lock(&priv->mutex); |
8483 | if (priv->config & CFG_STATIC_BSSID || | 8452 | if (priv->config & CFG_STATIC_BSSID || |
8484 | priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { | 8453 | priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { |
8485 | wrqu->ap_addr.sa_family = ARPHRD_ETHER; | 8454 | wrqu->ap_addr.sa_family = ARPHRD_ETHER; |
@@ -8489,7 +8458,7 @@ static int ipw_wx_get_wap(struct net_device *dev, | |||
8489 | 8458 | ||
8490 | IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n", | 8459 | IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n", |
8491 | MAC_ARG(wrqu->ap_addr.sa_data)); | 8460 | MAC_ARG(wrqu->ap_addr.sa_data)); |
8492 | up(&priv->sem); | 8461 | mutex_unlock(&priv->mutex); |
8493 | return 0; | 8462 | return 0; |
8494 | } | 8463 | } |
8495 | 8464 | ||
@@ -8500,7 +8469,7 @@ static int ipw_wx_set_essid(struct net_device *dev, | |||
8500 | struct ipw_priv *priv = ieee80211_priv(dev); | 8469 | struct ipw_priv *priv = ieee80211_priv(dev); |
8501 | char *essid = ""; /* ANY */ | 8470 | char *essid = ""; /* ANY */ |
8502 | int length = 0; | 8471 | int length = 0; |
8503 | down(&priv->sem); | 8472 | mutex_lock(&priv->mutex); |
8504 | if (wrqu->essid.flags && wrqu->essid.length) { | 8473 | if (wrqu->essid.flags && wrqu->essid.length) { |
8505 | length = wrqu->essid.length - 1; | 8474 | length = wrqu->essid.length - 1; |
8506 | essid = extra; | 8475 | essid = extra; |
@@ -8515,7 +8484,7 @@ static int ipw_wx_set_essid(struct net_device *dev, | |||
8515 | priv->config &= ~CFG_STATIC_ESSID; | 8484 | priv->config &= ~CFG_STATIC_ESSID; |
8516 | ipw_associate(priv); | 8485 | ipw_associate(priv); |
8517 | } | 8486 | } |
8518 | up(&priv->sem); | 8487 | mutex_unlock(&priv->mutex); |
8519 | return 0; | 8488 | return 0; |
8520 | } | 8489 | } |
8521 | 8490 | ||
@@ -8525,7 +8494,7 @@ static int ipw_wx_set_essid(struct net_device *dev, | |||
8525 | 8494 | ||
8526 | if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) { | 8495 | if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) { |
8527 | IPW_DEBUG_WX("ESSID set to current ESSID.\n"); | 8496 | IPW_DEBUG_WX("ESSID set to current ESSID.\n"); |
8528 | up(&priv->sem); | 8497 | mutex_unlock(&priv->mutex); |
8529 | return 0; | 8498 | return 0; |
8530 | } | 8499 | } |
8531 | 8500 | ||
@@ -8540,7 +8509,7 @@ static int ipw_wx_set_essid(struct net_device *dev, | |||
8540 | if (!ipw_disassociate(priv)) | 8509 | if (!ipw_disassociate(priv)) |
8541 | ipw_associate(priv); | 8510 | ipw_associate(priv); |
8542 | 8511 | ||
8543 | up(&priv->sem); | 8512 | mutex_unlock(&priv->mutex); |
8544 | return 0; | 8513 | return 0; |
8545 | } | 8514 | } |
8546 | 8515 | ||
@@ -8552,7 +8521,7 @@ static int ipw_wx_get_essid(struct net_device *dev, | |||
8552 | 8521 | ||
8553 | /* If we are associated, trying to associate, or have a statically | 8522 | /* If we are associated, trying to associate, or have a statically |
8554 | * configured ESSID then return that; otherwise return ANY */ | 8523 | * configured ESSID then return that; otherwise return ANY */ |
8555 | down(&priv->sem); | 8524 | mutex_lock(&priv->mutex); |
8556 | if (priv->config & CFG_STATIC_ESSID || | 8525 | if (priv->config & CFG_STATIC_ESSID || |
8557 | priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { | 8526 | priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { |
8558 | IPW_DEBUG_WX("Getting essid: '%s'\n", | 8527 | IPW_DEBUG_WX("Getting essid: '%s'\n", |
@@ -8565,7 +8534,7 @@ static int ipw_wx_get_essid(struct net_device *dev, | |||
8565 | wrqu->essid.length = 0; | 8534 | wrqu->essid.length = 0; |
8566 | wrqu->essid.flags = 0; /* active */ | 8535 | wrqu->essid.flags = 0; /* active */ |
8567 | } | 8536 | } |
8568 | up(&priv->sem); | 8537 | mutex_unlock(&priv->mutex); |
8569 | return 0; | 8538 | return 0; |
8570 | } | 8539 | } |
8571 | 8540 | ||
@@ -8578,12 +8547,12 @@ static int ipw_wx_set_nick(struct net_device *dev, | |||
8578 | IPW_DEBUG_WX("Setting nick to '%s'\n", extra); | 8547 | IPW_DEBUG_WX("Setting nick to '%s'\n", extra); |
8579 | if (wrqu->data.length > IW_ESSID_MAX_SIZE) | 8548 | if (wrqu->data.length > IW_ESSID_MAX_SIZE) |
8580 | return -E2BIG; | 8549 | return -E2BIG; |
8581 | down(&priv->sem); | 8550 | mutex_lock(&priv->mutex); |
8582 | wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); | 8551 | wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); |
8583 | memset(priv->nick, 0, sizeof(priv->nick)); | 8552 | memset(priv->nick, 0, sizeof(priv->nick)); |
8584 | memcpy(priv->nick, extra, wrqu->data.length); | 8553 | memcpy(priv->nick, extra, wrqu->data.length); |
8585 | IPW_DEBUG_TRACE("<<\n"); | 8554 | IPW_DEBUG_TRACE("<<\n"); |
8586 | up(&priv->sem); | 8555 | mutex_unlock(&priv->mutex); |
8587 | return 0; | 8556 | return 0; |
8588 | 8557 | ||
8589 | } | 8558 | } |
@@ -8594,11 +8563,57 @@ static int ipw_wx_get_nick(struct net_device *dev, | |||
8594 | { | 8563 | { |
8595 | struct ipw_priv *priv = ieee80211_priv(dev); | 8564 | struct ipw_priv *priv = ieee80211_priv(dev); |
8596 | IPW_DEBUG_WX("Getting nick\n"); | 8565 | IPW_DEBUG_WX("Getting nick\n"); |
8597 | down(&priv->sem); | 8566 | mutex_lock(&priv->mutex); |
8598 | wrqu->data.length = strlen(priv->nick) + 1; | 8567 | wrqu->data.length = strlen(priv->nick) + 1; |
8599 | memcpy(extra, priv->nick, wrqu->data.length); | 8568 | memcpy(extra, priv->nick, wrqu->data.length); |
8600 | wrqu->data.flags = 1; /* active */ | 8569 | wrqu->data.flags = 1; /* active */ |
8601 | up(&priv->sem); | 8570 | mutex_unlock(&priv->mutex); |
8571 | return 0; | ||
8572 | } | ||
8573 | |||
8574 | static int ipw_wx_set_sens(struct net_device *dev, | ||
8575 | struct iw_request_info *info, | ||
8576 | union iwreq_data *wrqu, char *extra) | ||
8577 | { | ||
8578 | struct ipw_priv *priv = ieee80211_priv(dev); | ||
8579 | int err = 0; | ||
8580 | |||
8581 | IPW_DEBUG_WX("Setting roaming threshold to %d\n", wrqu->sens.value); | ||
8582 | IPW_DEBUG_WX("Setting disassociate threshold to %d\n", 3*wrqu->sens.value); | ||
8583 | mutex_lock(&priv->mutex); | ||
8584 | |||
8585 | if (wrqu->sens.fixed == 0) | ||
8586 | { | ||
8587 | priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; | ||
8588 | priv->disassociate_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; | ||
8589 | goto out; | ||
8590 | } | ||
8591 | if ((wrqu->sens.value > IPW_MB_ROAMING_THRESHOLD_MAX) || | ||
8592 | (wrqu->sens.value < IPW_MB_ROAMING_THRESHOLD_MIN)) { | ||
8593 | err = -EINVAL; | ||
8594 | goto out; | ||
8595 | } | ||
8596 | |||
8597 | priv->roaming_threshold = wrqu->sens.value; | ||
8598 | priv->disassociate_threshold = 3*wrqu->sens.value; | ||
8599 | out: | ||
8600 | mutex_unlock(&priv->mutex); | ||
8601 | return err; | ||
8602 | } | ||
8603 | |||
8604 | static int ipw_wx_get_sens(struct net_device *dev, | ||
8605 | struct iw_request_info *info, | ||
8606 | union iwreq_data *wrqu, char *extra) | ||
8607 | { | ||
8608 | struct ipw_priv *priv = ieee80211_priv(dev); | ||
8609 | mutex_lock(&priv->mutex); | ||
8610 | wrqu->sens.fixed = 1; | ||
8611 | wrqu->sens.value = priv->roaming_threshold; | ||
8612 | mutex_unlock(&priv->mutex); | ||
8613 | |||
8614 | IPW_DEBUG_WX("GET roaming threshold -> %s %d \n", | ||
8615 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); | ||
8616 | |||
8602 | return 0; | 8617 | return 0; |
8603 | } | 8618 | } |
8604 | 8619 | ||
@@ -8691,7 +8706,7 @@ static int ipw_wx_set_rate(struct net_device *dev, | |||
8691 | apply: | 8706 | apply: |
8692 | IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", | 8707 | IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", |
8693 | mask, fixed ? "fixed" : "sub-rates"); | 8708 | mask, fixed ? "fixed" : "sub-rates"); |
8694 | down(&priv->sem); | 8709 | mutex_lock(&priv->mutex); |
8695 | if (mask == IEEE80211_DEFAULT_RATES_MASK) { | 8710 | if (mask == IEEE80211_DEFAULT_RATES_MASK) { |
8696 | priv->config &= ~CFG_FIXED_RATE; | 8711 | priv->config &= ~CFG_FIXED_RATE; |
8697 | ipw_set_fixed_rate(priv, priv->ieee->mode); | 8712 | ipw_set_fixed_rate(priv, priv->ieee->mode); |
@@ -8700,7 +8715,7 @@ static int ipw_wx_set_rate(struct net_device *dev, | |||
8700 | 8715 | ||
8701 | if (priv->rates_mask == mask) { | 8716 | if (priv->rates_mask == mask) { |
8702 | IPW_DEBUG_WX("Mask set to current mask.\n"); | 8717 | IPW_DEBUG_WX("Mask set to current mask.\n"); |
8703 | up(&priv->sem); | 8718 | mutex_unlock(&priv->mutex); |
8704 | return 0; | 8719 | return 0; |
8705 | } | 8720 | } |
8706 | 8721 | ||
@@ -8711,7 +8726,7 @@ static int ipw_wx_set_rate(struct net_device *dev, | |||
8711 | if (!ipw_disassociate(priv)) | 8726 | if (!ipw_disassociate(priv)) |
8712 | ipw_associate(priv); | 8727 | ipw_associate(priv); |
8713 | 8728 | ||
8714 | up(&priv->sem); | 8729 | mutex_unlock(&priv->mutex); |
8715 | return 0; | 8730 | return 0; |
8716 | } | 8731 | } |
8717 | 8732 | ||
@@ -8720,9 +8735,9 @@ static int ipw_wx_get_rate(struct net_device *dev, | |||
8720 | union iwreq_data *wrqu, char *extra) | 8735 | union iwreq_data *wrqu, char *extra) |
8721 | { | 8736 | { |
8722 | struct ipw_priv *priv = ieee80211_priv(dev); | 8737 | struct ipw_priv *priv = ieee80211_priv(dev); |
8723 | down(&priv->sem); | 8738 | mutex_lock(&priv->mutex); |
8724 | wrqu->bitrate.value = priv->last_rate; | 8739 | wrqu->bitrate.value = priv->last_rate; |
8725 | up(&priv->sem); | 8740 | mutex_unlock(&priv->mutex); |
8726 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); | 8741 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); |
8727 | return 0; | 8742 | return 0; |
8728 | } | 8743 | } |
@@ -8732,20 +8747,20 @@ static int ipw_wx_set_rts(struct net_device *dev, | |||
8732 | union iwreq_data *wrqu, char *extra) | 8747 | union iwreq_data *wrqu, char *extra) |
8733 | { | 8748 | { |
8734 | struct ipw_priv *priv = ieee80211_priv(dev); | 8749 | struct ipw_priv *priv = ieee80211_priv(dev); |
8735 | down(&priv->sem); | 8750 | mutex_lock(&priv->mutex); |
8736 | if (wrqu->rts.disabled) | 8751 | if (wrqu->rts.disabled) |
8737 | priv->rts_threshold = DEFAULT_RTS_THRESHOLD; | 8752 | priv->rts_threshold = DEFAULT_RTS_THRESHOLD; |
8738 | else { | 8753 | else { |
8739 | if (wrqu->rts.value < MIN_RTS_THRESHOLD || | 8754 | if (wrqu->rts.value < MIN_RTS_THRESHOLD || |
8740 | wrqu->rts.value > MAX_RTS_THRESHOLD) { | 8755 | wrqu->rts.value > MAX_RTS_THRESHOLD) { |
8741 | up(&priv->sem); | 8756 | mutex_unlock(&priv->mutex); |
8742 | return -EINVAL; | 8757 | return -EINVAL; |
8743 | } | 8758 | } |
8744 | priv->rts_threshold = wrqu->rts.value; | 8759 | priv->rts_threshold = wrqu->rts.value; |
8745 | } | 8760 | } |
8746 | 8761 | ||
8747 | ipw_send_rts_threshold(priv, priv->rts_threshold); | 8762 | ipw_send_rts_threshold(priv, priv->rts_threshold); |
8748 | up(&priv->sem); | 8763 | mutex_unlock(&priv->mutex); |
8749 | IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); | 8764 | IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); |
8750 | return 0; | 8765 | return 0; |
8751 | } | 8766 | } |
@@ -8755,11 +8770,11 @@ static int ipw_wx_get_rts(struct net_device *dev, | |||
8755 | union iwreq_data *wrqu, char *extra) | 8770 | union iwreq_data *wrqu, char *extra) |
8756 | { | 8771 | { |
8757 | struct ipw_priv *priv = ieee80211_priv(dev); | 8772 | struct ipw_priv *priv = ieee80211_priv(dev); |
8758 | down(&priv->sem); | 8773 | mutex_lock(&priv->mutex); |
8759 | wrqu->rts.value = priv->rts_threshold; | 8774 | wrqu->rts.value = priv->rts_threshold; |
8760 | wrqu->rts.fixed = 0; /* no auto select */ | 8775 | wrqu->rts.fixed = 0; /* no auto select */ |
8761 | wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); | 8776 | wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); |
8762 | up(&priv->sem); | 8777 | mutex_unlock(&priv->mutex); |
8763 | IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); | 8778 | IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); |
8764 | return 0; | 8779 | return 0; |
8765 | } | 8780 | } |
@@ -8771,7 +8786,7 @@ static int ipw_wx_set_txpow(struct net_device *dev, | |||
8771 | struct ipw_priv *priv = ieee80211_priv(dev); | 8786 | struct ipw_priv *priv = ieee80211_priv(dev); |
8772 | int err = 0; | 8787 | int err = 0; |
8773 | 8788 | ||
8774 | down(&priv->sem); | 8789 | mutex_lock(&priv->mutex); |
8775 | if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { | 8790 | if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { |
8776 | err = -EINPROGRESS; | 8791 | err = -EINPROGRESS; |
8777 | goto out; | 8792 | goto out; |
@@ -8794,7 +8809,7 @@ static int ipw_wx_set_txpow(struct net_device *dev, | |||
8794 | priv->tx_power = wrqu->power.value; | 8809 | priv->tx_power = wrqu->power.value; |
8795 | err = ipw_set_tx_power(priv); | 8810 | err = ipw_set_tx_power(priv); |
8796 | out: | 8811 | out: |
8797 | up(&priv->sem); | 8812 | mutex_unlock(&priv->mutex); |
8798 | return err; | 8813 | return err; |
8799 | } | 8814 | } |
8800 | 8815 | ||
@@ -8803,12 +8818,12 @@ static int ipw_wx_get_txpow(struct net_device *dev, | |||
8803 | union iwreq_data *wrqu, char *extra) | 8818 | union iwreq_data *wrqu, char *extra) |
8804 | { | 8819 | { |
8805 | struct ipw_priv *priv = ieee80211_priv(dev); | 8820 | struct ipw_priv *priv = ieee80211_priv(dev); |
8806 | down(&priv->sem); | 8821 | mutex_lock(&priv->mutex); |
8807 | wrqu->power.value = priv->tx_power; | 8822 | wrqu->power.value = priv->tx_power; |
8808 | wrqu->power.fixed = 1; | 8823 | wrqu->power.fixed = 1; |
8809 | wrqu->power.flags = IW_TXPOW_DBM; | 8824 | wrqu->power.flags = IW_TXPOW_DBM; |
8810 | wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; | 8825 | wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; |
8811 | up(&priv->sem); | 8826 | mutex_unlock(&priv->mutex); |
8812 | 8827 | ||
8813 | IPW_DEBUG_WX("GET TX Power -> %s %d \n", | 8828 | IPW_DEBUG_WX("GET TX Power -> %s %d \n", |
8814 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); | 8829 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); |
@@ -8821,13 +8836,13 @@ static int ipw_wx_set_frag(struct net_device *dev, | |||
8821 | union iwreq_data *wrqu, char *extra) | 8836 | union iwreq_data *wrqu, char *extra) |
8822 | { | 8837 | { |
8823 | struct ipw_priv *priv = ieee80211_priv(dev); | 8838 | struct ipw_priv *priv = ieee80211_priv(dev); |
8824 | down(&priv->sem); | 8839 | mutex_lock(&priv->mutex); |
8825 | if (wrqu->frag.disabled) | 8840 | if (wrqu->frag.disabled) |
8826 | priv->ieee->fts = DEFAULT_FTS; | 8841 | priv->ieee->fts = DEFAULT_FTS; |
8827 | else { | 8842 | else { |
8828 | if (wrqu->frag.value < MIN_FRAG_THRESHOLD || | 8843 | if (wrqu->frag.value < MIN_FRAG_THRESHOLD || |
8829 | wrqu->frag.value > MAX_FRAG_THRESHOLD) { | 8844 | wrqu->frag.value > MAX_FRAG_THRESHOLD) { |
8830 | up(&priv->sem); | 8845 | mutex_unlock(&priv->mutex); |
8831 | return -EINVAL; | 8846 | return -EINVAL; |
8832 | } | 8847 | } |
8833 | 8848 | ||
@@ -8835,7 +8850,7 @@ static int ipw_wx_set_frag(struct net_device *dev, | |||
8835 | } | 8850 | } |
8836 | 8851 | ||
8837 | ipw_send_frag_threshold(priv, wrqu->frag.value); | 8852 | ipw_send_frag_threshold(priv, wrqu->frag.value); |
8838 | up(&priv->sem); | 8853 | mutex_unlock(&priv->mutex); |
8839 | IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); | 8854 | IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); |
8840 | return 0; | 8855 | return 0; |
8841 | } | 8856 | } |
@@ -8845,11 +8860,11 @@ static int ipw_wx_get_frag(struct net_device *dev, | |||
8845 | union iwreq_data *wrqu, char *extra) | 8860 | union iwreq_data *wrqu, char *extra) |
8846 | { | 8861 | { |
8847 | struct ipw_priv *priv = ieee80211_priv(dev); | 8862 | struct ipw_priv *priv = ieee80211_priv(dev); |
8848 | down(&priv->sem); | 8863 | mutex_lock(&priv->mutex); |
8849 | wrqu->frag.value = priv->ieee->fts; | 8864 | wrqu->frag.value = priv->ieee->fts; |
8850 | wrqu->frag.fixed = 0; /* no auto select */ | 8865 | wrqu->frag.fixed = 0; /* no auto select */ |
8851 | wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); | 8866 | wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); |
8852 | up(&priv->sem); | 8867 | mutex_unlock(&priv->mutex); |
8853 | IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); | 8868 | IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); |
8854 | 8869 | ||
8855 | return 0; | 8870 | return 0; |
@@ -8870,7 +8885,7 @@ static int ipw_wx_set_retry(struct net_device *dev, | |||
8870 | if (wrqu->retry.value < 0 || wrqu->retry.value > 255) | 8885 | if (wrqu->retry.value < 0 || wrqu->retry.value > 255) |
8871 | return -EINVAL; | 8886 | return -EINVAL; |
8872 | 8887 | ||
8873 | down(&priv->sem); | 8888 | mutex_lock(&priv->mutex); |
8874 | if (wrqu->retry.flags & IW_RETRY_MIN) | 8889 | if (wrqu->retry.flags & IW_RETRY_MIN) |
8875 | priv->short_retry_limit = (u8) wrqu->retry.value; | 8890 | priv->short_retry_limit = (u8) wrqu->retry.value; |
8876 | else if (wrqu->retry.flags & IW_RETRY_MAX) | 8891 | else if (wrqu->retry.flags & IW_RETRY_MAX) |
@@ -8882,7 +8897,7 @@ static int ipw_wx_set_retry(struct net_device *dev, | |||
8882 | 8897 | ||
8883 | ipw_send_retry_limit(priv, priv->short_retry_limit, | 8898 | ipw_send_retry_limit(priv, priv->short_retry_limit, |
8884 | priv->long_retry_limit); | 8899 | priv->long_retry_limit); |
8885 | up(&priv->sem); | 8900 | mutex_unlock(&priv->mutex); |
8886 | IPW_DEBUG_WX("SET retry limit -> short:%d long:%d\n", | 8901 | IPW_DEBUG_WX("SET retry limit -> short:%d long:%d\n", |
8887 | priv->short_retry_limit, priv->long_retry_limit); | 8902 | priv->short_retry_limit, priv->long_retry_limit); |
8888 | return 0; | 8903 | return 0; |
@@ -8894,11 +8909,11 @@ static int ipw_wx_get_retry(struct net_device *dev, | |||
8894 | { | 8909 | { |
8895 | struct ipw_priv *priv = ieee80211_priv(dev); | 8910 | struct ipw_priv *priv = ieee80211_priv(dev); |
8896 | 8911 | ||
8897 | down(&priv->sem); | 8912 | mutex_lock(&priv->mutex); |
8898 | wrqu->retry.disabled = 0; | 8913 | wrqu->retry.disabled = 0; |
8899 | 8914 | ||
8900 | if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { | 8915 | if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { |
8901 | up(&priv->sem); | 8916 | mutex_unlock(&priv->mutex); |
8902 | return -EINVAL; | 8917 | return -EINVAL; |
8903 | } | 8918 | } |
8904 | 8919 | ||
@@ -8912,7 +8927,7 @@ static int ipw_wx_get_retry(struct net_device *dev, | |||
8912 | wrqu->retry.flags = IW_RETRY_LIMIT; | 8927 | wrqu->retry.flags = IW_RETRY_LIMIT; |
8913 | wrqu->retry.value = priv->short_retry_limit; | 8928 | wrqu->retry.value = priv->short_retry_limit; |
8914 | } | 8929 | } |
8915 | up(&priv->sem); | 8930 | mutex_unlock(&priv->mutex); |
8916 | 8931 | ||
8917 | IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value); | 8932 | IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value); |
8918 | 8933 | ||
@@ -8929,7 +8944,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, | |||
8929 | (priv->status & STATUS_EXIT_PENDING)) | 8944 | (priv->status & STATUS_EXIT_PENDING)) |
8930 | return 0; | 8945 | return 0; |
8931 | 8946 | ||
8932 | down(&priv->sem); | 8947 | mutex_lock(&priv->mutex); |
8933 | 8948 | ||
8934 | if (priv->status & STATUS_RF_KILL_MASK) { | 8949 | if (priv->status & STATUS_RF_KILL_MASK) { |
8935 | IPW_DEBUG_HC("Aborting scan due to RF kill activation\n"); | 8950 | IPW_DEBUG_HC("Aborting scan due to RF kill activation\n"); |
@@ -8981,7 +8996,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, | |||
8981 | priv->status |= STATUS_SCANNING; | 8996 | priv->status |= STATUS_SCANNING; |
8982 | 8997 | ||
8983 | done: | 8998 | done: |
8984 | up(&priv->sem); | 8999 | mutex_unlock(&priv->mutex); |
8985 | return err; | 9000 | return err; |
8986 | } | 9001 | } |
8987 | 9002 | ||
@@ -9024,7 +9039,7 @@ static int ipw_wx_set_encode(struct net_device *dev, | |||
9024 | int ret; | 9039 | int ret; |
9025 | u32 cap = priv->capability; | 9040 | u32 cap = priv->capability; |
9026 | 9041 | ||
9027 | down(&priv->sem); | 9042 | mutex_lock(&priv->mutex); |
9028 | ret = ieee80211_wx_set_encode(priv->ieee, info, wrqu, key); | 9043 | ret = ieee80211_wx_set_encode(priv->ieee, info, wrqu, key); |
9029 | 9044 | ||
9030 | /* In IBSS mode, we need to notify the firmware to update | 9045 | /* In IBSS mode, we need to notify the firmware to update |
@@ -9034,7 +9049,7 @@ static int ipw_wx_set_encode(struct net_device *dev, | |||
9034 | priv->status & STATUS_ASSOCIATED) | 9049 | priv->status & STATUS_ASSOCIATED) |
9035 | ipw_disassociate(priv); | 9050 | ipw_disassociate(priv); |
9036 | 9051 | ||
9037 | up(&priv->sem); | 9052 | mutex_unlock(&priv->mutex); |
9038 | return ret; | 9053 | return ret; |
9039 | } | 9054 | } |
9040 | 9055 | ||
@@ -9052,17 +9067,17 @@ static int ipw_wx_set_power(struct net_device *dev, | |||
9052 | { | 9067 | { |
9053 | struct ipw_priv *priv = ieee80211_priv(dev); | 9068 | struct ipw_priv *priv = ieee80211_priv(dev); |
9054 | int err; | 9069 | int err; |
9055 | down(&priv->sem); | 9070 | mutex_lock(&priv->mutex); |
9056 | if (wrqu->power.disabled) { | 9071 | if (wrqu->power.disabled) { |
9057 | priv->power_mode = IPW_POWER_LEVEL(priv->power_mode); | 9072 | priv->power_mode = IPW_POWER_LEVEL(priv->power_mode); |
9058 | err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM); | 9073 | err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM); |
9059 | if (err) { | 9074 | if (err) { |
9060 | IPW_DEBUG_WX("failed setting power mode.\n"); | 9075 | IPW_DEBUG_WX("failed setting power mode.\n"); |
9061 | up(&priv->sem); | 9076 | mutex_unlock(&priv->mutex); |
9062 | return err; | 9077 | return err; |
9063 | } | 9078 | } |
9064 | IPW_DEBUG_WX("SET Power Management Mode -> off\n"); | 9079 | IPW_DEBUG_WX("SET Power Management Mode -> off\n"); |
9065 | up(&priv->sem); | 9080 | mutex_unlock(&priv->mutex); |
9066 | return 0; | 9081 | return 0; |
9067 | } | 9082 | } |
9068 | 9083 | ||
@@ -9074,7 +9089,7 @@ static int ipw_wx_set_power(struct net_device *dev, | |||
9074 | default: /* Otherwise we don't support it */ | 9089 | default: /* Otherwise we don't support it */ |
9075 | IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", | 9090 | IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", |
9076 | wrqu->power.flags); | 9091 | wrqu->power.flags); |
9077 | up(&priv->sem); | 9092 | mutex_unlock(&priv->mutex); |
9078 | return -EOPNOTSUPP; | 9093 | return -EOPNOTSUPP; |
9079 | } | 9094 | } |
9080 | 9095 | ||
@@ -9087,12 +9102,12 @@ static int ipw_wx_set_power(struct net_device *dev, | |||
9087 | err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); | 9102 | err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); |
9088 | if (err) { | 9103 | if (err) { |
9089 | IPW_DEBUG_WX("failed setting power mode.\n"); | 9104 | IPW_DEBUG_WX("failed setting power mode.\n"); |
9090 | up(&priv->sem); | 9105 | mutex_unlock(&priv->mutex); |
9091 | return err; | 9106 | return err; |
9092 | } | 9107 | } |
9093 | 9108 | ||
9094 | IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); | 9109 | IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); |
9095 | up(&priv->sem); | 9110 | mutex_unlock(&priv->mutex); |
9096 | return 0; | 9111 | return 0; |
9097 | } | 9112 | } |
9098 | 9113 | ||
@@ -9101,13 +9116,13 @@ static int ipw_wx_get_power(struct net_device *dev, | |||
9101 | union iwreq_data *wrqu, char *extra) | 9116 | union iwreq_data *wrqu, char *extra) |
9102 | { | 9117 | { |
9103 | struct ipw_priv *priv = ieee80211_priv(dev); | 9118 | struct ipw_priv *priv = ieee80211_priv(dev); |
9104 | down(&priv->sem); | 9119 | mutex_lock(&priv->mutex); |
9105 | if (!(priv->power_mode & IPW_POWER_ENABLED)) | 9120 | if (!(priv->power_mode & IPW_POWER_ENABLED)) |
9106 | wrqu->power.disabled = 1; | 9121 | wrqu->power.disabled = 1; |
9107 | else | 9122 | else |
9108 | wrqu->power.disabled = 0; | 9123 | wrqu->power.disabled = 0; |
9109 | 9124 | ||
9110 | up(&priv->sem); | 9125 | mutex_unlock(&priv->mutex); |
9111 | IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode); | 9126 | IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode); |
9112 | 9127 | ||
9113 | return 0; | 9128 | return 0; |
@@ -9120,7 +9135,7 @@ static int ipw_wx_set_powermode(struct net_device *dev, | |||
9120 | struct ipw_priv *priv = ieee80211_priv(dev); | 9135 | struct ipw_priv *priv = ieee80211_priv(dev); |
9121 | int mode = *(int *)extra; | 9136 | int mode = *(int *)extra; |
9122 | int err; | 9137 | int err; |
9123 | down(&priv->sem); | 9138 | mutex_lock(&priv->mutex); |
9124 | if ((mode < 1) || (mode > IPW_POWER_LIMIT)) { | 9139 | if ((mode < 1) || (mode > IPW_POWER_LIMIT)) { |
9125 | mode = IPW_POWER_AC; | 9140 | mode = IPW_POWER_AC; |
9126 | priv->power_mode = mode; | 9141 | priv->power_mode = mode; |
@@ -9133,11 +9148,11 @@ static int ipw_wx_set_powermode(struct net_device *dev, | |||
9133 | 9148 | ||
9134 | if (err) { | 9149 | if (err) { |
9135 | IPW_DEBUG_WX("failed setting power mode.\n"); | 9150 | IPW_DEBUG_WX("failed setting power mode.\n"); |
9136 | up(&priv->sem); | 9151 | mutex_unlock(&priv->mutex); |
9137 | return err; | 9152 | return err; |
9138 | } | 9153 | } |
9139 | } | 9154 | } |
9140 | up(&priv->sem); | 9155 | mutex_unlock(&priv->mutex); |
9141 | return 0; | 9156 | return 0; |
9142 | } | 9157 | } |
9143 | 9158 | ||
@@ -9186,7 +9201,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, | |||
9186 | IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode); | 9201 | IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode); |
9187 | return -EINVAL; | 9202 | return -EINVAL; |
9188 | } | 9203 | } |
9189 | down(&priv->sem); | 9204 | mutex_lock(&priv->mutex); |
9190 | if (priv->adapter == IPW_2915ABG) { | 9205 | if (priv->adapter == IPW_2915ABG) { |
9191 | priv->ieee->abg_true = 1; | 9206 | priv->ieee->abg_true = 1; |
9192 | if (mode & IEEE_A) { | 9207 | if (mode & IEEE_A) { |
@@ -9198,7 +9213,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, | |||
9198 | if (mode & IEEE_A) { | 9213 | if (mode & IEEE_A) { |
9199 | IPW_WARNING("Attempt to set 2200BG into " | 9214 | IPW_WARNING("Attempt to set 2200BG into " |
9200 | "802.11a mode\n"); | 9215 | "802.11a mode\n"); |
9201 | up(&priv->sem); | 9216 | mutex_unlock(&priv->mutex); |
9202 | return -EINVAL; | 9217 | return -EINVAL; |
9203 | } | 9218 | } |
9204 | 9219 | ||
@@ -9235,7 +9250,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, | |||
9235 | IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n", | 9250 | IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n", |
9236 | mode & IEEE_A ? 'a' : '.', | 9251 | mode & IEEE_A ? 'a' : '.', |
9237 | mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.'); | 9252 | mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.'); |
9238 | up(&priv->sem); | 9253 | mutex_unlock(&priv->mutex); |
9239 | return 0; | 9254 | return 0; |
9240 | } | 9255 | } |
9241 | 9256 | ||
@@ -9244,7 +9259,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, | |||
9244 | union iwreq_data *wrqu, char *extra) | 9259 | union iwreq_data *wrqu, char *extra) |
9245 | { | 9260 | { |
9246 | struct ipw_priv *priv = ieee80211_priv(dev); | 9261 | struct ipw_priv *priv = ieee80211_priv(dev); |
9247 | down(&priv->sem); | 9262 | mutex_lock(&priv->mutex); |
9248 | switch (priv->ieee->mode) { | 9263 | switch (priv->ieee->mode) { |
9249 | case IEEE_A: | 9264 | case IEEE_A: |
9250 | strncpy(extra, "802.11a (1)", MAX_WX_STRING); | 9265 | strncpy(extra, "802.11a (1)", MAX_WX_STRING); |
@@ -9275,7 +9290,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, | |||
9275 | IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); | 9290 | IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); |
9276 | 9291 | ||
9277 | wrqu->data.length = strlen(extra) + 1; | 9292 | wrqu->data.length = strlen(extra) + 1; |
9278 | up(&priv->sem); | 9293 | mutex_unlock(&priv->mutex); |
9279 | 9294 | ||
9280 | return 0; | 9295 | return 0; |
9281 | } | 9296 | } |
@@ -9286,7 +9301,7 @@ static int ipw_wx_set_preamble(struct net_device *dev, | |||
9286 | { | 9301 | { |
9287 | struct ipw_priv *priv = ieee80211_priv(dev); | 9302 | struct ipw_priv *priv = ieee80211_priv(dev); |
9288 | int mode = *(int *)extra; | 9303 | int mode = *(int *)extra; |
9289 | down(&priv->sem); | 9304 | mutex_lock(&priv->mutex); |
9290 | /* Switching from SHORT -> LONG requires a disassociation */ | 9305 | /* Switching from SHORT -> LONG requires a disassociation */ |
9291 | if (mode == 1) { | 9306 | if (mode == 1) { |
9292 | if (!(priv->config & CFG_PREAMBLE_LONG)) { | 9307 | if (!(priv->config & CFG_PREAMBLE_LONG)) { |
@@ -9305,11 +9320,11 @@ static int ipw_wx_set_preamble(struct net_device *dev, | |||
9305 | priv->config &= ~CFG_PREAMBLE_LONG; | 9320 | priv->config &= ~CFG_PREAMBLE_LONG; |
9306 | goto done; | 9321 | goto done; |
9307 | } | 9322 | } |
9308 | up(&priv->sem); | 9323 | mutex_unlock(&priv->mutex); |
9309 | return -EINVAL; | 9324 | return -EINVAL; |
9310 | 9325 | ||
9311 | done: | 9326 | done: |
9312 | up(&priv->sem); | 9327 | mutex_unlock(&priv->mutex); |
9313 | return 0; | 9328 | return 0; |
9314 | } | 9329 | } |
9315 | 9330 | ||
@@ -9318,12 +9333,12 @@ static int ipw_wx_get_preamble(struct net_device *dev, | |||
9318 | union iwreq_data *wrqu, char *extra) | 9333 | union iwreq_data *wrqu, char *extra) |
9319 | { | 9334 | { |
9320 | struct ipw_priv *priv = ieee80211_priv(dev); | 9335 | struct ipw_priv *priv = ieee80211_priv(dev); |
9321 | down(&priv->sem); | 9336 | mutex_lock(&priv->mutex); |
9322 | if (priv->config & CFG_PREAMBLE_LONG) | 9337 | if (priv->config & CFG_PREAMBLE_LONG) |
9323 | snprintf(wrqu->name, IFNAMSIZ, "long (1)"); | 9338 | snprintf(wrqu->name, IFNAMSIZ, "long (1)"); |
9324 | else | 9339 | else |
9325 | snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); | 9340 | snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); |
9326 | up(&priv->sem); | 9341 | mutex_unlock(&priv->mutex); |
9327 | return 0; | 9342 | return 0; |
9328 | } | 9343 | } |
9329 | 9344 | ||
@@ -9335,7 +9350,7 @@ static int ipw_wx_set_monitor(struct net_device *dev, | |||
9335 | struct ipw_priv *priv = ieee80211_priv(dev); | 9350 | struct ipw_priv *priv = ieee80211_priv(dev); |
9336 | int *parms = (int *)extra; | 9351 | int *parms = (int *)extra; |
9337 | int enable = (parms[0] > 0); | 9352 | int enable = (parms[0] > 0); |
9338 | down(&priv->sem); | 9353 | mutex_lock(&priv->mutex); |
9339 | IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); | 9354 | IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); |
9340 | if (enable) { | 9355 | if (enable) { |
9341 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { | 9356 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { |
@@ -9350,13 +9365,13 @@ static int ipw_wx_set_monitor(struct net_device *dev, | |||
9350 | ipw_set_channel(priv, parms[1]); | 9365 | ipw_set_channel(priv, parms[1]); |
9351 | } else { | 9366 | } else { |
9352 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { | 9367 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { |
9353 | up(&priv->sem); | 9368 | mutex_unlock(&priv->mutex); |
9354 | return 0; | 9369 | return 0; |
9355 | } | 9370 | } |
9356 | priv->net_dev->type = ARPHRD_ETHER; | 9371 | priv->net_dev->type = ARPHRD_ETHER; |
9357 | queue_work(priv->workqueue, &priv->adapter_restart); | 9372 | queue_work(priv->workqueue, &priv->adapter_restart); |
9358 | } | 9373 | } |
9359 | up(&priv->sem); | 9374 | mutex_unlock(&priv->mutex); |
9360 | return 0; | 9375 | return 0; |
9361 | } | 9376 | } |
9362 | 9377 | ||
@@ -9386,9 +9401,9 @@ static int ipw_wx_sw_reset(struct net_device *dev, | |||
9386 | 9401 | ||
9387 | IPW_DEBUG_WX("SW_RESET\n"); | 9402 | IPW_DEBUG_WX("SW_RESET\n"); |
9388 | 9403 | ||
9389 | down(&priv->sem); | 9404 | mutex_lock(&priv->mutex); |
9390 | 9405 | ||
9391 | ret = ipw_sw_reset(priv, 0); | 9406 | ret = ipw_sw_reset(priv, 2); |
9392 | if (!ret) { | 9407 | if (!ret) { |
9393 | free_firmware(); | 9408 | free_firmware(); |
9394 | ipw_adapter_restart(priv); | 9409 | ipw_adapter_restart(priv); |
@@ -9398,9 +9413,9 @@ static int ipw_wx_sw_reset(struct net_device *dev, | |||
9398 | * module parameter, so take appropriate action */ | 9413 | * module parameter, so take appropriate action */ |
9399 | ipw_radio_kill_sw(priv, priv->status & STATUS_RF_KILL_SW); | 9414 | ipw_radio_kill_sw(priv, priv->status & STATUS_RF_KILL_SW); |
9400 | 9415 | ||
9401 | up(&priv->sem); | 9416 | mutex_unlock(&priv->mutex); |
9402 | ieee80211_wx_set_encode(priv->ieee, info, &wrqu_sec, NULL); | 9417 | ieee80211_wx_set_encode(priv->ieee, info, &wrqu_sec, NULL); |
9403 | down(&priv->sem); | 9418 | mutex_lock(&priv->mutex); |
9404 | 9419 | ||
9405 | if (!(priv->status & STATUS_RF_KILL_MASK)) { | 9420 | if (!(priv->status & STATUS_RF_KILL_MASK)) { |
9406 | /* Configuration likely changed -- force [re]association */ | 9421 | /* Configuration likely changed -- force [re]association */ |
@@ -9410,7 +9425,7 @@ static int ipw_wx_sw_reset(struct net_device *dev, | |||
9410 | ipw_associate(priv); | 9425 | ipw_associate(priv); |
9411 | } | 9426 | } |
9412 | 9427 | ||
9413 | up(&priv->sem); | 9428 | mutex_unlock(&priv->mutex); |
9414 | 9429 | ||
9415 | return 0; | 9430 | return 0; |
9416 | } | 9431 | } |
@@ -9423,6 +9438,8 @@ static iw_handler ipw_wx_handlers[] = { | |||
9423 | IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, | 9438 | IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, |
9424 | IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, | 9439 | IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, |
9425 | IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode, | 9440 | IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode, |
9441 | IW_IOCTL(SIOCSIWSENS) = ipw_wx_set_sens, | ||
9442 | IW_IOCTL(SIOCGIWSENS) = ipw_wx_get_sens, | ||
9426 | IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range, | 9443 | IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range, |
9427 | IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap, | 9444 | IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap, |
9428 | IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap, | 9445 | IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap, |
@@ -9568,7 +9585,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) | |||
9568 | wstats->qual.level = average_value(&priv->average_rssi); | 9585 | wstats->qual.level = average_value(&priv->average_rssi); |
9569 | wstats->qual.noise = average_value(&priv->average_noise); | 9586 | wstats->qual.noise = average_value(&priv->average_noise); |
9570 | wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | | 9587 | wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | |
9571 | IW_QUAL_NOISE_UPDATED; | 9588 | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; |
9572 | 9589 | ||
9573 | wstats->miss.beacon = average_value(&priv->average_missed_beacons); | 9590 | wstats->miss.beacon = average_value(&priv->average_missed_beacons); |
9574 | wstats->discard.retries = priv->last_tx_failures; | 9591 | wstats->discard.retries = priv->last_tx_failures; |
@@ -9586,7 +9603,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) | |||
9586 | static void init_sys_config(struct ipw_sys_config *sys_config) | 9603 | static void init_sys_config(struct ipw_sys_config *sys_config) |
9587 | { | 9604 | { |
9588 | memset(sys_config, 0, sizeof(struct ipw_sys_config)); | 9605 | memset(sys_config, 0, sizeof(struct ipw_sys_config)); |
9589 | sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */ | 9606 | sys_config->bt_coexistence = 0; |
9590 | sys_config->answer_broadcast_ssid_probe = 0; | 9607 | sys_config->answer_broadcast_ssid_probe = 0; |
9591 | sys_config->accept_all_data_frames = 0; | 9608 | sys_config->accept_all_data_frames = 0; |
9592 | sys_config->accept_non_directed_frames = 1; | 9609 | sys_config->accept_non_directed_frames = 1; |
@@ -9594,12 +9611,13 @@ static void init_sys_config(struct ipw_sys_config *sys_config) | |||
9594 | sys_config->disable_unicast_decryption = 1; | 9611 | sys_config->disable_unicast_decryption = 1; |
9595 | sys_config->exclude_multicast_unencrypted = 0; | 9612 | sys_config->exclude_multicast_unencrypted = 0; |
9596 | sys_config->disable_multicast_decryption = 1; | 9613 | sys_config->disable_multicast_decryption = 1; |
9597 | sys_config->antenna_diversity = CFG_SYS_ANTENNA_BOTH; | 9614 | sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV; |
9598 | sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ | 9615 | sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ |
9599 | sys_config->dot11g_auto_detection = 0; | 9616 | sys_config->dot11g_auto_detection = 0; |
9600 | sys_config->enable_cts_to_self = 0; | 9617 | sys_config->enable_cts_to_self = 0; |
9601 | sys_config->bt_coexist_collision_thr = 0; | 9618 | sys_config->bt_coexist_collision_thr = 0; |
9602 | sys_config->pass_noise_stats_to_host = 1; //1 -- fix for 256 | 9619 | sys_config->pass_noise_stats_to_host = 1; //1 -- fix for 256 |
9620 | sys_config->silence_threshold = 0x1e; | ||
9603 | } | 9621 | } |
9604 | 9622 | ||
9605 | static int ipw_net_open(struct net_device *dev) | 9623 | static int ipw_net_open(struct net_device *dev) |
@@ -9607,11 +9625,11 @@ static int ipw_net_open(struct net_device *dev) | |||
9607 | struct ipw_priv *priv = ieee80211_priv(dev); | 9625 | struct ipw_priv *priv = ieee80211_priv(dev); |
9608 | IPW_DEBUG_INFO("dev->open\n"); | 9626 | IPW_DEBUG_INFO("dev->open\n"); |
9609 | /* we should be verifying the device is ready to be opened */ | 9627 | /* we should be verifying the device is ready to be opened */ |
9610 | down(&priv->sem); | 9628 | mutex_lock(&priv->mutex); |
9611 | if (!(priv->status & STATUS_RF_KILL_MASK) && | 9629 | if (!(priv->status & STATUS_RF_KILL_MASK) && |
9612 | (priv->status & STATUS_ASSOCIATED)) | 9630 | (priv->status & STATUS_ASSOCIATED)) |
9613 | netif_start_queue(dev); | 9631 | netif_start_queue(dev); |
9614 | up(&priv->sem); | 9632 | mutex_unlock(&priv->mutex); |
9615 | return 0; | 9633 | return 0; |
9616 | } | 9634 | } |
9617 | 9635 | ||
@@ -9647,11 +9665,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
9647 | u16 remaining_bytes; | 9665 | u16 remaining_bytes; |
9648 | int fc; | 9666 | int fc; |
9649 | 9667 | ||
9650 | /* If there isn't room in the queue, we return busy and let the | ||
9651 | * network stack requeue the packet for us */ | ||
9652 | if (ipw_queue_space(q) < q->high_mark) | ||
9653 | return NETDEV_TX_BUSY; | ||
9654 | |||
9655 | switch (priv->ieee->iw_mode) { | 9668 | switch (priv->ieee->iw_mode) { |
9656 | case IW_MODE_ADHOC: | 9669 | case IW_MODE_ADHOC: |
9657 | hdr_len = IEEE80211_3ADDR_LEN; | 9670 | hdr_len = IEEE80211_3ADDR_LEN; |
@@ -9817,6 +9830,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
9817 | q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); | 9830 | q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); |
9818 | ipw_write32(priv, q->reg_w, q->first_empty); | 9831 | ipw_write32(priv, q->reg_w, q->first_empty); |
9819 | 9832 | ||
9833 | if (ipw_queue_space(q) < q->high_mark) | ||
9834 | netif_stop_queue(priv->net_dev); | ||
9835 | |||
9820 | return NETDEV_TX_OK; | 9836 | return NETDEV_TX_OK; |
9821 | 9837 | ||
9822 | drop: | 9838 | drop: |
@@ -9890,13 +9906,13 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p) | |||
9890 | struct sockaddr *addr = p; | 9906 | struct sockaddr *addr = p; |
9891 | if (!is_valid_ether_addr(addr->sa_data)) | 9907 | if (!is_valid_ether_addr(addr->sa_data)) |
9892 | return -EADDRNOTAVAIL; | 9908 | return -EADDRNOTAVAIL; |
9893 | down(&priv->sem); | 9909 | mutex_lock(&priv->mutex); |
9894 | priv->config |= CFG_CUSTOM_MAC; | 9910 | priv->config |= CFG_CUSTOM_MAC; |
9895 | memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); | 9911 | memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); |
9896 | printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n", | 9912 | printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n", |
9897 | priv->net_dev->name, MAC_ARG(priv->mac_addr)); | 9913 | priv->net_dev->name, MAC_ARG(priv->mac_addr)); |
9898 | queue_work(priv->workqueue, &priv->adapter_restart); | 9914 | queue_work(priv->workqueue, &priv->adapter_restart); |
9899 | up(&priv->sem); | 9915 | mutex_unlock(&priv->mutex); |
9900 | return 0; | 9916 | return 0; |
9901 | } | 9917 | } |
9902 | 9918 | ||
@@ -9940,9 +9956,9 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev, | |||
9940 | 9956 | ||
9941 | if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) | 9957 | if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) |
9942 | return -EINVAL; | 9958 | return -EINVAL; |
9943 | down(&p->sem); | 9959 | mutex_lock(&p->mutex); |
9944 | memcpy(bytes, &p->eeprom[eeprom->offset], eeprom->len); | 9960 | memcpy(bytes, &p->eeprom[eeprom->offset], eeprom->len); |
9945 | up(&p->sem); | 9961 | mutex_unlock(&p->mutex); |
9946 | return 0; | 9962 | return 0; |
9947 | } | 9963 | } |
9948 | 9964 | ||
@@ -9954,12 +9970,11 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, | |||
9954 | 9970 | ||
9955 | if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) | 9971 | if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) |
9956 | return -EINVAL; | 9972 | return -EINVAL; |
9957 | down(&p->sem); | 9973 | mutex_lock(&p->mutex); |
9958 | memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len); | 9974 | memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len); |
9959 | for (i = IPW_EEPROM_DATA; | 9975 | for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++) |
9960 | i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++) | 9976 | ipw_write8(p, i + IPW_EEPROM_DATA, p->eeprom[i]); |
9961 | ipw_write8(p, i, p->eeprom[i]); | 9977 | mutex_unlock(&p->mutex); |
9962 | up(&p->sem); | ||
9963 | return 0; | 9978 | return 0; |
9964 | } | 9979 | } |
9965 | 9980 | ||
@@ -10054,12 +10069,12 @@ static void ipw_rf_kill(void *adapter) | |||
10054 | static void ipw_bg_rf_kill(void *data) | 10069 | static void ipw_bg_rf_kill(void *data) |
10055 | { | 10070 | { |
10056 | struct ipw_priv *priv = data; | 10071 | struct ipw_priv *priv = data; |
10057 | down(&priv->sem); | 10072 | mutex_lock(&priv->mutex); |
10058 | ipw_rf_kill(data); | 10073 | ipw_rf_kill(data); |
10059 | up(&priv->sem); | 10074 | mutex_unlock(&priv->mutex); |
10060 | } | 10075 | } |
10061 | 10076 | ||
10062 | void ipw_link_up(struct ipw_priv *priv) | 10077 | static void ipw_link_up(struct ipw_priv *priv) |
10063 | { | 10078 | { |
10064 | priv->last_seq_num = -1; | 10079 | priv->last_seq_num = -1; |
10065 | priv->last_frag_num = -1; | 10080 | priv->last_frag_num = -1; |
@@ -10089,12 +10104,12 @@ void ipw_link_up(struct ipw_priv *priv) | |||
10089 | static void ipw_bg_link_up(void *data) | 10104 | static void ipw_bg_link_up(void *data) |
10090 | { | 10105 | { |
10091 | struct ipw_priv *priv = data; | 10106 | struct ipw_priv *priv = data; |
10092 | down(&priv->sem); | 10107 | mutex_lock(&priv->mutex); |
10093 | ipw_link_up(data); | 10108 | ipw_link_up(data); |
10094 | up(&priv->sem); | 10109 | mutex_unlock(&priv->mutex); |
10095 | } | 10110 | } |
10096 | 10111 | ||
10097 | void ipw_link_down(struct ipw_priv *priv) | 10112 | static void ipw_link_down(struct ipw_priv *priv) |
10098 | { | 10113 | { |
10099 | ipw_led_link_down(priv); | 10114 | ipw_led_link_down(priv); |
10100 | netif_carrier_off(priv->net_dev); | 10115 | netif_carrier_off(priv->net_dev); |
@@ -10117,9 +10132,9 @@ void ipw_link_down(struct ipw_priv *priv) | |||
10117 | static void ipw_bg_link_down(void *data) | 10132 | static void ipw_bg_link_down(void *data) |
10118 | { | 10133 | { |
10119 | struct ipw_priv *priv = data; | 10134 | struct ipw_priv *priv = data; |
10120 | down(&priv->sem); | 10135 | mutex_lock(&priv->mutex); |
10121 | ipw_link_down(data); | 10136 | ipw_link_down(data); |
10122 | up(&priv->sem); | 10137 | mutex_unlock(&priv->mutex); |
10123 | } | 10138 | } |
10124 | 10139 | ||
10125 | static int ipw_setup_deferred_work(struct ipw_priv *priv) | 10140 | static int ipw_setup_deferred_work(struct ipw_priv *priv) |
@@ -10292,6 +10307,20 @@ static int ipw_config(struct ipw_priv *priv) | |||
10292 | 10307 | ||
10293 | /* set basic system config settings */ | 10308 | /* set basic system config settings */ |
10294 | init_sys_config(&priv->sys_config); | 10309 | init_sys_config(&priv->sys_config); |
10310 | |||
10311 | /* Support Bluetooth if we have BT h/w on board, and user wants to. | ||
10312 | * Does not support BT priority yet (don't abort or defer our Tx) */ | ||
10313 | if (bt_coexist) { | ||
10314 | unsigned char bt_caps = priv->eeprom[EEPROM_SKU_CAPABILITY]; | ||
10315 | |||
10316 | if (bt_caps & EEPROM_SKU_CAP_BT_CHANNEL_SIG) | ||
10317 | priv->sys_config.bt_coexistence | ||
10318 | |= CFG_BT_COEXISTENCE_SIGNAL_CHNL; | ||
10319 | if (bt_caps & EEPROM_SKU_CAP_BT_OOB) | ||
10320 | priv->sys_config.bt_coexistence | ||
10321 | |= CFG_BT_COEXISTENCE_OOB; | ||
10322 | } | ||
10323 | |||
10295 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) | 10324 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) |
10296 | priv->sys_config.answer_broadcast_ssid_probe = 1; | 10325 | priv->sys_config.answer_broadcast_ssid_probe = 1; |
10297 | else | 10326 | else |
@@ -10349,6 +10378,9 @@ static int ipw_config(struct ipw_priv *priv) | |||
10349 | * not intended for resale of the above mentioned Intel adapters has | 10378 | * not intended for resale of the above mentioned Intel adapters has |
10350 | * not been tested. | 10379 | * not been tested. |
10351 | * | 10380 | * |
10381 | * Remember to update the table in README.ipw2200 when changing this | ||
10382 | * table. | ||
10383 | * | ||
10352 | */ | 10384 | */ |
10353 | static const struct ieee80211_geo ipw_geos[] = { | 10385 | static const struct ieee80211_geo ipw_geos[] = { |
10354 | { /* Restricted */ | 10386 | { /* Restricted */ |
@@ -10596,96 +10628,6 @@ static const struct ieee80211_geo ipw_geos[] = { | |||
10596 | } | 10628 | } |
10597 | }; | 10629 | }; |
10598 | 10630 | ||
10599 | /* GEO code borrowed from ieee80211_geo.c */ | ||
10600 | static int ipw_is_valid_channel(struct ieee80211_device *ieee, u8 channel) | ||
10601 | { | ||
10602 | int i; | ||
10603 | |||
10604 | /* Driver needs to initialize the geography map before using | ||
10605 | * these helper functions */ | ||
10606 | BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); | ||
10607 | |||
10608 | if (ieee->freq_band & IEEE80211_24GHZ_BAND) | ||
10609 | for (i = 0; i < ieee->geo.bg_channels; i++) | ||
10610 | /* NOTE: If G mode is currently supported but | ||
10611 | * this is a B only channel, we don't see it | ||
10612 | * as valid. */ | ||
10613 | if ((ieee->geo.bg[i].channel == channel) && | ||
10614 | (!(ieee->mode & IEEE_G) || | ||
10615 | !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY))) | ||
10616 | return IEEE80211_24GHZ_BAND; | ||
10617 | |||
10618 | if (ieee->freq_band & IEEE80211_52GHZ_BAND) | ||
10619 | for (i = 0; i < ieee->geo.a_channels; i++) | ||
10620 | if (ieee->geo.a[i].channel == channel) | ||
10621 | return IEEE80211_52GHZ_BAND; | ||
10622 | |||
10623 | return 0; | ||
10624 | } | ||
10625 | |||
10626 | static int ipw_channel_to_index(struct ieee80211_device *ieee, u8 channel) | ||
10627 | { | ||
10628 | int i; | ||
10629 | |||
10630 | /* Driver needs to initialize the geography map before using | ||
10631 | * these helper functions */ | ||
10632 | BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); | ||
10633 | |||
10634 | if (ieee->freq_band & IEEE80211_24GHZ_BAND) | ||
10635 | for (i = 0; i < ieee->geo.bg_channels; i++) | ||
10636 | if (ieee->geo.bg[i].channel == channel) | ||
10637 | return i; | ||
10638 | |||
10639 | if (ieee->freq_band & IEEE80211_52GHZ_BAND) | ||
10640 | for (i = 0; i < ieee->geo.a_channels; i++) | ||
10641 | if (ieee->geo.a[i].channel == channel) | ||
10642 | return i; | ||
10643 | |||
10644 | return -1; | ||
10645 | } | ||
10646 | |||
10647 | static u8 ipw_freq_to_channel(struct ieee80211_device *ieee, u32 freq) | ||
10648 | { | ||
10649 | int i; | ||
10650 | |||
10651 | /* Driver needs to initialize the geography map before using | ||
10652 | * these helper functions */ | ||
10653 | BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); | ||
10654 | |||
10655 | freq /= 100000; | ||
10656 | |||
10657 | if (ieee->freq_band & IEEE80211_24GHZ_BAND) | ||
10658 | for (i = 0; i < ieee->geo.bg_channels; i++) | ||
10659 | if (ieee->geo.bg[i].freq == freq) | ||
10660 | return ieee->geo.bg[i].channel; | ||
10661 | |||
10662 | if (ieee->freq_band & IEEE80211_52GHZ_BAND) | ||
10663 | for (i = 0; i < ieee->geo.a_channels; i++) | ||
10664 | if (ieee->geo.a[i].freq == freq) | ||
10665 | return ieee->geo.a[i].channel; | ||
10666 | |||
10667 | return 0; | ||
10668 | } | ||
10669 | |||
10670 | static int ipw_set_geo(struct ieee80211_device *ieee, | ||
10671 | const struct ieee80211_geo *geo) | ||
10672 | { | ||
10673 | memcpy(ieee->geo.name, geo->name, 3); | ||
10674 | ieee->geo.name[3] = '\0'; | ||
10675 | ieee->geo.bg_channels = geo->bg_channels; | ||
10676 | ieee->geo.a_channels = geo->a_channels; | ||
10677 | memcpy(ieee->geo.bg, geo->bg, geo->bg_channels * | ||
10678 | sizeof(struct ieee80211_channel)); | ||
10679 | memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels * | ||
10680 | sizeof(struct ieee80211_channel)); | ||
10681 | return 0; | ||
10682 | } | ||
10683 | |||
10684 | static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *ieee) | ||
10685 | { | ||
10686 | return &ieee->geo; | ||
10687 | } | ||
10688 | |||
10689 | #define MAX_HW_RESTARTS 5 | 10631 | #define MAX_HW_RESTARTS 5 |
10690 | static int ipw_up(struct ipw_priv *priv) | 10632 | static int ipw_up(struct ipw_priv *priv) |
10691 | { | 10633 | { |
@@ -10732,14 +10674,11 @@ static int ipw_up(struct ipw_priv *priv) | |||
10732 | priv->eeprom[EEPROM_COUNTRY_CODE + 2]); | 10674 | priv->eeprom[EEPROM_COUNTRY_CODE + 2]); |
10733 | j = 0; | 10675 | j = 0; |
10734 | } | 10676 | } |
10735 | if (ipw_set_geo(priv->ieee, &ipw_geos[j])) { | 10677 | if (ieee80211_set_geo(priv->ieee, &ipw_geos[j])) { |
10736 | IPW_WARNING("Could not set geography."); | 10678 | IPW_WARNING("Could not set geography."); |
10737 | return 0; | 10679 | return 0; |
10738 | } | 10680 | } |
10739 | 10681 | ||
10740 | IPW_DEBUG_INFO("Geography %03d [%s] detected.\n", | ||
10741 | j, priv->ieee->geo.name); | ||
10742 | |||
10743 | if (priv->status & STATUS_RF_KILL_SW) { | 10682 | if (priv->status & STATUS_RF_KILL_SW) { |
10744 | IPW_WARNING("Radio disabled by module parameter.\n"); | 10683 | IPW_WARNING("Radio disabled by module parameter.\n"); |
10745 | return 0; | 10684 | return 0; |
@@ -10782,9 +10721,9 @@ static int ipw_up(struct ipw_priv *priv) | |||
10782 | static void ipw_bg_up(void *data) | 10721 | static void ipw_bg_up(void *data) |
10783 | { | 10722 | { |
10784 | struct ipw_priv *priv = data; | 10723 | struct ipw_priv *priv = data; |
10785 | down(&priv->sem); | 10724 | mutex_lock(&priv->mutex); |
10786 | ipw_up(data); | 10725 | ipw_up(data); |
10787 | up(&priv->sem); | 10726 | mutex_unlock(&priv->mutex); |
10788 | } | 10727 | } |
10789 | 10728 | ||
10790 | static void ipw_deinit(struct ipw_priv *priv) | 10729 | static void ipw_deinit(struct ipw_priv *priv) |
@@ -10853,23 +10792,23 @@ static void ipw_down(struct ipw_priv *priv) | |||
10853 | static void ipw_bg_down(void *data) | 10792 | static void ipw_bg_down(void *data) |
10854 | { | 10793 | { |
10855 | struct ipw_priv *priv = data; | 10794 | struct ipw_priv *priv = data; |
10856 | down(&priv->sem); | 10795 | mutex_lock(&priv->mutex); |
10857 | ipw_down(data); | 10796 | ipw_down(data); |
10858 | up(&priv->sem); | 10797 | mutex_unlock(&priv->mutex); |
10859 | } | 10798 | } |
10860 | 10799 | ||
10861 | /* Called by register_netdev() */ | 10800 | /* Called by register_netdev() */ |
10862 | static int ipw_net_init(struct net_device *dev) | 10801 | static int ipw_net_init(struct net_device *dev) |
10863 | { | 10802 | { |
10864 | struct ipw_priv *priv = ieee80211_priv(dev); | 10803 | struct ipw_priv *priv = ieee80211_priv(dev); |
10865 | down(&priv->sem); | 10804 | mutex_lock(&priv->mutex); |
10866 | 10805 | ||
10867 | if (ipw_up(priv)) { | 10806 | if (ipw_up(priv)) { |
10868 | up(&priv->sem); | 10807 | mutex_unlock(&priv->mutex); |
10869 | return -EIO; | 10808 | return -EIO; |
10870 | } | 10809 | } |
10871 | 10810 | ||
10872 | up(&priv->sem); | 10811 | mutex_unlock(&priv->mutex); |
10873 | return 0; | 10812 | return 0; |
10874 | } | 10813 | } |
10875 | 10814 | ||
@@ -10959,7 +10898,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
10959 | for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) | 10898 | for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) |
10960 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); | 10899 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); |
10961 | 10900 | ||
10962 | init_MUTEX(&priv->sem); | 10901 | mutex_init(&priv->mutex); |
10963 | if (pci_enable_device(pdev)) { | 10902 | if (pci_enable_device(pdev)) { |
10964 | err = -ENODEV; | 10903 | err = -ENODEV; |
10965 | goto out_free_ieee80211; | 10904 | goto out_free_ieee80211; |
@@ -11017,7 +10956,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
11017 | SET_MODULE_OWNER(net_dev); | 10956 | SET_MODULE_OWNER(net_dev); |
11018 | SET_NETDEV_DEV(net_dev, &pdev->dev); | 10957 | SET_NETDEV_DEV(net_dev, &pdev->dev); |
11019 | 10958 | ||
11020 | down(&priv->sem); | 10959 | mutex_lock(&priv->mutex); |
11021 | 10960 | ||
11022 | priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; | 10961 | priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; |
11023 | priv->ieee->set_security = shim__set_security; | 10962 | priv->ieee->set_security = shim__set_security; |
@@ -11050,16 +10989,22 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
11050 | err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group); | 10989 | err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group); |
11051 | if (err) { | 10990 | if (err) { |
11052 | IPW_ERROR("failed to create sysfs device attributes\n"); | 10991 | IPW_ERROR("failed to create sysfs device attributes\n"); |
11053 | up(&priv->sem); | 10992 | mutex_unlock(&priv->mutex); |
11054 | goto out_release_irq; | 10993 | goto out_release_irq; |
11055 | } | 10994 | } |
11056 | 10995 | ||
11057 | up(&priv->sem); | 10996 | mutex_unlock(&priv->mutex); |
11058 | err = register_netdev(net_dev); | 10997 | err = register_netdev(net_dev); |
11059 | if (err) { | 10998 | if (err) { |
11060 | IPW_ERROR("failed to register network device\n"); | 10999 | IPW_ERROR("failed to register network device\n"); |
11061 | goto out_remove_sysfs; | 11000 | goto out_remove_sysfs; |
11062 | } | 11001 | } |
11002 | |||
11003 | printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg " | ||
11004 | "channels, %d 802.11a channels)\n", | ||
11005 | priv->ieee->geo.name, priv->ieee->geo.bg_channels, | ||
11006 | priv->ieee->geo.a_channels); | ||
11007 | |||
11063 | return 0; | 11008 | return 0; |
11064 | 11009 | ||
11065 | out_remove_sysfs: | 11010 | out_remove_sysfs: |
@@ -11091,13 +11036,13 @@ static void ipw_pci_remove(struct pci_dev *pdev) | |||
11091 | if (!priv) | 11036 | if (!priv) |
11092 | return; | 11037 | return; |
11093 | 11038 | ||
11094 | down(&priv->sem); | 11039 | mutex_lock(&priv->mutex); |
11095 | 11040 | ||
11096 | priv->status |= STATUS_EXIT_PENDING; | 11041 | priv->status |= STATUS_EXIT_PENDING; |
11097 | ipw_down(priv); | 11042 | ipw_down(priv); |
11098 | sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); | 11043 | sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); |
11099 | 11044 | ||
11100 | up(&priv->sem); | 11045 | mutex_unlock(&priv->mutex); |
11101 | 11046 | ||
11102 | unregister_netdev(priv->net_dev); | 11047 | unregister_netdev(priv->net_dev); |
11103 | 11048 | ||
@@ -11250,8 +11195,10 @@ MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); | |||
11250 | module_param(led, int, 0444); | 11195 | module_param(led, int, 0444); |
11251 | MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n"); | 11196 | MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n"); |
11252 | 11197 | ||
11198 | #ifdef CONFIG_IPW2200_DEBUG | ||
11253 | module_param(debug, int, 0444); | 11199 | module_param(debug, int, 0444); |
11254 | MODULE_PARM_DESC(debug, "debug output mask"); | 11200 | MODULE_PARM_DESC(debug, "debug output mask"); |
11201 | #endif | ||
11255 | 11202 | ||
11256 | module_param(channel, int, 0444); | 11203 | module_param(channel, int, 0444); |
11257 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); | 11204 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); |
@@ -11281,12 +11228,18 @@ module_param(mode, int, 0444); | |||
11281 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); | 11228 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); |
11282 | #endif | 11229 | #endif |
11283 | 11230 | ||
11231 | module_param(bt_coexist, int, 0444); | ||
11232 | MODULE_PARM_DESC(bt_coexist, "enable bluetooth coexistence (default off)"); | ||
11233 | |||
11284 | module_param(hwcrypto, int, 0444); | 11234 | module_param(hwcrypto, int, 0444); |
11285 | MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default on)"); | 11235 | MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default off)"); |
11286 | 11236 | ||
11287 | module_param(cmdlog, int, 0444); | 11237 | module_param(cmdlog, int, 0444); |
11288 | MODULE_PARM_DESC(cmdlog, | 11238 | MODULE_PARM_DESC(cmdlog, |
11289 | "allocate a ring buffer for logging firmware commands"); | 11239 | "allocate a ring buffer for logging firmware commands"); |
11290 | 11240 | ||
11241 | module_param(roaming, int, 0444); | ||
11242 | MODULE_PARM_DESC(roaming, "enable roaming support (default on)"); | ||
11243 | |||
11291 | module_exit(ipw_exit); | 11244 | module_exit(ipw_exit); |
11292 | module_init(ipw_init); | 11245 | module_init(ipw_init); |