diff options
author | James Ketrenos <jketreno@linux.intel.com> | 2005-08-24 23:04:42 -0400 |
---|---|---|
committer | James Ketrenos <jketreno@linux.intel.com> | 2005-11-07 18:49:58 -0500 |
commit | b095c3819805f87d73d41641a53e4c070360d783 (patch) | |
tree | 48edc722c8445078aea620c740d19d466dd8fc25 /drivers/net/wireless/ipw2200.c | |
parent | c848d0af404f00835f038e370005733d90a186fd (diff) |
Catch ipw2200 up to equivelancy with v1.0.4
* Fixed #627 problem with open APs not working with wpa_supplicant
* Fixed #632 problem with 'txpower auto' setting power incorrectly (thanks
to Kai Groner)
* Fixed #634 problem with 'iwconfig eth1 frag 0' hanging the shell
* Fixed problem with adapter not fully powering off during suspend to RAM or
when module unloaded.
* Fixed #645 problem with turning fixed rates off not taking effect until
you reload the driver
* Fixed problem with firmware restart if wpa_supplicant was used to set a key
that wasn't exactly 5 or 13 bytes in length.
* Fixed #623 Added iwpriv sw_reset extension to reset sw parameters
* Added managment frame export to user space with frame statistics
* Fixed #652 Modified the driver to load the EEPROM data even if RF KILL is
active during driver load
* Global s:CX2_:IPW_:g to make code more consistent
* Fixed #572 problem with setting txpower to auto
* Fixed #656 problem with kernel oops if mode auto; modprobe -r ipw2200
* Added QoS (CONFIG_IPW_QOS) support. This is being actively developed but
is the first step in getting WMM support into the driver and the kernel.
* Fixed some race conditions with channel changes, association, and scan
abort that could periodically cause a firmware restart.
* Added some extensions to export scan and network statistics to user space
(exposed through speed_scan and net_stats sysfs entries)
* Fixed a few bugs in how monitor mode was supported (scan lists
weren't quite right)
* Updated the firmware requirement from 2.2 to 2.3 which supports
monitor mode.
Signed-off-by: James Ketrenos <jketreno@linux.intel.com>
Diffstat (limited to 'drivers/net/wireless/ipw2200.c')
-rw-r--r-- | drivers/net/wireless/ipw2200.c | 2420 |
1 files changed, 1782 insertions, 638 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 0bf1931ac5f3..0a583afbcddf 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -32,11 +32,13 @@ | |||
32 | 32 | ||
33 | #include "ipw2200.h" | 33 | #include "ipw2200.h" |
34 | 34 | ||
35 | #define IPW2200_VERSION "1.0.3" | 35 | #define IPW2200_VERSION "1.0.4" |
36 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" | 36 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" |
37 | #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" | 37 | #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" |
38 | #define DRV_VERSION IPW2200_VERSION | 38 | #define DRV_VERSION IPW2200_VERSION |
39 | 39 | ||
40 | #define ETH_P_80211_STATS (ETH_P_80211_RAW + 1) | ||
41 | |||
40 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 42 | MODULE_DESCRIPTION(DRV_DESCRIPTION); |
41 | MODULE_VERSION(DRV_VERSION); | 43 | MODULE_VERSION(DRV_VERSION); |
42 | MODULE_AUTHOR(DRV_COPYRIGHT); | 44 | MODULE_AUTHOR(DRV_COPYRIGHT); |
@@ -51,10 +53,78 @@ static int associate = 1; | |||
51 | static int auto_create = 1; | 53 | static int auto_create = 1; |
52 | static int led = 0; | 54 | static int led = 0; |
53 | static int disable = 0; | 55 | static int disable = 0; |
56 | static int hwcrypto = 1; | ||
54 | static const char ipw_modes[] = { | 57 | static const char ipw_modes[] = { |
55 | 'a', 'b', 'g', '?' | 58 | 'a', 'b', 'g', '?' |
56 | }; | 59 | }; |
57 | 60 | ||
61 | #ifdef CONFIG_IPW_QOS | ||
62 | static int qos_enable = 0; | ||
63 | static int qos_burst_enable = 0; | ||
64 | static int qos_no_ack_mask = 0; | ||
65 | static int burst_duration_CCK = 0; | ||
66 | static int burst_duration_OFDM = 0; | ||
67 | |||
68 | static struct ieee80211_qos_parameters def_qos_parameters_OFDM = { | ||
69 | {QOS_TX0_CW_MIN_OFDM, QOS_TX1_CW_MIN_OFDM, QOS_TX2_CW_MIN_OFDM, | ||
70 | QOS_TX3_CW_MIN_OFDM}, | ||
71 | {QOS_TX0_CW_MAX_OFDM, QOS_TX1_CW_MAX_OFDM, QOS_TX2_CW_MAX_OFDM, | ||
72 | QOS_TX3_CW_MAX_OFDM}, | ||
73 | {QOS_TX0_AIFS, QOS_TX1_AIFS, QOS_TX2_AIFS, QOS_TX3_AIFS}, | ||
74 | {QOS_TX0_ACM, QOS_TX1_ACM, QOS_TX2_ACM, QOS_TX3_ACM}, | ||
75 | {QOS_TX0_TXOP_LIMIT_OFDM, QOS_TX1_TXOP_LIMIT_OFDM, | ||
76 | QOS_TX2_TXOP_LIMIT_OFDM, QOS_TX3_TXOP_LIMIT_OFDM} | ||
77 | }; | ||
78 | |||
79 | static struct ieee80211_qos_parameters def_qos_parameters_CCK = { | ||
80 | {QOS_TX0_CW_MIN_CCK, QOS_TX1_CW_MIN_CCK, QOS_TX2_CW_MIN_CCK, | ||
81 | QOS_TX3_CW_MIN_CCK}, | ||
82 | {QOS_TX0_CW_MAX_CCK, QOS_TX1_CW_MAX_CCK, QOS_TX2_CW_MAX_CCK, | ||
83 | QOS_TX3_CW_MAX_CCK}, | ||
84 | {QOS_TX0_AIFS, QOS_TX1_AIFS, QOS_TX2_AIFS, QOS_TX3_AIFS}, | ||
85 | {QOS_TX0_ACM, QOS_TX1_ACM, QOS_TX2_ACM, QOS_TX3_ACM}, | ||
86 | {QOS_TX0_TXOP_LIMIT_CCK, QOS_TX1_TXOP_LIMIT_CCK, QOS_TX2_TXOP_LIMIT_CCK, | ||
87 | QOS_TX3_TXOP_LIMIT_CCK} | ||
88 | }; | ||
89 | |||
90 | static struct ieee80211_qos_parameters def_parameters_OFDM = { | ||
91 | {DEF_TX0_CW_MIN_OFDM, DEF_TX1_CW_MIN_OFDM, DEF_TX2_CW_MIN_OFDM, | ||
92 | DEF_TX3_CW_MIN_OFDM}, | ||
93 | {DEF_TX0_CW_MAX_OFDM, DEF_TX1_CW_MAX_OFDM, DEF_TX2_CW_MAX_OFDM, | ||
94 | DEF_TX3_CW_MAX_OFDM}, | ||
95 | {DEF_TX0_AIFS, DEF_TX1_AIFS, DEF_TX2_AIFS, DEF_TX3_AIFS}, | ||
96 | {DEF_TX0_ACM, DEF_TX1_ACM, DEF_TX2_ACM, DEF_TX3_ACM}, | ||
97 | {DEF_TX0_TXOP_LIMIT_OFDM, DEF_TX1_TXOP_LIMIT_OFDM, | ||
98 | DEF_TX2_TXOP_LIMIT_OFDM, DEF_TX3_TXOP_LIMIT_OFDM} | ||
99 | }; | ||
100 | |||
101 | static struct ieee80211_qos_parameters def_parameters_CCK = { | ||
102 | {DEF_TX0_CW_MIN_CCK, DEF_TX1_CW_MIN_CCK, DEF_TX2_CW_MIN_CCK, | ||
103 | DEF_TX3_CW_MIN_CCK}, | ||
104 | {DEF_TX0_CW_MAX_CCK, DEF_TX1_CW_MAX_CCK, DEF_TX2_CW_MAX_CCK, | ||
105 | DEF_TX3_CW_MAX_CCK}, | ||
106 | {DEF_TX0_AIFS, DEF_TX1_AIFS, DEF_TX2_AIFS, DEF_TX3_AIFS}, | ||
107 | {DEF_TX0_ACM, DEF_TX1_ACM, DEF_TX2_ACM, DEF_TX3_ACM}, | ||
108 | {DEF_TX0_TXOP_LIMIT_CCK, DEF_TX1_TXOP_LIMIT_CCK, DEF_TX2_TXOP_LIMIT_CCK, | ||
109 | DEF_TX3_TXOP_LIMIT_CCK} | ||
110 | }; | ||
111 | |||
112 | static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; | ||
113 | |||
114 | static int from_priority_to_tx_queue[] = { | ||
115 | IPW_TX_QUEUE_1, IPW_TX_QUEUE_2, IPW_TX_QUEUE_2, IPW_TX_QUEUE_1, | ||
116 | IPW_TX_QUEUE_3, IPW_TX_QUEUE_3, IPW_TX_QUEUE_4, IPW_TX_QUEUE_4 | ||
117 | }; | ||
118 | |||
119 | static u32 ipw_qos_get_burst_duration(struct ipw_priv *priv); | ||
120 | |||
121 | static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters | ||
122 | *qos_param); | ||
123 | static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element | ||
124 | *qos_param); | ||
125 | #endif /* CONFIG_IPW_QOS */ | ||
126 | |||
127 | static void ipw_remove_current_network(struct ipw_priv *priv); | ||
58 | static void ipw_rx(struct ipw_priv *priv); | 128 | static void ipw_rx(struct ipw_priv *priv); |
59 | static int ipw_queue_tx_reclaim(struct ipw_priv *priv, | 129 | static int ipw_queue_tx_reclaim(struct ipw_priv *priv, |
60 | struct clx2_tx_queue *txq, int qindex); | 130 | struct clx2_tx_queue *txq, int qindex); |
@@ -75,33 +145,8 @@ static void ipw_bg_down(void *); | |||
75 | static int ipw_config(struct ipw_priv *); | 145 | static int ipw_config(struct ipw_priv *); |
76 | static int init_supported_rates(struct ipw_priv *priv, | 146 | static int init_supported_rates(struct ipw_priv *priv, |
77 | struct ipw_supported_rates *prates); | 147 | struct ipw_supported_rates *prates); |
78 | 148 | static void ipw_set_hwcrypto_keys(struct ipw_priv *); | |
79 | static u8 band_b_active_channel[MAX_B_CHANNELS] = { | 149 | static void ipw_send_wep_keys(struct ipw_priv *, int); |
80 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 | ||
81 | }; | ||
82 | static u8 band_a_active_channel[MAX_A_CHANNELS] = { | ||
83 | 36, 40, 44, 48, 149, 153, 157, 161, 165, 52, 56, 60, 64, 0 | ||
84 | }; | ||
85 | |||
86 | static int is_valid_channel(int mode_mask, int channel) | ||
87 | { | ||
88 | int i; | ||
89 | |||
90 | if (!channel) | ||
91 | return 0; | ||
92 | |||
93 | if (mode_mask & IEEE_A) | ||
94 | for (i = 0; i < MAX_A_CHANNELS; i++) | ||
95 | if (band_a_active_channel[i] == channel) | ||
96 | return IEEE_A; | ||
97 | |||
98 | if (mode_mask & (IEEE_B | IEEE_G)) | ||
99 | for (i = 0; i < MAX_B_CHANNELS; i++) | ||
100 | if (band_b_active_channel[i] == channel) | ||
101 | return mode_mask & (IEEE_B | IEEE_G); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | 150 | ||
106 | static char *snprint_line(char *buf, size_t count, | 151 | static char *snprint_line(char *buf, size_t count, |
107 | const u8 * data, u32 len, u32 ofs) | 152 | const u8 * data, u32 len, u32 ofs) |
@@ -241,24 +286,24 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data, | |||
241 | static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) | 286 | static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) |
242 | { | 287 | { |
243 | IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value); | 288 | IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value); |
244 | _ipw_write32(priv, CX2_INDIRECT_ADDR, reg); | 289 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); |
245 | _ipw_write32(priv, CX2_INDIRECT_DATA, value); | 290 | _ipw_write32(priv, IPW_INDIRECT_DATA, value); |
246 | } | 291 | } |
247 | 292 | ||
248 | static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) | 293 | static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) |
249 | { | 294 | { |
250 | IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); | 295 | IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); |
251 | _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK); | 296 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); |
252 | _ipw_write8(priv, CX2_INDIRECT_DATA, value); | 297 | _ipw_write8(priv, IPW_INDIRECT_DATA, value); |
253 | IPW_DEBUG_IO(" reg = 0x%8lX : value = 0x%8X\n", | 298 | IPW_DEBUG_IO(" reg = 0x%8lX : value = 0x%8X\n", |
254 | (unsigned long)(priv->hw_base + CX2_INDIRECT_DATA), value); | 299 | (unsigned long)(priv->hw_base + IPW_INDIRECT_DATA), value); |
255 | } | 300 | } |
256 | 301 | ||
257 | static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) | 302 | static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) |
258 | { | 303 | { |
259 | IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); | 304 | IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); |
260 | _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK); | 305 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); |
261 | _ipw_write16(priv, CX2_INDIRECT_DATA, value); | 306 | _ipw_write16(priv, IPW_INDIRECT_DATA, value); |
262 | } | 307 | } |
263 | 308 | ||
264 | /* indirect read s */ | 309 | /* indirect read s */ |
@@ -266,9 +311,9 @@ static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) | |||
266 | static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) | 311 | static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) |
267 | { | 312 | { |
268 | u32 word; | 313 | u32 word; |
269 | _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK); | 314 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); |
270 | IPW_DEBUG_IO(" reg = 0x%8X : \n", reg); | 315 | IPW_DEBUG_IO(" reg = 0x%8X : \n", reg); |
271 | word = _ipw_read32(priv, CX2_INDIRECT_DATA); | 316 | word = _ipw_read32(priv, IPW_INDIRECT_DATA); |
272 | return (word >> ((reg & 0x3) * 8)) & 0xff; | 317 | return (word >> ((reg & 0x3) * 8)) & 0xff; |
273 | } | 318 | } |
274 | 319 | ||
@@ -278,8 +323,8 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) | |||
278 | 323 | ||
279 | IPW_DEBUG_IO("%p : reg = 0x%08x\n", priv, reg); | 324 | IPW_DEBUG_IO("%p : reg = 0x%08x\n", priv, reg); |
280 | 325 | ||
281 | _ipw_write32(priv, CX2_INDIRECT_ADDR, reg); | 326 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); |
282 | value = _ipw_read32(priv, CX2_INDIRECT_DATA); | 327 | value = _ipw_read32(priv, IPW_INDIRECT_DATA); |
283 | IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value); | 328 | IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value); |
284 | return value; | 329 | return value; |
285 | } | 330 | } |
@@ -288,7 +333,7 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) | |||
288 | static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | 333 | static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, |
289 | int num) | 334 | int num) |
290 | { | 335 | { |
291 | u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK; | 336 | u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; |
292 | u32 dif_len = addr - aligned_addr; | 337 | u32 dif_len = addr - aligned_addr; |
293 | u32 i; | 338 | u32 i; |
294 | 339 | ||
@@ -300,29 +345,29 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | |||
300 | 345 | ||
301 | /* Read the first nibble byte by byte */ | 346 | /* Read the first nibble byte by byte */ |
302 | if (unlikely(dif_len)) { | 347 | if (unlikely(dif_len)) { |
303 | _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); | 348 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
304 | /* Start reading at aligned_addr + dif_len */ | 349 | /* Start reading at aligned_addr + dif_len */ |
305 | for (i = dif_len; ((i < 4) && (num > 0)); i++, num--) | 350 | for (i = dif_len; ((i < 4) && (num > 0)); i++, num--) |
306 | *buf++ = _ipw_read8(priv, CX2_INDIRECT_DATA + i); | 351 | *buf++ = _ipw_read8(priv, IPW_INDIRECT_DATA + i); |
307 | aligned_addr += 4; | 352 | aligned_addr += 4; |
308 | } | 353 | } |
309 | 354 | ||
310 | _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr); | 355 | _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); |
311 | for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) | 356 | for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) |
312 | *(u32 *) buf = _ipw_read32(priv, CX2_AUTOINC_DATA); | 357 | *(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA); |
313 | 358 | ||
314 | /* Copy the last nibble */ | 359 | /* Copy the last nibble */ |
315 | if (unlikely(num)) { | 360 | if (unlikely(num)) { |
316 | _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); | 361 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
317 | for (i = 0; num > 0; i++, num--) | 362 | for (i = 0; num > 0; i++, num--) |
318 | *buf++ = ipw_read8(priv, CX2_INDIRECT_DATA + i); | 363 | *buf++ = ipw_read8(priv, IPW_INDIRECT_DATA + i); |
319 | } | 364 | } |
320 | } | 365 | } |
321 | 366 | ||
322 | static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | 367 | static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, |
323 | int num) | 368 | int num) |
324 | { | 369 | { |
325 | u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK; | 370 | u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; |
326 | u32 dif_len = addr - aligned_addr; | 371 | u32 dif_len = addr - aligned_addr; |
327 | u32 i; | 372 | u32 i; |
328 | 373 | ||
@@ -334,22 +379,22 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, | |||
334 | 379 | ||
335 | /* Write the first nibble byte by byte */ | 380 | /* Write the first nibble byte by byte */ |
336 | if (unlikely(dif_len)) { | 381 | if (unlikely(dif_len)) { |
337 | _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); | 382 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
338 | /* Start reading at aligned_addr + dif_len */ | 383 | /* Start reading at aligned_addr + dif_len */ |
339 | for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++) | 384 | for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++) |
340 | _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf); | 385 | _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); |
341 | aligned_addr += 4; | 386 | aligned_addr += 4; |
342 | } | 387 | } |
343 | 388 | ||
344 | _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr); | 389 | _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); |
345 | for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) | 390 | for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) |
346 | _ipw_write32(priv, CX2_AUTOINC_DATA, *(u32 *) buf); | 391 | _ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf); |
347 | 392 | ||
348 | /* Copy the last nibble */ | 393 | /* Copy the last nibble */ |
349 | if (unlikely(num)) { | 394 | if (unlikely(num)) { |
350 | _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); | 395 | _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); |
351 | for (i = 0; num > 0; i++, num--, buf++) | 396 | for (i = 0; num > 0; i++, num--, buf++) |
352 | _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf); | 397 | _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); |
353 | } | 398 | } |
354 | } | 399 | } |
355 | 400 | ||
@@ -374,7 +419,7 @@ static inline void ipw_enable_interrupts(struct ipw_priv *priv) | |||
374 | if (priv->status & STATUS_INT_ENABLED) | 419 | if (priv->status & STATUS_INT_ENABLED) |
375 | return; | 420 | return; |
376 | priv->status |= STATUS_INT_ENABLED; | 421 | priv->status |= STATUS_INT_ENABLED; |
377 | ipw_write32(priv, CX2_INTA_MASK_R, CX2_INTA_MASK_ALL); | 422 | ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL); |
378 | } | 423 | } |
379 | 424 | ||
380 | static inline void ipw_disable_interrupts(struct ipw_priv *priv) | 425 | static inline void ipw_disable_interrupts(struct ipw_priv *priv) |
@@ -382,7 +427,7 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv) | |||
382 | if (!(priv->status & STATUS_INT_ENABLED)) | 427 | if (!(priv->status & STATUS_INT_ENABLED)) |
383 | return; | 428 | return; |
384 | priv->status &= ~STATUS_INT_ENABLED; | 429 | priv->status &= ~STATUS_INT_ENABLED; |
385 | ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL); | 430 | ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); |
386 | } | 431 | } |
387 | 432 | ||
388 | static char *ipw_error_desc(u32 val) | 433 | static char *ipw_error_desc(u32 val) |
@@ -397,29 +442,29 @@ static char *ipw_error_desc(u32 val) | |||
397 | case IPW_FW_ERROR_MEMORY_OVERFLOW: | 442 | case IPW_FW_ERROR_MEMORY_OVERFLOW: |
398 | return "MEMORY_OVERFLOW"; | 443 | return "MEMORY_OVERFLOW"; |
399 | case IPW_FW_ERROR_BAD_PARAM: | 444 | case IPW_FW_ERROR_BAD_PARAM: |
400 | return "ERROR_BAD_PARAM"; | 445 | return "BAD_PARAM"; |
401 | case IPW_FW_ERROR_BAD_CHECKSUM: | 446 | case IPW_FW_ERROR_BAD_CHECKSUM: |
402 | return "ERROR_BAD_CHECKSUM"; | 447 | return "BAD_CHECKSUM"; |
403 | case IPW_FW_ERROR_NMI_INTERRUPT: | 448 | case IPW_FW_ERROR_NMI_INTERRUPT: |
404 | return "ERROR_NMI_INTERRUPT"; | 449 | return "NMI_INTERRUPT"; |
405 | case IPW_FW_ERROR_BAD_DATABASE: | 450 | case IPW_FW_ERROR_BAD_DATABASE: |
406 | return "ERROR_BAD_DATABASE"; | 451 | return "BAD_DATABASE"; |
407 | case IPW_FW_ERROR_ALLOC_FAIL: | 452 | case IPW_FW_ERROR_ALLOC_FAIL: |
408 | return "ERROR_ALLOC_FAIL"; | 453 | return "ALLOC_FAIL"; |
409 | case IPW_FW_ERROR_DMA_UNDERRUN: | 454 | case IPW_FW_ERROR_DMA_UNDERRUN: |
410 | return "ERROR_DMA_UNDERRUN"; | 455 | return "DMA_UNDERRUN"; |
411 | case IPW_FW_ERROR_DMA_STATUS: | 456 | case IPW_FW_ERROR_DMA_STATUS: |
412 | return "ERROR_DMA_STATUS"; | 457 | return "DMA_STATUS"; |
413 | case IPW_FW_ERROR_DINOSTATUS_ERROR: | 458 | case IPW_FW_ERROR_DINO_ERROR: |
414 | return "ERROR_DINOSTATUS_ERROR"; | 459 | return "DINO_ERROR"; |
415 | case IPW_FW_ERROR_EEPROMSTATUS_ERROR: | 460 | case IPW_FW_ERROR_EEPROM_ERROR: |
416 | return "ERROR_EEPROMSTATUS_ERROR"; | 461 | return "EEPROM_ERROR"; |
417 | case IPW_FW_ERROR_SYSASSERT: | 462 | case IPW_FW_ERROR_SYSASSERT: |
418 | return "ERROR_SYSASSERT"; | 463 | return "SYSASSERT"; |
419 | case IPW_FW_ERROR_FATAL_ERROR: | 464 | case IPW_FW_ERROR_FATAL_ERROR: |
420 | return "ERROR_FATALSTATUS_ERROR"; | 465 | return "FATAL_ERROR"; |
421 | default: | 466 | default: |
422 | return "UNKNOWNSTATUS_ERROR"; | 467 | return "UNKNOWN_ERROR"; |
423 | } | 468 | } |
424 | } | 469 | } |
425 | 470 | ||
@@ -646,13 +691,13 @@ static void ipw_init_ordinals(struct ipw_priv *priv) | |||
646 | 691 | ||
647 | u32 ipw_register_toggle(u32 reg) | 692 | u32 ipw_register_toggle(u32 reg) |
648 | { | 693 | { |
649 | reg &= ~CX2_START_STANDBY; | 694 | reg &= ~IPW_START_STANDBY; |
650 | if (reg & CX2_GATE_ODMA) | 695 | if (reg & IPW_GATE_ODMA) |
651 | reg &= ~CX2_GATE_ODMA; | 696 | reg &= ~IPW_GATE_ODMA; |
652 | if (reg & CX2_GATE_IDMA) | 697 | if (reg & IPW_GATE_IDMA) |
653 | reg &= ~CX2_GATE_IDMA; | 698 | reg &= ~IPW_GATE_IDMA; |
654 | if (reg & CX2_GATE_ADMA) | 699 | if (reg & IPW_GATE_ADMA) |
655 | reg &= ~CX2_GATE_ADMA; | 700 | reg &= ~IPW_GATE_ADMA; |
656 | return reg; | 701 | return reg; |
657 | } | 702 | } |
658 | 703 | ||
@@ -684,13 +729,13 @@ void ipw_led_link_on(struct ipw_priv *priv) | |||
684 | if (!(priv->status & STATUS_RF_KILL_MASK) && | 729 | if (!(priv->status & STATUS_RF_KILL_MASK) && |
685 | !(priv->status & STATUS_LED_LINK_ON)) { | 730 | !(priv->status & STATUS_LED_LINK_ON)) { |
686 | IPW_DEBUG_LED("Link LED On\n"); | 731 | IPW_DEBUG_LED("Link LED On\n"); |
687 | led = ipw_read_reg32(priv, CX2_EVENT_REG); | 732 | led = ipw_read_reg32(priv, IPW_EVENT_REG); |
688 | led |= priv->led_association_on; | 733 | led |= priv->led_association_on; |
689 | 734 | ||
690 | led = ipw_register_toggle(led); | 735 | led = ipw_register_toggle(led); |
691 | 736 | ||
692 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); | 737 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); |
693 | ipw_write_reg32(priv, CX2_EVENT_REG, led); | 738 | ipw_write_reg32(priv, IPW_EVENT_REG, led); |
694 | 739 | ||
695 | priv->status |= STATUS_LED_LINK_ON; | 740 | priv->status |= STATUS_LED_LINK_ON; |
696 | 741 | ||
@@ -725,12 +770,12 @@ void ipw_led_link_off(struct ipw_priv *priv) | |||
725 | spin_lock_irqsave(&priv->lock, flags); | 770 | spin_lock_irqsave(&priv->lock, flags); |
726 | 771 | ||
727 | if (priv->status & STATUS_LED_LINK_ON) { | 772 | if (priv->status & STATUS_LED_LINK_ON) { |
728 | led = ipw_read_reg32(priv, CX2_EVENT_REG); | 773 | led = ipw_read_reg32(priv, IPW_EVENT_REG); |
729 | led &= priv->led_association_off; | 774 | led &= priv->led_association_off; |
730 | led = ipw_register_toggle(led); | 775 | led = ipw_register_toggle(led); |
731 | 776 | ||
732 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); | 777 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); |
733 | ipw_write_reg32(priv, CX2_EVENT_REG, led); | 778 | ipw_write_reg32(priv, IPW_EVENT_REG, led); |
734 | 779 | ||
735 | IPW_DEBUG_LED("Link LED Off\n"); | 780 | IPW_DEBUG_LED("Link LED Off\n"); |
736 | 781 | ||
@@ -756,29 +801,24 @@ static void ipw_bg_led_link_off(void *data) | |||
756 | up(&priv->sem); | 801 | up(&priv->sem); |
757 | } | 802 | } |
758 | 803 | ||
759 | void ipw_led_activity_on(struct ipw_priv *priv) | 804 | static inline void __ipw_led_activity_on(struct ipw_priv *priv) |
760 | { | 805 | { |
761 | unsigned long flags; | ||
762 | u32 led; | 806 | u32 led; |
763 | 807 | ||
764 | if (priv->config & CFG_NO_LED) | 808 | if (priv->config & CFG_NO_LED) |
765 | return; | 809 | return; |
766 | 810 | ||
767 | spin_lock_irqsave(&priv->lock, flags); | 811 | if (priv->status & STATUS_RF_KILL_MASK) |
768 | |||
769 | if (priv->status & STATUS_RF_KILL_MASK) { | ||
770 | spin_unlock_irqrestore(&priv->lock, flags); | ||
771 | return; | 812 | return; |
772 | } | ||
773 | 813 | ||
774 | if (!(priv->status & STATUS_LED_ACT_ON)) { | 814 | if (!(priv->status & STATUS_LED_ACT_ON)) { |
775 | led = ipw_read_reg32(priv, CX2_EVENT_REG); | 815 | led = ipw_read_reg32(priv, IPW_EVENT_REG); |
776 | led |= priv->led_activity_on; | 816 | led |= priv->led_activity_on; |
777 | 817 | ||
778 | led = ipw_register_toggle(led); | 818 | led = ipw_register_toggle(led); |
779 | 819 | ||
780 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); | 820 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); |
781 | ipw_write_reg32(priv, CX2_EVENT_REG, led); | 821 | ipw_write_reg32(priv, IPW_EVENT_REG, led); |
782 | 822 | ||
783 | IPW_DEBUG_LED("Activity LED On\n"); | 823 | IPW_DEBUG_LED("Activity LED On\n"); |
784 | 824 | ||
@@ -793,7 +833,13 @@ void ipw_led_activity_on(struct ipw_priv *priv) | |||
793 | queue_delayed_work(priv->workqueue, &priv->led_act_off, | 833 | queue_delayed_work(priv->workqueue, &priv->led_act_off, |
794 | LD_TIME_ACT_ON); | 834 | LD_TIME_ACT_ON); |
795 | } | 835 | } |
836 | } | ||
796 | 837 | ||
838 | void ipw_led_activity_on(struct ipw_priv *priv) | ||
839 | { | ||
840 | unsigned long flags; | ||
841 | spin_lock_irqsave(&priv->lock, flags); | ||
842 | __ipw_led_activity_on(priv); | ||
797 | spin_unlock_irqrestore(&priv->lock, flags); | 843 | spin_unlock_irqrestore(&priv->lock, flags); |
798 | } | 844 | } |
799 | 845 | ||
@@ -808,13 +854,13 @@ void ipw_led_activity_off(struct ipw_priv *priv) | |||
808 | spin_lock_irqsave(&priv->lock, flags); | 854 | spin_lock_irqsave(&priv->lock, flags); |
809 | 855 | ||
810 | if (priv->status & STATUS_LED_ACT_ON) { | 856 | if (priv->status & STATUS_LED_ACT_ON) { |
811 | led = ipw_read_reg32(priv, CX2_EVENT_REG); | 857 | led = ipw_read_reg32(priv, IPW_EVENT_REG); |
812 | led &= priv->led_activity_off; | 858 | led &= priv->led_activity_off; |
813 | 859 | ||
814 | led = ipw_register_toggle(led); | 860 | led = ipw_register_toggle(led); |
815 | 861 | ||
816 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); | 862 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); |
817 | ipw_write_reg32(priv, CX2_EVENT_REG, led); | 863 | ipw_write_reg32(priv, IPW_EVENT_REG, led); |
818 | 864 | ||
819 | IPW_DEBUG_LED("Activity LED Off\n"); | 865 | IPW_DEBUG_LED("Activity LED Off\n"); |
820 | 866 | ||
@@ -844,7 +890,7 @@ void ipw_led_band_on(struct ipw_priv *priv) | |||
844 | 890 | ||
845 | spin_lock_irqsave(&priv->lock, flags); | 891 | spin_lock_irqsave(&priv->lock, flags); |
846 | 892 | ||
847 | led = ipw_read_reg32(priv, CX2_EVENT_REG); | 893 | led = ipw_read_reg32(priv, IPW_EVENT_REG); |
848 | if (priv->assoc_network->mode == IEEE_A) { | 894 | if (priv->assoc_network->mode == IEEE_A) { |
849 | led |= priv->led_ofdm_on; | 895 | led |= priv->led_ofdm_on; |
850 | led &= priv->led_association_off; | 896 | led &= priv->led_association_off; |
@@ -862,7 +908,7 @@ void ipw_led_band_on(struct ipw_priv *priv) | |||
862 | led = ipw_register_toggle(led); | 908 | led = ipw_register_toggle(led); |
863 | 909 | ||
864 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); | 910 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); |
865 | ipw_write_reg32(priv, CX2_EVENT_REG, led); | 911 | ipw_write_reg32(priv, IPW_EVENT_REG, led); |
866 | 912 | ||
867 | spin_unlock_irqrestore(&priv->lock, flags); | 913 | spin_unlock_irqrestore(&priv->lock, flags); |
868 | } | 914 | } |
@@ -878,14 +924,14 @@ void ipw_led_band_off(struct ipw_priv *priv) | |||
878 | 924 | ||
879 | spin_lock_irqsave(&priv->lock, flags); | 925 | spin_lock_irqsave(&priv->lock, flags); |
880 | 926 | ||
881 | led = ipw_read_reg32(priv, CX2_EVENT_REG); | 927 | led = ipw_read_reg32(priv, IPW_EVENT_REG); |
882 | led &= priv->led_ofdm_off; | 928 | led &= priv->led_ofdm_off; |
883 | led &= priv->led_association_off; | 929 | led &= priv->led_association_off; |
884 | 930 | ||
885 | led = ipw_register_toggle(led); | 931 | led = ipw_register_toggle(led); |
886 | 932 | ||
887 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); | 933 | IPW_DEBUG_LED("Reg: 0x%08X\n", led); |
888 | ipw_write_reg32(priv, CX2_EVENT_REG, led); | 934 | ipw_write_reg32(priv, IPW_EVENT_REG, led); |
889 | 935 | ||
890 | spin_unlock_irqrestore(&priv->lock, flags); | 936 | spin_unlock_irqrestore(&priv->lock, flags); |
891 | } | 937 | } |
@@ -921,23 +967,23 @@ void ipw_led_init(struct ipw_priv *priv) | |||
921 | priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE]; | 967 | priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE]; |
922 | 968 | ||
923 | /* Set the default PINs for the link and activity leds */ | 969 | /* Set the default PINs for the link and activity leds */ |
924 | priv->led_activity_on = CX2_ACTIVITY_LED; | 970 | priv->led_activity_on = IPW_ACTIVITY_LED; |
925 | priv->led_activity_off = ~(CX2_ACTIVITY_LED); | 971 | priv->led_activity_off = ~(IPW_ACTIVITY_LED); |
926 | 972 | ||
927 | priv->led_association_on = CX2_ASSOCIATED_LED; | 973 | priv->led_association_on = IPW_ASSOCIATED_LED; |
928 | priv->led_association_off = ~(CX2_ASSOCIATED_LED); | 974 | priv->led_association_off = ~(IPW_ASSOCIATED_LED); |
929 | 975 | ||
930 | /* Set the default PINs for the OFDM leds */ | 976 | /* Set the default PINs for the OFDM leds */ |
931 | priv->led_ofdm_on = CX2_OFDM_LED; | 977 | priv->led_ofdm_on = IPW_OFDM_LED; |
932 | priv->led_ofdm_off = ~(CX2_OFDM_LED); | 978 | priv->led_ofdm_off = ~(IPW_OFDM_LED); |
933 | 979 | ||
934 | switch (priv->nic_type) { | 980 | switch (priv->nic_type) { |
935 | case EEPROM_NIC_TYPE_1: | 981 | case EEPROM_NIC_TYPE_1: |
936 | /* In this NIC type, the LEDs are reversed.... */ | 982 | /* In this NIC type, the LEDs are reversed.... */ |
937 | priv->led_activity_on = CX2_ASSOCIATED_LED; | 983 | priv->led_activity_on = IPW_ASSOCIATED_LED; |
938 | priv->led_activity_off = ~(CX2_ASSOCIATED_LED); | 984 | priv->led_activity_off = ~(IPW_ASSOCIATED_LED); |
939 | priv->led_association_on = CX2_ACTIVITY_LED; | 985 | priv->led_association_on = IPW_ACTIVITY_LED; |
940 | priv->led_association_off = ~(CX2_ACTIVITY_LED); | 986 | priv->led_association_off = ~(IPW_ACTIVITY_LED); |
941 | 987 | ||
942 | if (!(priv->config & CFG_NO_LED)) | 988 | if (!(priv->config & CFG_NO_LED)) |
943 | ipw_led_band_on(priv); | 989 | ipw_led_band_on(priv); |
@@ -1203,7 +1249,7 @@ static ssize_t show_command_event_reg(struct device *d, | |||
1203 | u32 reg = 0; | 1249 | u32 reg = 0; |
1204 | struct ipw_priv *p = d->driver_data; | 1250 | struct ipw_priv *p = d->driver_data; |
1205 | 1251 | ||
1206 | reg = ipw_read_reg32(p, CX2_INTERNAL_CMD_EVENT); | 1252 | reg = ipw_read_reg32(p, IPW_INTERNAL_CMD_EVENT); |
1207 | return sprintf(buf, "0x%08x\n", reg); | 1253 | return sprintf(buf, "0x%08x\n", reg); |
1208 | } | 1254 | } |
1209 | static ssize_t store_command_event_reg(struct device *d, | 1255 | static ssize_t store_command_event_reg(struct device *d, |
@@ -1214,7 +1260,7 @@ static ssize_t store_command_event_reg(struct device *d, | |||
1214 | struct ipw_priv *p = d->driver_data; | 1260 | struct ipw_priv *p = d->driver_data; |
1215 | 1261 | ||
1216 | sscanf(buf, "%x", ®); | 1262 | sscanf(buf, "%x", ®); |
1217 | ipw_write_reg32(p, CX2_INTERNAL_CMD_EVENT, reg); | 1263 | ipw_write_reg32(p, IPW_INTERNAL_CMD_EVENT, reg); |
1218 | return strnlen(buf, count); | 1264 | return strnlen(buf, count); |
1219 | } | 1265 | } |
1220 | 1266 | ||
@@ -1361,7 +1407,6 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) | |||
1361 | 1407 | ||
1362 | if (priv->workqueue) | 1408 | if (priv->workqueue) |
1363 | cancel_delayed_work(&priv->request_scan); | 1409 | cancel_delayed_work(&priv->request_scan); |
1364 | wake_up_interruptible(&priv->wait_command_queue); | ||
1365 | queue_work(priv->workqueue, &priv->down); | 1410 | queue_work(priv->workqueue, &priv->down); |
1366 | } else { | 1411 | } else { |
1367 | priv->status &= ~STATUS_RF_KILL_SW; | 1412 | priv->status &= ~STATUS_RF_KILL_SW; |
@@ -1391,6 +1436,82 @@ static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, | |||
1391 | 1436 | ||
1392 | static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); | 1437 | static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); |
1393 | 1438 | ||
1439 | static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr, | ||
1440 | char *buf) | ||
1441 | { | ||
1442 | struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; | ||
1443 | int pos = 0, len = 0; | ||
1444 | if (priv->config & CFG_SPEED_SCAN) { | ||
1445 | while (priv->speed_scan[pos] != 0) | ||
1446 | len += sprintf(&buf[len], "%d ", | ||
1447 | priv->speed_scan[pos++]); | ||
1448 | return len + sprintf(&buf[len], "\n"); | ||
1449 | } | ||
1450 | |||
1451 | return sprintf(buf, "0\n"); | ||
1452 | } | ||
1453 | |||
1454 | static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr, | ||
1455 | const char *buf, size_t count) | ||
1456 | { | ||
1457 | struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; | ||
1458 | int channel, pos = 0; | ||
1459 | const char *p = buf; | ||
1460 | |||
1461 | /* list of space separated channels to scan, optionally ending with 0 */ | ||
1462 | while ((channel = simple_strtol(p, NULL, 0))) { | ||
1463 | if (pos == MAX_SPEED_SCAN - 1) { | ||
1464 | priv->speed_scan[pos] = 0; | ||
1465 | break; | ||
1466 | } | ||
1467 | |||
1468 | if (ieee80211_is_valid_channel(priv->ieee, channel)) | ||
1469 | priv->speed_scan[pos++] = channel; | ||
1470 | else | ||
1471 | IPW_WARNING("Skipping invalid channel request: %d\n", | ||
1472 | channel); | ||
1473 | p = strchr(p, ' '); | ||
1474 | if (!p) | ||
1475 | break; | ||
1476 | while (*p == ' ' || *p == '\t') | ||
1477 | p++; | ||
1478 | } | ||
1479 | |||
1480 | if (pos == 0) | ||
1481 | priv->config &= ~CFG_SPEED_SCAN; | ||
1482 | else { | ||
1483 | priv->speed_scan_pos = 0; | ||
1484 | priv->config |= CFG_SPEED_SCAN; | ||
1485 | } | ||
1486 | |||
1487 | return count; | ||
1488 | } | ||
1489 | |||
1490 | static DEVICE_ATTR(speed_scan, S_IWUSR | S_IRUGO, show_speed_scan, | ||
1491 | store_speed_scan); | ||
1492 | |||
1493 | static ssize_t show_net_stats(struct device *d, struct device_attribute *attr, | ||
1494 | char *buf) | ||
1495 | { | ||
1496 | struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; | ||
1497 | return sprintf(buf, "%c\n", (priv->config & CFG_NET_STATS) ? '1' : '0'); | ||
1498 | } | ||
1499 | |||
1500 | static ssize_t store_net_stats(struct device *d, struct device_attribute *attr, | ||
1501 | const char *buf, size_t count) | ||
1502 | { | ||
1503 | struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; | ||
1504 | if (buf[0] == '1') | ||
1505 | priv->config |= CFG_NET_STATS; | ||
1506 | else | ||
1507 | priv->config &= ~CFG_NET_STATS; | ||
1508 | |||
1509 | return count; | ||
1510 | } | ||
1511 | |||
1512 | static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO, show_net_stats, | ||
1513 | store_net_stats); | ||
1514 | |||
1394 | static void notify_wx_assoc_event(struct ipw_priv *priv) | 1515 | static void notify_wx_assoc_event(struct ipw_priv *priv) |
1395 | { | 1516 | { |
1396 | union iwreq_data wrqu; | 1517 | union iwreq_data wrqu; |
@@ -1410,77 +1531,77 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1410 | 1531 | ||
1411 | spin_lock_irqsave(&priv->lock, flags); | 1532 | spin_lock_irqsave(&priv->lock, flags); |
1412 | 1533 | ||
1413 | inta = ipw_read32(priv, CX2_INTA_RW); | 1534 | inta = ipw_read32(priv, IPW_INTA_RW); |
1414 | inta_mask = ipw_read32(priv, CX2_INTA_MASK_R); | 1535 | inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); |
1415 | inta &= (CX2_INTA_MASK_ALL & inta_mask); | 1536 | inta &= (IPW_INTA_MASK_ALL & inta_mask); |
1416 | 1537 | ||
1417 | /* Add any cached INTA values that need to be handled */ | 1538 | /* Add any cached INTA values that need to be handled */ |
1418 | inta |= priv->isr_inta; | 1539 | inta |= priv->isr_inta; |
1419 | 1540 | ||
1420 | /* handle all the justifications for the interrupt */ | 1541 | /* handle all the justifications for the interrupt */ |
1421 | if (inta & CX2_INTA_BIT_RX_TRANSFER) { | 1542 | if (inta & IPW_INTA_BIT_RX_TRANSFER) { |
1422 | ipw_rx(priv); | 1543 | ipw_rx(priv); |
1423 | handled |= CX2_INTA_BIT_RX_TRANSFER; | 1544 | handled |= IPW_INTA_BIT_RX_TRANSFER; |
1424 | } | 1545 | } |
1425 | 1546 | ||
1426 | if (inta & CX2_INTA_BIT_TX_CMD_QUEUE) { | 1547 | if (inta & IPW_INTA_BIT_TX_CMD_QUEUE) { |
1427 | IPW_DEBUG_HC("Command completed.\n"); | 1548 | IPW_DEBUG_HC("Command completed.\n"); |
1428 | rc = ipw_queue_tx_reclaim(priv, &priv->txq_cmd, -1); | 1549 | rc = ipw_queue_tx_reclaim(priv, &priv->txq_cmd, -1); |
1429 | priv->status &= ~STATUS_HCMD_ACTIVE; | 1550 | priv->status &= ~STATUS_HCMD_ACTIVE; |
1430 | wake_up_interruptible(&priv->wait_command_queue); | 1551 | wake_up_interruptible(&priv->wait_command_queue); |
1431 | handled |= CX2_INTA_BIT_TX_CMD_QUEUE; | 1552 | handled |= IPW_INTA_BIT_TX_CMD_QUEUE; |
1432 | } | 1553 | } |
1433 | 1554 | ||
1434 | if (inta & CX2_INTA_BIT_TX_QUEUE_1) { | 1555 | if (inta & IPW_INTA_BIT_TX_QUEUE_1) { |
1435 | IPW_DEBUG_TX("TX_QUEUE_1\n"); | 1556 | IPW_DEBUG_TX("TX_QUEUE_1\n"); |
1436 | rc = ipw_queue_tx_reclaim(priv, &priv->txq[0], 0); | 1557 | rc = ipw_queue_tx_reclaim(priv, &priv->txq[0], 0); |
1437 | handled |= CX2_INTA_BIT_TX_QUEUE_1; | 1558 | handled |= IPW_INTA_BIT_TX_QUEUE_1; |
1438 | } | 1559 | } |
1439 | 1560 | ||
1440 | if (inta & CX2_INTA_BIT_TX_QUEUE_2) { | 1561 | if (inta & IPW_INTA_BIT_TX_QUEUE_2) { |
1441 | IPW_DEBUG_TX("TX_QUEUE_2\n"); | 1562 | IPW_DEBUG_TX("TX_QUEUE_2\n"); |
1442 | rc = ipw_queue_tx_reclaim(priv, &priv->txq[1], 1); | 1563 | rc = ipw_queue_tx_reclaim(priv, &priv->txq[1], 1); |
1443 | handled |= CX2_INTA_BIT_TX_QUEUE_2; | 1564 | handled |= IPW_INTA_BIT_TX_QUEUE_2; |
1444 | } | 1565 | } |
1445 | 1566 | ||
1446 | if (inta & CX2_INTA_BIT_TX_QUEUE_3) { | 1567 | if (inta & IPW_INTA_BIT_TX_QUEUE_3) { |
1447 | IPW_DEBUG_TX("TX_QUEUE_3\n"); | 1568 | IPW_DEBUG_TX("TX_QUEUE_3\n"); |
1448 | rc = ipw_queue_tx_reclaim(priv, &priv->txq[2], 2); | 1569 | rc = ipw_queue_tx_reclaim(priv, &priv->txq[2], 2); |
1449 | handled |= CX2_INTA_BIT_TX_QUEUE_3; | 1570 | handled |= IPW_INTA_BIT_TX_QUEUE_3; |
1450 | } | 1571 | } |
1451 | 1572 | ||
1452 | if (inta & CX2_INTA_BIT_TX_QUEUE_4) { | 1573 | if (inta & IPW_INTA_BIT_TX_QUEUE_4) { |
1453 | IPW_DEBUG_TX("TX_QUEUE_4\n"); | 1574 | IPW_DEBUG_TX("TX_QUEUE_4\n"); |
1454 | rc = ipw_queue_tx_reclaim(priv, &priv->txq[3], 3); | 1575 | rc = ipw_queue_tx_reclaim(priv, &priv->txq[3], 3); |
1455 | handled |= CX2_INTA_BIT_TX_QUEUE_4; | 1576 | handled |= IPW_INTA_BIT_TX_QUEUE_4; |
1456 | } | 1577 | } |
1457 | 1578 | ||
1458 | if (inta & CX2_INTA_BIT_STATUS_CHANGE) { | 1579 | if (inta & IPW_INTA_BIT_STATUS_CHANGE) { |
1459 | IPW_WARNING("STATUS_CHANGE\n"); | 1580 | IPW_WARNING("STATUS_CHANGE\n"); |
1460 | handled |= CX2_INTA_BIT_STATUS_CHANGE; | 1581 | handled |= IPW_INTA_BIT_STATUS_CHANGE; |
1461 | } | 1582 | } |
1462 | 1583 | ||
1463 | if (inta & CX2_INTA_BIT_BEACON_PERIOD_EXPIRED) { | 1584 | if (inta & IPW_INTA_BIT_BEACON_PERIOD_EXPIRED) { |
1464 | IPW_WARNING("TX_PERIOD_EXPIRED\n"); | 1585 | IPW_WARNING("TX_PERIOD_EXPIRED\n"); |
1465 | handled |= CX2_INTA_BIT_BEACON_PERIOD_EXPIRED; | 1586 | handled |= IPW_INTA_BIT_BEACON_PERIOD_EXPIRED; |
1466 | } | 1587 | } |
1467 | 1588 | ||
1468 | if (inta & CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE) { | 1589 | if (inta & IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE) { |
1469 | IPW_WARNING("HOST_CMD_DONE\n"); | 1590 | IPW_WARNING("HOST_CMD_DONE\n"); |
1470 | handled |= CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE; | 1591 | handled |= IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE; |
1471 | } | 1592 | } |
1472 | 1593 | ||
1473 | if (inta & CX2_INTA_BIT_FW_INITIALIZATION_DONE) { | 1594 | if (inta & IPW_INTA_BIT_FW_INITIALIZATION_DONE) { |
1474 | IPW_WARNING("FW_INITIALIZATION_DONE\n"); | 1595 | IPW_WARNING("FW_INITIALIZATION_DONE\n"); |
1475 | handled |= CX2_INTA_BIT_FW_INITIALIZATION_DONE; | 1596 | handled |= IPW_INTA_BIT_FW_INITIALIZATION_DONE; |
1476 | } | 1597 | } |
1477 | 1598 | ||
1478 | if (inta & CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE) { | 1599 | if (inta & IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE) { |
1479 | IPW_WARNING("PHY_OFF_DONE\n"); | 1600 | IPW_WARNING("PHY_OFF_DONE\n"); |
1480 | handled |= CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE; | 1601 | handled |= IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE; |
1481 | } | 1602 | } |
1482 | 1603 | ||
1483 | if (inta & CX2_INTA_BIT_RF_KILL_DONE) { | 1604 | if (inta & IPW_INTA_BIT_RF_KILL_DONE) { |
1484 | IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); | 1605 | IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); |
1485 | priv->status |= STATUS_RF_KILL_HW; | 1606 | priv->status |= STATUS_RF_KILL_HW; |
1486 | wake_up_interruptible(&priv->wait_command_queue); | 1607 | wake_up_interruptible(&priv->wait_command_queue); |
@@ -1488,10 +1609,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1488 | cancel_delayed_work(&priv->request_scan); | 1609 | cancel_delayed_work(&priv->request_scan); |
1489 | schedule_work(&priv->link_down); | 1610 | schedule_work(&priv->link_down); |
1490 | queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); | 1611 | queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); |
1491 | handled |= CX2_INTA_BIT_RF_KILL_DONE; | 1612 | handled |= IPW_INTA_BIT_RF_KILL_DONE; |
1492 | } | 1613 | } |
1493 | 1614 | ||
1494 | if (inta & CX2_INTA_BIT_FATAL_ERROR) { | 1615 | if (inta & IPW_INTA_BIT_FATAL_ERROR) { |
1495 | IPW_ERROR("Firmware error detected. Restarting.\n"); | 1616 | IPW_ERROR("Firmware error detected. Restarting.\n"); |
1496 | #ifdef CONFIG_IPW_DEBUG | 1617 | #ifdef CONFIG_IPW_DEBUG |
1497 | if (ipw_debug_level & IPW_DL_FW_ERRORS) { | 1618 | if (ipw_debug_level & IPW_DL_FW_ERRORS) { |
@@ -1499,13 +1620,23 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1499 | ipw_dump_nic_event_log(priv); | 1620 | ipw_dump_nic_event_log(priv); |
1500 | } | 1621 | } |
1501 | #endif | 1622 | #endif |
1623 | /* XXX: If hardware encryption is for WPA/WPA2, | ||
1624 | * we have to notify the supplicant. */ | ||
1625 | if (priv->ieee->sec.encrypt) { | ||
1626 | priv->status &= ~STATUS_ASSOCIATED; | ||
1627 | notify_wx_assoc_event(priv); | ||
1628 | } | ||
1629 | |||
1630 | /* Keep the restart process from trying to send host | ||
1631 | * commands by clearing the INIT status bit */ | ||
1632 | priv->status &= ~STATUS_INIT; | ||
1502 | queue_work(priv->workqueue, &priv->adapter_restart); | 1633 | queue_work(priv->workqueue, &priv->adapter_restart); |
1503 | handled |= CX2_INTA_BIT_FATAL_ERROR; | 1634 | handled |= IPW_INTA_BIT_FATAL_ERROR; |
1504 | } | 1635 | } |
1505 | 1636 | ||
1506 | if (inta & CX2_INTA_BIT_PARITY_ERROR) { | 1637 | if (inta & IPW_INTA_BIT_PARITY_ERROR) { |
1507 | IPW_ERROR("Parity error\n"); | 1638 | IPW_ERROR("Parity error\n"); |
1508 | handled |= CX2_INTA_BIT_PARITY_ERROR; | 1639 | handled |= IPW_INTA_BIT_PARITY_ERROR; |
1509 | } | 1640 | } |
1510 | 1641 | ||
1511 | if (handled != inta) { | 1642 | if (handled != inta) { |
@@ -1594,8 +1725,9 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) | |||
1594 | 1725 | ||
1595 | priv->status |= STATUS_HCMD_ACTIVE; | 1726 | priv->status |= STATUS_HCMD_ACTIVE; |
1596 | 1727 | ||
1597 | IPW_DEBUG_HC("Sending %s command (#%d), %d bytes\n", | 1728 | IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n", |
1598 | get_cmd_string(cmd->cmd), cmd->cmd, cmd->len); | 1729 | get_cmd_string(cmd->cmd), cmd->cmd, cmd->len, |
1730 | priv->status); | ||
1599 | printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); | 1731 | printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); |
1600 | 1732 | ||
1601 | rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0); | 1733 | rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0); |
@@ -1623,7 +1755,7 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) | |||
1623 | spin_unlock_irqrestore(&priv->lock, flags); | 1755 | spin_unlock_irqrestore(&priv->lock, flags); |
1624 | } | 1756 | } |
1625 | 1757 | ||
1626 | if (priv->status & STATUS_RF_KILL_MASK) { | 1758 | if (priv->status & STATUS_RF_KILL_HW) { |
1627 | IPW_DEBUG_INFO("Command aborted due to RF Kill Switch\n"); | 1759 | IPW_DEBUG_INFO("Command aborted due to RF Kill Switch\n"); |
1628 | return -EIO; | 1760 | return -EIO; |
1629 | } | 1761 | } |
@@ -1732,10 +1864,20 @@ static void ipw_adapter_restart(void *adapter) | |||
1732 | return; | 1864 | return; |
1733 | 1865 | ||
1734 | ipw_down(priv); | 1866 | ipw_down(priv); |
1867 | |||
1868 | if (priv->assoc_network && | ||
1869 | (priv->assoc_network->capability & WLAN_CAPABILITY_IBSS)) | ||
1870 | ipw_remove_current_network(priv); | ||
1871 | |||
1735 | if (ipw_up(priv)) { | 1872 | if (ipw_up(priv)) { |
1736 | IPW_ERROR("Failed to up device\n"); | 1873 | IPW_ERROR("Failed to up device\n"); |
1737 | return; | 1874 | return; |
1738 | } | 1875 | } |
1876 | |||
1877 | if ((priv->capability & CAP_PRIVACY_ON) && | ||
1878 | (priv->ieee->sec.level == SEC_LEVEL_1) && | ||
1879 | !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) | ||
1880 | ipw_set_hwcrypto_keys(priv); | ||
1739 | } | 1881 | } |
1740 | 1882 | ||
1741 | static void ipw_bg_adapter_restart(void *data) | 1883 | static void ipw_bg_adapter_restart(void *data) |
@@ -1775,11 +1917,6 @@ static int ipw_send_scan_request_ext(struct ipw_priv *priv, | |||
1775 | .len = sizeof(*request) | 1917 | .len = sizeof(*request) |
1776 | }; | 1918 | }; |
1777 | 1919 | ||
1778 | if (!priv || !request) { | ||
1779 | IPW_ERROR("Invalid args\n"); | ||
1780 | return -1; | ||
1781 | } | ||
1782 | |||
1783 | memcpy(&cmd.param, request, sizeof(*request)); | 1920 | memcpy(&cmd.param, request, sizeof(*request)); |
1784 | if (ipw_send_cmd(priv, &cmd)) { | 1921 | if (ipw_send_cmd(priv, &cmd)) { |
1785 | IPW_ERROR("failed to send SCAN_REQUEST_EXT command\n"); | 1922 | IPW_ERROR("failed to send SCAN_REQUEST_EXT command\n"); |
@@ -1907,7 +2044,6 @@ static int ipw_set_random_seed(struct ipw_priv *priv) | |||
1907 | return 0; | 2044 | return 0; |
1908 | } | 2045 | } |
1909 | 2046 | ||
1910 | #if 0 | ||
1911 | static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) | 2047 | static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) |
1912 | { | 2048 | { |
1913 | struct host_cmd cmd = { | 2049 | struct host_cmd cmd = { |
@@ -1929,7 +2065,6 @@ static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) | |||
1929 | 2065 | ||
1930 | return 0; | 2066 | return 0; |
1931 | } | 2067 | } |
1932 | #endif | ||
1933 | 2068 | ||
1934 | static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) | 2069 | static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) |
1935 | { | 2070 | { |
@@ -2166,7 +2301,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) | |||
2166 | IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n"); | 2301 | IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n"); |
2167 | 2302 | ||
2168 | /* write the eeprom data to sram */ | 2303 | /* write the eeprom data to sram */ |
2169 | for (i = 0; i < CX2_EEPROM_IMAGE_SIZE; i++) | 2304 | for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++) |
2170 | ipw_write8(priv, IPW_EEPROM_DATA + i, priv->eeprom[i]); | 2305 | ipw_write8(priv, IPW_EEPROM_DATA + i, priv->eeprom[i]); |
2171 | 2306 | ||
2172 | /* Do not load eeprom data on fatal error or suspend */ | 2307 | /* Do not load eeprom data on fatal error or suspend */ |
@@ -2186,14 +2321,14 @@ static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) | |||
2186 | count >>= 2; | 2321 | count >>= 2; |
2187 | if (!count) | 2322 | if (!count) |
2188 | return; | 2323 | return; |
2189 | _ipw_write32(priv, CX2_AUTOINC_ADDR, start); | 2324 | _ipw_write32(priv, IPW_AUTOINC_ADDR, start); |
2190 | while (count--) | 2325 | while (count--) |
2191 | _ipw_write32(priv, CX2_AUTOINC_DATA, 0); | 2326 | _ipw_write32(priv, IPW_AUTOINC_DATA, 0); |
2192 | } | 2327 | } |
2193 | 2328 | ||
2194 | static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv) | 2329 | static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv) |
2195 | { | 2330 | { |
2196 | ipw_zero_memory(priv, CX2_SHARED_SRAM_DMA_CONTROL, | 2331 | ipw_zero_memory(priv, IPW_SHARED_SRAM_DMA_CONTROL, |
2197 | CB_NUMBER_OF_ELEMENTS_SMALL * | 2332 | CB_NUMBER_OF_ELEMENTS_SMALL * |
2198 | sizeof(struct command_block)); | 2333 | sizeof(struct command_block)); |
2199 | } | 2334 | } |
@@ -2207,7 +2342,7 @@ static int ipw_fw_dma_enable(struct ipw_priv *priv) | |||
2207 | ipw_fw_dma_reset_command_blocks(priv); | 2342 | ipw_fw_dma_reset_command_blocks(priv); |
2208 | 2343 | ||
2209 | /* Write CB base address */ | 2344 | /* Write CB base address */ |
2210 | ipw_write_reg32(priv, CX2_DMA_I_CB_BASE, CX2_SHARED_SRAM_DMA_CONTROL); | 2345 | ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL); |
2211 | 2346 | ||
2212 | IPW_DEBUG_FW("<< : \n"); | 2347 | IPW_DEBUG_FW("<< : \n"); |
2213 | return 0; | 2348 | return 0; |
@@ -2221,7 +2356,7 @@ static void ipw_fw_dma_abort(struct ipw_priv *priv) | |||
2221 | 2356 | ||
2222 | //set the Stop and Abort bit | 2357 | //set the Stop and Abort bit |
2223 | control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT; | 2358 | control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT; |
2224 | ipw_write_reg32(priv, CX2_DMA_I_DMA_CONTROL, control); | 2359 | ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); |
2225 | priv->sram_desc.last_cb_index = 0; | 2360 | priv->sram_desc.last_cb_index = 0; |
2226 | 2361 | ||
2227 | IPW_DEBUG_FW("<< \n"); | 2362 | IPW_DEBUG_FW("<< \n"); |
@@ -2231,7 +2366,7 @@ static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index, | |||
2231 | struct command_block *cb) | 2366 | struct command_block *cb) |
2232 | { | 2367 | { |
2233 | u32 address = | 2368 | u32 address = |
2234 | CX2_SHARED_SRAM_DMA_CONTROL + | 2369 | IPW_SHARED_SRAM_DMA_CONTROL + |
2235 | (sizeof(struct command_block) * index); | 2370 | (sizeof(struct command_block) * index); |
2236 | IPW_DEBUG_FW(">> :\n"); | 2371 | IPW_DEBUG_FW(">> :\n"); |
2237 | 2372 | ||
@@ -2255,13 +2390,13 @@ static int ipw_fw_dma_kick(struct ipw_priv *priv) | |||
2255 | &priv->sram_desc.cb_list[index]); | 2390 | &priv->sram_desc.cb_list[index]); |
2256 | 2391 | ||
2257 | /* Enable the DMA in the CSR register */ | 2392 | /* Enable the DMA in the CSR register */ |
2258 | ipw_clear_bit(priv, CX2_RESET_REG, | 2393 | ipw_clear_bit(priv, IPW_RESET_REG, |
2259 | CX2_RESET_REG_MASTER_DISABLED | | 2394 | IPW_RESET_REG_MASTER_DISABLED | |
2260 | CX2_RESET_REG_STOP_MASTER); | 2395 | IPW_RESET_REG_STOP_MASTER); |
2261 | 2396 | ||
2262 | /* Set the Start bit. */ | 2397 | /* Set the Start bit. */ |
2263 | control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_START; | 2398 | control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_START; |
2264 | ipw_write_reg32(priv, CX2_DMA_I_DMA_CONTROL, control); | 2399 | ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); |
2265 | 2400 | ||
2266 | IPW_DEBUG_FW("<< :\n"); | 2401 | IPW_DEBUG_FW("<< :\n"); |
2267 | return 0; | 2402 | return 0; |
@@ -2274,12 +2409,12 @@ static void ipw_fw_dma_dump_command_block(struct ipw_priv *priv) | |||
2274 | u32 cb_fields_address = 0; | 2409 | u32 cb_fields_address = 0; |
2275 | 2410 | ||
2276 | IPW_DEBUG_FW(">> :\n"); | 2411 | IPW_DEBUG_FW(">> :\n"); |
2277 | address = ipw_read_reg32(priv, CX2_DMA_I_CURRENT_CB); | 2412 | address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); |
2278 | IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address); | 2413 | IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address); |
2279 | 2414 | ||
2280 | /* Read the DMA Controlor register */ | 2415 | /* Read the DMA Controlor register */ |
2281 | register_value = ipw_read_reg32(priv, CX2_DMA_I_DMA_CONTROL); | 2416 | register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL); |
2282 | IPW_DEBUG_FW_INFO("CX2_DMA_I_DMA_CONTROL is 0x%x \n", register_value); | 2417 | IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x \n", register_value); |
2283 | 2418 | ||
2284 | /* Print the CB values */ | 2419 | /* Print the CB values */ |
2285 | cb_fields_address = address; | 2420 | cb_fields_address = address; |
@@ -2308,9 +2443,9 @@ static int ipw_fw_dma_command_block_index(struct ipw_priv *priv) | |||
2308 | u32 current_cb_index = 0; | 2443 | u32 current_cb_index = 0; |
2309 | 2444 | ||
2310 | IPW_DEBUG_FW("<< :\n"); | 2445 | IPW_DEBUG_FW("<< :\n"); |
2311 | current_cb_address = ipw_read_reg32(priv, CX2_DMA_I_CURRENT_CB); | 2446 | current_cb_address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); |
2312 | 2447 | ||
2313 | current_cb_index = (current_cb_address - CX2_SHARED_SRAM_DMA_CONTROL) / | 2448 | current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) / |
2314 | sizeof(struct command_block); | 2449 | sizeof(struct command_block); |
2315 | 2450 | ||
2316 | IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n", | 2451 | IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n", |
@@ -2439,8 +2574,8 @@ static int ipw_fw_dma_wait(struct ipw_priv *priv) | |||
2439 | ipw_fw_dma_abort(priv); | 2574 | ipw_fw_dma_abort(priv); |
2440 | 2575 | ||
2441 | /*Disable the DMA in the CSR register */ | 2576 | /*Disable the DMA in the CSR register */ |
2442 | ipw_set_bit(priv, CX2_RESET_REG, | 2577 | ipw_set_bit(priv, IPW_RESET_REG, |
2443 | CX2_RESET_REG_MASTER_DISABLED | CX2_RESET_REG_STOP_MASTER); | 2578 | IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER); |
2444 | 2579 | ||
2445 | IPW_DEBUG_FW("<< dmaWaitSync \n"); | 2580 | IPW_DEBUG_FW("<< dmaWaitSync \n"); |
2446 | return 0; | 2581 | return 0; |
@@ -2504,10 +2639,10 @@ static int ipw_stop_master(struct ipw_priv *priv) | |||
2504 | 2639 | ||
2505 | IPW_DEBUG_TRACE(">> \n"); | 2640 | IPW_DEBUG_TRACE(">> \n"); |
2506 | /* stop master. typical delay - 0 */ | 2641 | /* stop master. typical delay - 0 */ |
2507 | ipw_set_bit(priv, CX2_RESET_REG, CX2_RESET_REG_STOP_MASTER); | 2642 | ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); |
2508 | 2643 | ||
2509 | rc = ipw_poll_bit(priv, CX2_RESET_REG, | 2644 | rc = ipw_poll_bit(priv, IPW_RESET_REG, |
2510 | CX2_RESET_REG_MASTER_DISABLED, 100); | 2645 | IPW_RESET_REG_MASTER_DISABLED, 100); |
2511 | if (rc < 0) { | 2646 | if (rc < 0) { |
2512 | IPW_ERROR("stop master failed in 10ms\n"); | 2647 | IPW_ERROR("stop master failed in 10ms\n"); |
2513 | return -1; | 2648 | return -1; |
@@ -2523,7 +2658,7 @@ static void ipw_arc_release(struct ipw_priv *priv) | |||
2523 | IPW_DEBUG_TRACE(">> \n"); | 2658 | IPW_DEBUG_TRACE(">> \n"); |
2524 | mdelay(5); | 2659 | mdelay(5); |
2525 | 2660 | ||
2526 | ipw_clear_bit(priv, CX2_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); | 2661 | ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); |
2527 | 2662 | ||
2528 | /* no one knows timing, for safety add some delay */ | 2663 | /* no one knows timing, for safety add some delay */ |
2529 | mdelay(5); | 2664 | mdelay(5); |
@@ -2540,7 +2675,7 @@ struct fw_chunk { | |||
2540 | }; | 2675 | }; |
2541 | 2676 | ||
2542 | #define IPW_FW_MAJOR_VERSION 2 | 2677 | #define IPW_FW_MAJOR_VERSION 2 |
2543 | #define IPW_FW_MINOR_VERSION 2 | 2678 | #define IPW_FW_MINOR_VERSION 3 |
2544 | 2679 | ||
2545 | #define IPW_FW_MINOR(x) ((x & 0xff) >> 8) | 2680 | #define IPW_FW_MINOR(x) ((x & 0xff) >> 8) |
2546 | #define IPW_FW_MAJOR(x) (x & 0xff) | 2681 | #define IPW_FW_MAJOR(x) (x & 0xff) |
@@ -2574,8 +2709,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
2574 | 2709 | ||
2575 | // spin_lock_irqsave(&priv->lock, flags); | 2710 | // spin_lock_irqsave(&priv->lock, flags); |
2576 | 2711 | ||
2577 | for (addr = CX2_SHARED_LOWER_BOUND; | 2712 | for (addr = IPW_SHARED_LOWER_BOUND; |
2578 | addr < CX2_REGISTER_DOMAIN1_END; addr += 4) { | 2713 | addr < IPW_REGISTER_DOMAIN1_END; addr += 4) { |
2579 | ipw_write32(priv, addr, 0); | 2714 | ipw_write32(priv, addr, 0); |
2580 | } | 2715 | } |
2581 | 2716 | ||
@@ -2584,16 +2719,16 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
2584 | /* destroy DMA queues */ | 2719 | /* destroy DMA queues */ |
2585 | /* reset sequence */ | 2720 | /* reset sequence */ |
2586 | 2721 | ||
2587 | ipw_write_reg32(priv, CX2_MEM_HALT_AND_RESET, CX2_BIT_HALT_RESET_ON); | 2722 | ipw_write_reg32(priv, IPW_MEM_HALT_AND_RESET, IPW_BIT_HALT_RESET_ON); |
2588 | ipw_arc_release(priv); | 2723 | ipw_arc_release(priv); |
2589 | ipw_write_reg32(priv, CX2_MEM_HALT_AND_RESET, CX2_BIT_HALT_RESET_OFF); | 2724 | ipw_write_reg32(priv, IPW_MEM_HALT_AND_RESET, IPW_BIT_HALT_RESET_OFF); |
2590 | mdelay(1); | 2725 | mdelay(1); |
2591 | 2726 | ||
2592 | /* reset PHY */ | 2727 | /* reset PHY */ |
2593 | ipw_write_reg32(priv, CX2_INTERNAL_CMD_EVENT, CX2_BASEBAND_POWER_DOWN); | 2728 | ipw_write_reg32(priv, IPW_INTERNAL_CMD_EVENT, IPW_BASEBAND_POWER_DOWN); |
2594 | mdelay(1); | 2729 | mdelay(1); |
2595 | 2730 | ||
2596 | ipw_write_reg32(priv, CX2_INTERNAL_CMD_EVENT, 0); | 2731 | ipw_write_reg32(priv, IPW_INTERNAL_CMD_EVENT, 0); |
2597 | mdelay(1); | 2732 | mdelay(1); |
2598 | 2733 | ||
2599 | /* enable ucode store */ | 2734 | /* enable ucode store */ |
@@ -2611,19 +2746,19 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
2611 | */ | 2746 | */ |
2612 | /* load new ipw uCode */ | 2747 | /* load new ipw uCode */ |
2613 | for (i = 0; i < len / 2; i++) | 2748 | for (i = 0; i < len / 2; i++) |
2614 | ipw_write_reg16(priv, CX2_BASEBAND_CONTROL_STORE, | 2749 | ipw_write_reg16(priv, IPW_BASEBAND_CONTROL_STORE, |
2615 | cpu_to_le16(image[i])); | 2750 | cpu_to_le16(image[i])); |
2616 | 2751 | ||
2617 | /* enable DINO */ | 2752 | /* enable DINO */ |
2618 | ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0); | 2753 | ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); |
2619 | ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, DINO_ENABLE_SYSTEM); | 2754 | ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, DINO_ENABLE_SYSTEM); |
2620 | 2755 | ||
2621 | /* this is where the igx / win driver deveates from the VAP driver. */ | 2756 | /* this is where the igx / win driver deveates from the VAP driver. */ |
2622 | 2757 | ||
2623 | /* wait for alive response */ | 2758 | /* wait for alive response */ |
2624 | for (i = 0; i < 100; i++) { | 2759 | for (i = 0; i < 100; i++) { |
2625 | /* poll for incoming data */ | 2760 | /* poll for incoming data */ |
2626 | cr = ipw_read_reg8(priv, CX2_BASEBAND_CONTROL_STATUS); | 2761 | cr = ipw_read_reg8(priv, IPW_BASEBAND_CONTROL_STATUS); |
2627 | if (cr & DINO_RXFIFO_DATA) | 2762 | if (cr & DINO_RXFIFO_DATA) |
2628 | break; | 2763 | break; |
2629 | mdelay(1); | 2764 | mdelay(1); |
@@ -2636,7 +2771,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
2636 | for (i = 0; i < ARRAY_SIZE(response_buffer); i++) | 2771 | for (i = 0; i < ARRAY_SIZE(response_buffer); i++) |
2637 | response_buffer[i] = | 2772 | response_buffer[i] = |
2638 | le32_to_cpu(ipw_read_reg32(priv, | 2773 | le32_to_cpu(ipw_read_reg32(priv, |
2639 | CX2_BASEBAND_RX_FIFO_READ)); | 2774 | IPW_BASEBAND_RX_FIFO_READ)); |
2640 | memcpy(&priv->dino_alive, response_buffer, | 2775 | memcpy(&priv->dino_alive, response_buffer, |
2641 | sizeof(priv->dino_alive)); | 2776 | sizeof(priv->dino_alive)); |
2642 | if (priv->dino_alive.alive_command == 1 | 2777 | if (priv->dino_alive.alive_command == 1 |
@@ -2665,7 +2800,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
2665 | 2800 | ||
2666 | /* disable DINO, otherwise for some reason | 2801 | /* disable DINO, otherwise for some reason |
2667 | firmware have problem getting alive resp. */ | 2802 | firmware have problem getting alive resp. */ |
2668 | ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0); | 2803 | ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); |
2669 | 2804 | ||
2670 | // spin_unlock_irqrestore(&priv->lock, flags); | 2805 | // spin_unlock_irqrestore(&priv->lock, flags); |
2671 | 2806 | ||
@@ -2738,16 +2873,16 @@ static int ipw_stop_nic(struct ipw_priv *priv) | |||
2738 | int rc = 0; | 2873 | int rc = 0; |
2739 | 2874 | ||
2740 | /* stop */ | 2875 | /* stop */ |
2741 | ipw_write32(priv, CX2_RESET_REG, CX2_RESET_REG_STOP_MASTER); | 2876 | ipw_write32(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); |
2742 | 2877 | ||
2743 | rc = ipw_poll_bit(priv, CX2_RESET_REG, | 2878 | rc = ipw_poll_bit(priv, IPW_RESET_REG, |
2744 | CX2_RESET_REG_MASTER_DISABLED, 500); | 2879 | IPW_RESET_REG_MASTER_DISABLED, 500); |
2745 | if (rc < 0) { | 2880 | if (rc < 0) { |
2746 | IPW_ERROR("wait for reg master disabled failed\n"); | 2881 | IPW_ERROR("wait for reg master disabled failed\n"); |
2747 | return rc; | 2882 | return rc; |
2748 | } | 2883 | } |
2749 | 2884 | ||
2750 | ipw_set_bit(priv, CX2_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); | 2885 | ipw_set_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); |
2751 | 2886 | ||
2752 | return rc; | 2887 | return rc; |
2753 | } | 2888 | } |
@@ -2757,14 +2892,14 @@ static void ipw_start_nic(struct ipw_priv *priv) | |||
2757 | IPW_DEBUG_TRACE(">>\n"); | 2892 | IPW_DEBUG_TRACE(">>\n"); |
2758 | 2893 | ||
2759 | /* prvHwStartNic release ARC */ | 2894 | /* prvHwStartNic release ARC */ |
2760 | ipw_clear_bit(priv, CX2_RESET_REG, | 2895 | ipw_clear_bit(priv, IPW_RESET_REG, |
2761 | CX2_RESET_REG_MASTER_DISABLED | | 2896 | IPW_RESET_REG_MASTER_DISABLED | |
2762 | CX2_RESET_REG_STOP_MASTER | | 2897 | IPW_RESET_REG_STOP_MASTER | |
2763 | CBD_RESET_REG_PRINCETON_RESET); | 2898 | CBD_RESET_REG_PRINCETON_RESET); |
2764 | 2899 | ||
2765 | /* enable power management */ | 2900 | /* enable power management */ |
2766 | ipw_set_bit(priv, CX2_GP_CNTRL_RW, | 2901 | ipw_set_bit(priv, IPW_GP_CNTRL_RW, |
2767 | CX2_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY); | 2902 | IPW_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY); |
2768 | 2903 | ||
2769 | IPW_DEBUG_TRACE("<<\n"); | 2904 | IPW_DEBUG_TRACE("<<\n"); |
2770 | } | 2905 | } |
@@ -2777,25 +2912,25 @@ static int ipw_init_nic(struct ipw_priv *priv) | |||
2777 | /* reset */ | 2912 | /* reset */ |
2778 | /*prvHwInitNic */ | 2913 | /*prvHwInitNic */ |
2779 | /* set "initialization complete" bit to move adapter to D0 state */ | 2914 | /* set "initialization complete" bit to move adapter to D0 state */ |
2780 | ipw_set_bit(priv, CX2_GP_CNTRL_RW, CX2_GP_CNTRL_BIT_INIT_DONE); | 2915 | ipw_set_bit(priv, IPW_GP_CNTRL_RW, IPW_GP_CNTRL_BIT_INIT_DONE); |
2781 | 2916 | ||
2782 | /* low-level PLL activation */ | 2917 | /* low-level PLL activation */ |
2783 | ipw_write32(priv, CX2_READ_INT_REGISTER, | 2918 | ipw_write32(priv, IPW_READ_INT_REGISTER, |
2784 | CX2_BIT_INT_HOST_SRAM_READ_INT_REGISTER); | 2919 | IPW_BIT_INT_HOST_SRAM_READ_INT_REGISTER); |
2785 | 2920 | ||
2786 | /* wait for clock stabilization */ | 2921 | /* wait for clock stabilization */ |
2787 | rc = ipw_poll_bit(priv, CX2_GP_CNTRL_RW, | 2922 | rc = ipw_poll_bit(priv, IPW_GP_CNTRL_RW, |
2788 | CX2_GP_CNTRL_BIT_CLOCK_READY, 250); | 2923 | IPW_GP_CNTRL_BIT_CLOCK_READY, 250); |
2789 | if (rc < 0) | 2924 | if (rc < 0) |
2790 | IPW_DEBUG_INFO("FAILED wait for clock stablization\n"); | 2925 | IPW_DEBUG_INFO("FAILED wait for clock stablization\n"); |
2791 | 2926 | ||
2792 | /* assert SW reset */ | 2927 | /* assert SW reset */ |
2793 | ipw_set_bit(priv, CX2_RESET_REG, CX2_RESET_REG_SW_RESET); | 2928 | ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_SW_RESET); |
2794 | 2929 | ||
2795 | udelay(10); | 2930 | udelay(10); |
2796 | 2931 | ||
2797 | /* set "initialization complete" bit to move adapter to D0 state */ | 2932 | /* set "initialization complete" bit to move adapter to D0 state */ |
2798 | ipw_set_bit(priv, CX2_GP_CNTRL_RW, CX2_GP_CNTRL_BIT_INIT_DONE); | 2933 | ipw_set_bit(priv, IPW_GP_CNTRL_RW, IPW_GP_CNTRL_BIT_INIT_DONE); |
2799 | 2934 | ||
2800 | IPW_DEBUG_TRACE(">>\n"); | 2935 | IPW_DEBUG_TRACE(">>\n"); |
2801 | return 0; | 2936 | return 0; |
@@ -2853,7 +2988,7 @@ static int ipw_get_fw(struct ipw_priv *priv, | |||
2853 | return 0; | 2988 | return 0; |
2854 | } | 2989 | } |
2855 | 2990 | ||
2856 | #define CX2_RX_BUF_SIZE (3000) | 2991 | #define IPW_RX_BUF_SIZE (3000) |
2857 | 2992 | ||
2858 | static inline void ipw_rx_queue_reset(struct ipw_priv *priv, | 2993 | static inline void ipw_rx_queue_reset(struct ipw_priv *priv, |
2859 | struct ipw_rx_queue *rxq) | 2994 | struct ipw_rx_queue *rxq) |
@@ -2872,7 +3007,7 @@ static inline void ipw_rx_queue_reset(struct ipw_priv *priv, | |||
2872 | * to an SKB, so we need to unmap and free potential storage */ | 3007 | * to an SKB, so we need to unmap and free potential storage */ |
2873 | if (rxq->pool[i].skb != NULL) { | 3008 | if (rxq->pool[i].skb != NULL) { |
2874 | pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, | 3009 | pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, |
2875 | CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); | 3010 | IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); |
2876 | dev_kfree_skb(rxq->pool[i].skb); | 3011 | dev_kfree_skb(rxq->pool[i].skb); |
2877 | rxq->pool[i].skb = NULL; | 3012 | rxq->pool[i].skb = NULL; |
2878 | } | 3013 | } |
@@ -2920,7 +3055,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
2920 | rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss")); | 3055 | rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss")); |
2921 | break; | 3056 | break; |
2922 | 3057 | ||
2923 | #ifdef CONFIG_IPW_MONITOR | 3058 | #ifdef CONFIG_IPW2200_MONITOR |
2924 | case IW_MODE_MONITOR: | 3059 | case IW_MODE_MONITOR: |
2925 | rc = ipw_get_fw(priv, &ucode, | 3060 | rc = ipw_get_fw(priv, &ucode, |
2926 | IPW_FW_NAME("sniffer_ucode")); | 3061 | IPW_FW_NAME("sniffer_ucode")); |
@@ -2962,11 +3097,11 @@ static int ipw_load(struct ipw_priv *priv) | |||
2962 | 3097 | ||
2963 | retry: | 3098 | retry: |
2964 | /* Ensure interrupts are disabled */ | 3099 | /* Ensure interrupts are disabled */ |
2965 | ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL); | 3100 | ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); |
2966 | priv->status &= ~STATUS_INT_ENABLED; | 3101 | priv->status &= ~STATUS_INT_ENABLED; |
2967 | 3102 | ||
2968 | /* ack pending interrupts */ | 3103 | /* ack pending interrupts */ |
2969 | ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); | 3104 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); |
2970 | 3105 | ||
2971 | ipw_stop_nic(priv); | 3106 | ipw_stop_nic(priv); |
2972 | 3107 | ||
@@ -2976,8 +3111,8 @@ static int ipw_load(struct ipw_priv *priv) | |||
2976 | goto error; | 3111 | goto error; |
2977 | } | 3112 | } |
2978 | 3113 | ||
2979 | ipw_zero_memory(priv, CX2_NIC_SRAM_LOWER_BOUND, | 3114 | ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND, |
2980 | CX2_NIC_SRAM_UPPER_BOUND - CX2_NIC_SRAM_LOWER_BOUND); | 3115 | IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); |
2981 | 3116 | ||
2982 | /* DMA the initial boot firmware into the device */ | 3117 | /* DMA the initial boot firmware into the device */ |
2983 | rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), | 3118 | rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), |
@@ -2991,8 +3126,8 @@ static int ipw_load(struct ipw_priv *priv) | |||
2991 | ipw_start_nic(priv); | 3126 | ipw_start_nic(priv); |
2992 | 3127 | ||
2993 | /* wait for the device to finish it's initial startup sequence */ | 3128 | /* wait for the device to finish it's initial startup sequence */ |
2994 | rc = ipw_poll_bit(priv, CX2_INTA_RW, | 3129 | rc = ipw_poll_bit(priv, IPW_INTA_RW, |
2995 | CX2_INTA_BIT_FW_INITIALIZATION_DONE, 500); | 3130 | IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); |
2996 | if (rc < 0) { | 3131 | if (rc < 0) { |
2997 | IPW_ERROR("device failed to boot initial fw image\n"); | 3132 | IPW_ERROR("device failed to boot initial fw image\n"); |
2998 | goto error; | 3133 | goto error; |
@@ -3000,7 +3135,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3000 | IPW_DEBUG_INFO("initial device response after %dms\n", rc); | 3135 | IPW_DEBUG_INFO("initial device response after %dms\n", rc); |
3001 | 3136 | ||
3002 | /* ack fw init done interrupt */ | 3137 | /* ack fw init done interrupt */ |
3003 | ipw_write32(priv, CX2_INTA_RW, CX2_INTA_BIT_FW_INITIALIZATION_DONE); | 3138 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); |
3004 | 3139 | ||
3005 | /* DMA the ucode into the device */ | 3140 | /* DMA the ucode into the device */ |
3006 | rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), | 3141 | rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), |
@@ -3031,14 +3166,14 @@ static int ipw_load(struct ipw_priv *priv) | |||
3031 | } | 3166 | } |
3032 | 3167 | ||
3033 | /* Ensure interrupts are disabled */ | 3168 | /* Ensure interrupts are disabled */ |
3034 | ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL); | 3169 | ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); |
3035 | /* ack pending interrupts */ | 3170 | /* ack pending interrupts */ |
3036 | ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); | 3171 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); |
3037 | 3172 | ||
3038 | /* kick start the device */ | 3173 | /* kick start the device */ |
3039 | ipw_start_nic(priv); | 3174 | ipw_start_nic(priv); |
3040 | 3175 | ||
3041 | if (ipw_read32(priv, CX2_INTA_RW) & CX2_INTA_BIT_PARITY_ERROR) { | 3176 | if (ipw_read32(priv, IPW_INTA_RW) & IPW_INTA_BIT_PARITY_ERROR) { |
3042 | if (retries > 0) { | 3177 | if (retries > 0) { |
3043 | IPW_WARNING("Parity error. Retrying init.\n"); | 3178 | IPW_WARNING("Parity error. Retrying init.\n"); |
3044 | retries--; | 3179 | retries--; |
@@ -3051,8 +3186,8 @@ static int ipw_load(struct ipw_priv *priv) | |||
3051 | } | 3186 | } |
3052 | 3187 | ||
3053 | /* wait for the device */ | 3188 | /* wait for the device */ |
3054 | rc = ipw_poll_bit(priv, CX2_INTA_RW, | 3189 | rc = ipw_poll_bit(priv, IPW_INTA_RW, |
3055 | CX2_INTA_BIT_FW_INITIALIZATION_DONE, 500); | 3190 | IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); |
3056 | if (rc < 0) { | 3191 | if (rc < 0) { |
3057 | IPW_ERROR("device failed to start after 500ms\n"); | 3192 | IPW_ERROR("device failed to start after 500ms\n"); |
3058 | goto error; | 3193 | goto error; |
@@ -3060,7 +3195,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3060 | IPW_DEBUG_INFO("device response after %dms\n", rc); | 3195 | IPW_DEBUG_INFO("device response after %dms\n", rc); |
3061 | 3196 | ||
3062 | /* ack fw init done interrupt */ | 3197 | /* ack fw init done interrupt */ |
3063 | ipw_write32(priv, CX2_INTA_RW, CX2_INTA_BIT_FW_INITIALIZATION_DONE); | 3198 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); |
3064 | 3199 | ||
3065 | /* read eeprom data and initialize the eeprom region of sram */ | 3200 | /* read eeprom data and initialize the eeprom region of sram */ |
3066 | priv->eeprom_delay = 1; | 3201 | priv->eeprom_delay = 1; |
@@ -3072,10 +3207,10 @@ static int ipw_load(struct ipw_priv *priv) | |||
3072 | /* Ensure our queue has valid packets */ | 3207 | /* Ensure our queue has valid packets */ |
3073 | ipw_rx_queue_replenish(priv); | 3208 | ipw_rx_queue_replenish(priv); |
3074 | 3209 | ||
3075 | ipw_write32(priv, CX2_RX_READ_INDEX, priv->rxq->read); | 3210 | ipw_write32(priv, IPW_RX_READ_INDEX, priv->rxq->read); |
3076 | 3211 | ||
3077 | /* ack pending interrupts */ | 3212 | /* ack pending interrupts */ |
3078 | ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); | 3213 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); |
3079 | 3214 | ||
3080 | #ifndef CONFIG_PM | 3215 | #ifndef CONFIG_PM |
3081 | release_firmware(bootfw); | 3216 | release_firmware(bootfw); |
@@ -3829,8 +3964,8 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, | |||
3829 | * stuck (only if we aren't roaming -- | 3964 | * stuck (only if we aren't roaming -- |
3830 | * otherwise we'll never scan more than 2 or 3 | 3965 | * otherwise we'll never scan more than 2 or 3 |
3831 | * channels..) */ | 3966 | * channels..) */ |
3832 | IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | | 3967 | IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | IPW_DL_STATE, |
3833 | IPW_DL_STATE, "Aborting scan with missed beacon.\n"); | 3968 | "Aborting scan with missed beacon.\n"); |
3834 | queue_work(priv->workqueue, &priv->abort_scan); | 3969 | queue_work(priv->workqueue, &priv->abort_scan); |
3835 | } | 3970 | } |
3836 | 3971 | ||
@@ -3891,6 +4026,35 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, | |||
3891 | priv->status &= ~STATUS_ASSOCIATING; | 4026 | priv->status &= ~STATUS_ASSOCIATING; |
3892 | priv->status |= STATUS_ASSOCIATED; | 4027 | priv->status |= STATUS_ASSOCIATED; |
3893 | 4028 | ||
4029 | #ifdef CONFIG_IPW_QOS | ||
4030 | if (priv->status & STATUS_AUTH) { | ||
4031 | if ((sizeof | ||
4032 | (struct | ||
4033 | ieee80211_assoc_response_frame) | ||
4034 | <= notif->size) | ||
4035 | && (notif->size <= 2314)) { | ||
4036 | struct | ||
4037 | ieee80211_rx_stats | ||
4038 | stats = { | ||
4039 | .len = | ||
4040 | notif-> | ||
4041 | size - 1, | ||
4042 | }; | ||
4043 | |||
4044 | IPW_DEBUG_QOS | ||
4045 | ("QoS Associate " | ||
4046 | "size %d\n", | ||
4047 | notif->size); | ||
4048 | ieee80211_rx_mgt(priv-> | ||
4049 | ieee, | ||
4050 | (struct | ||
4051 | ieee80211_hdr | ||
4052 | *) | ||
4053 | ¬if->u.raw, &stats); | ||
4054 | } | ||
4055 | } | ||
4056 | #endif | ||
4057 | |||
3894 | schedule_work(&priv->link_up); | 4058 | schedule_work(&priv->link_up); |
3895 | 4059 | ||
3896 | break; | 4060 | break; |
@@ -3970,12 +4134,21 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, | |||
3970 | ~(STATUS_DISASSOCIATING | | 4134 | ~(STATUS_DISASSOCIATING | |
3971 | STATUS_ASSOCIATING | | 4135 | STATUS_ASSOCIATING | |
3972 | STATUS_ASSOCIATED | STATUS_AUTH); | 4136 | STATUS_ASSOCIATED | STATUS_AUTH); |
4137 | if (priv->assoc_network | ||
4138 | && (priv->assoc_network-> | ||
4139 | capability & | ||
4140 | WLAN_CAPABILITY_IBSS)) | ||
4141 | ipw_remove_current_network | ||
4142 | (priv); | ||
3973 | 4143 | ||
3974 | schedule_work(&priv->link_down); | 4144 | schedule_work(&priv->link_down); |
3975 | 4145 | ||
3976 | break; | 4146 | break; |
3977 | } | 4147 | } |
3978 | 4148 | ||
4149 | case CMAS_RX_ASSOC_RESP: | ||
4150 | break; | ||
4151 | |||
3979 | default: | 4152 | default: |
3980 | IPW_ERROR("assoc: unknown (%d)\n", | 4153 | IPW_ERROR("assoc: unknown (%d)\n", |
3981 | assoc->state); | 4154 | assoc->state); |
@@ -4060,6 +4233,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, | |||
4060 | case CMAS_RX_ASSOC_RESP: | 4233 | case CMAS_RX_ASSOC_RESP: |
4061 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4234 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4062 | IPW_DL_ASSOC, "RX_ASSOC_RESP\n"); | 4235 | IPW_DL_ASSOC, "RX_ASSOC_RESP\n"); |
4236 | |||
4063 | break; | 4237 | break; |
4064 | case CMAS_ASSOCIATED: | 4238 | case CMAS_ASSOCIATED: |
4065 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4239 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
@@ -4106,6 +4280,19 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, | |||
4106 | 4280 | ||
4107 | cancel_delayed_work(&priv->scan_check); | 4281 | cancel_delayed_work(&priv->scan_check); |
4108 | 4282 | ||
4283 | if (priv->status & STATUS_EXIT_PENDING) | ||
4284 | break; | ||
4285 | |||
4286 | priv->ieee->scans++; | ||
4287 | |||
4288 | #ifdef CONFIG_IPW2200_MONITOR | ||
4289 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | ||
4290 | queue_work(priv->workqueue, | ||
4291 | &priv->request_scan); | ||
4292 | break; | ||
4293 | } | ||
4294 | #endif /* CONFIG_IPW2200_MONITOR */ | ||
4295 | |||
4109 | if (!(priv->status & (STATUS_ASSOCIATED | | 4296 | if (!(priv->status & (STATUS_ASSOCIATED | |
4110 | STATUS_ASSOCIATING | | 4297 | STATUS_ASSOCIATING | |
4111 | STATUS_ROAMING | | 4298 | STATUS_ROAMING | |
@@ -4124,8 +4311,6 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, | |||
4124 | && priv->status & STATUS_ASSOCIATED) | 4311 | && priv->status & STATUS_ASSOCIATED) |
4125 | queue_delayed_work(priv->workqueue, | 4312 | queue_delayed_work(priv->workqueue, |
4126 | &priv->request_scan, HZ); | 4313 | &priv->request_scan, HZ); |
4127 | |||
4128 | priv->ieee->scans++; | ||
4129 | break; | 4314 | break; |
4130 | } | 4315 | } |
4131 | 4316 | ||
@@ -4256,43 +4441,43 @@ static int ipw_queue_reset(struct ipw_priv *priv) | |||
4256 | ipw_tx_queue_free(priv); | 4441 | ipw_tx_queue_free(priv); |
4257 | /* Tx CMD queue */ | 4442 | /* Tx CMD queue */ |
4258 | rc = ipw_queue_tx_init(priv, &priv->txq_cmd, nTxCmd, | 4443 | rc = ipw_queue_tx_init(priv, &priv->txq_cmd, nTxCmd, |
4259 | CX2_TX_CMD_QUEUE_READ_INDEX, | 4444 | IPW_TX_CMD_QUEUE_READ_INDEX, |
4260 | CX2_TX_CMD_QUEUE_WRITE_INDEX, | 4445 | IPW_TX_CMD_QUEUE_WRITE_INDEX, |
4261 | CX2_TX_CMD_QUEUE_BD_BASE, | 4446 | IPW_TX_CMD_QUEUE_BD_BASE, |
4262 | CX2_TX_CMD_QUEUE_BD_SIZE); | 4447 | IPW_TX_CMD_QUEUE_BD_SIZE); |
4263 | if (rc) { | 4448 | if (rc) { |
4264 | IPW_ERROR("Tx Cmd queue init failed\n"); | 4449 | IPW_ERROR("Tx Cmd queue init failed\n"); |
4265 | goto error; | 4450 | goto error; |
4266 | } | 4451 | } |
4267 | /* Tx queue(s) */ | 4452 | /* Tx queue(s) */ |
4268 | rc = ipw_queue_tx_init(priv, &priv->txq[0], nTx, | 4453 | rc = ipw_queue_tx_init(priv, &priv->txq[0], nTx, |
4269 | CX2_TX_QUEUE_0_READ_INDEX, | 4454 | IPW_TX_QUEUE_0_READ_INDEX, |
4270 | CX2_TX_QUEUE_0_WRITE_INDEX, | 4455 | IPW_TX_QUEUE_0_WRITE_INDEX, |
4271 | CX2_TX_QUEUE_0_BD_BASE, CX2_TX_QUEUE_0_BD_SIZE); | 4456 | IPW_TX_QUEUE_0_BD_BASE, IPW_TX_QUEUE_0_BD_SIZE); |
4272 | if (rc) { | 4457 | if (rc) { |
4273 | IPW_ERROR("Tx 0 queue init failed\n"); | 4458 | IPW_ERROR("Tx 0 queue init failed\n"); |
4274 | goto error; | 4459 | goto error; |
4275 | } | 4460 | } |
4276 | rc = ipw_queue_tx_init(priv, &priv->txq[1], nTx, | 4461 | rc = ipw_queue_tx_init(priv, &priv->txq[1], nTx, |
4277 | CX2_TX_QUEUE_1_READ_INDEX, | 4462 | IPW_TX_QUEUE_1_READ_INDEX, |
4278 | CX2_TX_QUEUE_1_WRITE_INDEX, | 4463 | IPW_TX_QUEUE_1_WRITE_INDEX, |
4279 | CX2_TX_QUEUE_1_BD_BASE, CX2_TX_QUEUE_1_BD_SIZE); | 4464 | IPW_TX_QUEUE_1_BD_BASE, IPW_TX_QUEUE_1_BD_SIZE); |
4280 | if (rc) { | 4465 | if (rc) { |
4281 | IPW_ERROR("Tx 1 queue init failed\n"); | 4466 | IPW_ERROR("Tx 1 queue init failed\n"); |
4282 | goto error; | 4467 | goto error; |
4283 | } | 4468 | } |
4284 | rc = ipw_queue_tx_init(priv, &priv->txq[2], nTx, | 4469 | rc = ipw_queue_tx_init(priv, &priv->txq[2], nTx, |
4285 | CX2_TX_QUEUE_2_READ_INDEX, | 4470 | IPW_TX_QUEUE_2_READ_INDEX, |
4286 | CX2_TX_QUEUE_2_WRITE_INDEX, | 4471 | IPW_TX_QUEUE_2_WRITE_INDEX, |
4287 | CX2_TX_QUEUE_2_BD_BASE, CX2_TX_QUEUE_2_BD_SIZE); | 4472 | IPW_TX_QUEUE_2_BD_BASE, IPW_TX_QUEUE_2_BD_SIZE); |
4288 | if (rc) { | 4473 | if (rc) { |
4289 | IPW_ERROR("Tx 2 queue init failed\n"); | 4474 | IPW_ERROR("Tx 2 queue init failed\n"); |
4290 | goto error; | 4475 | goto error; |
4291 | } | 4476 | } |
4292 | rc = ipw_queue_tx_init(priv, &priv->txq[3], nTx, | 4477 | rc = ipw_queue_tx_init(priv, &priv->txq[3], nTx, |
4293 | CX2_TX_QUEUE_3_READ_INDEX, | 4478 | IPW_TX_QUEUE_3_READ_INDEX, |
4294 | CX2_TX_QUEUE_3_WRITE_INDEX, | 4479 | IPW_TX_QUEUE_3_WRITE_INDEX, |
4295 | CX2_TX_QUEUE_3_BD_BASE, CX2_TX_QUEUE_3_BD_SIZE); | 4480 | IPW_TX_QUEUE_3_BD_BASE, IPW_TX_QUEUE_3_BD_SIZE); |
4296 | if (rc) { | 4481 | if (rc) { |
4297 | IPW_ERROR("Tx 3 queue init failed\n"); | 4482 | IPW_ERROR("Tx 3 queue init failed\n"); |
4298 | goto error; | 4483 | goto error; |
@@ -4382,7 +4567,7 @@ static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf, | |||
4382 | * Rx theory of operation | 4567 | * Rx theory of operation |
4383 | * | 4568 | * |
4384 | * The host allocates 32 DMA target addresses and passes the host address | 4569 | * The host allocates 32 DMA target addresses and passes the host address |
4385 | * to the firmware at register CX2_RFDS_TABLE_LOWER + N * RFD_SIZE where N is | 4570 | * to the firmware at register IPW_RFDS_TABLE_LOWER + N * RFD_SIZE where N is |
4386 | * 0 to 31 | 4571 | * 0 to 31 |
4387 | * | 4572 | * |
4388 | * Rx Queue Indexes | 4573 | * Rx Queue Indexes |
@@ -4466,7 +4651,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv) | |||
4466 | rxb = list_entry(element, struct ipw_rx_mem_buffer, list); | 4651 | rxb = list_entry(element, struct ipw_rx_mem_buffer, list); |
4467 | list_del(element); | 4652 | list_del(element); |
4468 | 4653 | ||
4469 | ipw_write32(priv, CX2_RFDS_TABLE_LOWER + rxq->write * RFD_SIZE, | 4654 | ipw_write32(priv, IPW_RFDS_TABLE_LOWER + rxq->write * RFD_SIZE, |
4470 | rxb->dma_addr); | 4655 | rxb->dma_addr); |
4471 | rxq->queue[rxq->write] = rxb; | 4656 | rxq->queue[rxq->write] = rxb; |
4472 | rxq->write = (rxq->write + 1) % RX_QUEUE_SIZE; | 4657 | rxq->write = (rxq->write + 1) % RX_QUEUE_SIZE; |
@@ -4481,7 +4666,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv) | |||
4481 | 4666 | ||
4482 | /* If we've added more space for the firmware to place data, tell it */ | 4667 | /* If we've added more space for the firmware to place data, tell it */ |
4483 | if (write != rxq->write) | 4668 | if (write != rxq->write) |
4484 | ipw_write32(priv, CX2_RX_WRITE_INDEX, rxq->write); | 4669 | ipw_write32(priv, IPW_RX_WRITE_INDEX, rxq->write); |
4485 | } | 4670 | } |
4486 | 4671 | ||
4487 | /* | 4672 | /* |
@@ -4502,7 +4687,7 @@ static void ipw_rx_queue_replenish(void *data) | |||
4502 | while (!list_empty(&rxq->rx_used)) { | 4687 | while (!list_empty(&rxq->rx_used)) { |
4503 | element = rxq->rx_used.next; | 4688 | element = rxq->rx_used.next; |
4504 | rxb = list_entry(element, struct ipw_rx_mem_buffer, list); | 4689 | rxb = list_entry(element, struct ipw_rx_mem_buffer, list); |
4505 | rxb->skb = alloc_skb(CX2_RX_BUF_SIZE, GFP_ATOMIC); | 4690 | rxb->skb = alloc_skb(IPW_RX_BUF_SIZE, GFP_ATOMIC); |
4506 | if (!rxb->skb) { | 4691 | if (!rxb->skb) { |
4507 | printk(KERN_CRIT "%s: Can not allocate SKB buffers.\n", | 4692 | printk(KERN_CRIT "%s: Can not allocate SKB buffers.\n", |
4508 | priv->net_dev->name); | 4693 | priv->net_dev->name); |
@@ -4516,7 +4701,7 @@ static void ipw_rx_queue_replenish(void *data) | |||
4516 | rxb->rxb = (struct ipw_rx_buffer *)rxb->skb->data; | 4701 | rxb->rxb = (struct ipw_rx_buffer *)rxb->skb->data; |
4517 | rxb->dma_addr = | 4702 | rxb->dma_addr = |
4518 | pci_map_single(priv->pci_dev, rxb->skb->data, | 4703 | pci_map_single(priv->pci_dev, rxb->skb->data, |
4519 | CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); | 4704 | IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); |
4520 | 4705 | ||
4521 | list_add_tail(&rxb->list, &rxq->rx_free); | 4706 | list_add_tail(&rxb->list, &rxq->rx_free); |
4522 | rxq->free_count++; | 4707 | rxq->free_count++; |
@@ -4549,7 +4734,7 @@ static void ipw_rx_queue_free(struct ipw_priv *priv, struct ipw_rx_queue *rxq) | |||
4549 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | 4734 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { |
4550 | if (rxq->pool[i].skb != NULL) { | 4735 | if (rxq->pool[i].skb != NULL) { |
4551 | pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, | 4736 | pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, |
4552 | CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); | 4737 | IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); |
4553 | dev_kfree_skb(rxq->pool[i].skb); | 4738 | dev_kfree_skb(rxq->pool[i].skb); |
4554 | } | 4739 | } |
4555 | } | 4740 | } |
@@ -5195,20 +5380,21 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5195 | * with an invalid channel for wireless mode will trigger a | 5380 | * with an invalid channel for wireless mode will trigger a |
5196 | * FW fatal error. | 5381 | * FW fatal error. |
5197 | */ | 5382 | */ |
5198 | network->mode = is_valid_channel(priv->ieee->mode, priv->channel); | 5383 | if (!ieee80211_is_valid_channel(priv->ieee, priv->channel)) { |
5199 | if (!network->mode) { | 5384 | const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); |
5200 | IPW_WARNING("Overriding invalid channel\n"); | 5385 | IPW_WARNING("Overriding invalid channel\n"); |
5201 | if (priv->ieee->mode & IEEE_A) { | 5386 | if (priv->ieee->mode & IEEE_A) { |
5202 | network->mode = IEEE_A; | 5387 | network->mode = IEEE_A; |
5203 | priv->channel = band_a_active_channel[0]; | 5388 | priv->channel = geo->a[0].channel; |
5204 | } else if (priv->ieee->mode & IEEE_G) { | 5389 | } else if (priv->ieee->mode & IEEE_G) { |
5205 | network->mode = IEEE_G; | 5390 | network->mode = IEEE_G; |
5206 | priv->channel = band_b_active_channel[0]; | 5391 | priv->channel = geo->bg[0].channel; |
5207 | } else { | 5392 | } else { |
5208 | network->mode = IEEE_B; | 5393 | network->mode = IEEE_B; |
5209 | priv->channel = band_b_active_channel[0]; | 5394 | priv->channel = geo->bg[0].channel; |
5210 | } | 5395 | } |
5211 | } | 5396 | } else |
5397 | network->mode = priv->ieee->mode; | ||
5212 | 5398 | ||
5213 | network->channel = priv->channel; | 5399 | network->channel = priv->channel; |
5214 | priv->config |= CFG_ADHOC_PERSIST; | 5400 | priv->config |= CFG_ADHOC_PERSIST; |
@@ -5239,7 +5425,34 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5239 | network->rsn_ie_len = 0; | 5425 | network->rsn_ie_len = 0; |
5240 | } | 5426 | } |
5241 | 5427 | ||
5242 | static void ipw_send_wep_keys(struct ipw_priv *priv) | 5428 | static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index) |
5429 | { | ||
5430 | struct ipw_tgi_tx_key *key; | ||
5431 | struct host_cmd cmd = { | ||
5432 | .cmd = IPW_CMD_TGI_TX_KEY, | ||
5433 | .len = sizeof(*key) | ||
5434 | }; | ||
5435 | |||
5436 | if (!(priv->ieee->sec.flags & (1 << index))) | ||
5437 | return; | ||
5438 | |||
5439 | key = (struct ipw_tgi_tx_key *)&cmd.param; | ||
5440 | key->key_id = index; | ||
5441 | memcpy(key->key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH); | ||
5442 | key->security_type = type; | ||
5443 | key->station_index = 0; /* always 0 for BSS */ | ||
5444 | key->flags = 0; | ||
5445 | /* 0 for new key; previous value of counter (after fatal error) */ | ||
5446 | key->tx_counter[0] = 0; | ||
5447 | key->tx_counter[1] = 0; | ||
5448 | |||
5449 | if (ipw_send_cmd(priv, &cmd)) { | ||
5450 | IPW_ERROR("failed to send TGI_TX_KEY command\n"); | ||
5451 | return; | ||
5452 | } | ||
5453 | } | ||
5454 | |||
5455 | static void ipw_send_wep_keys(struct ipw_priv *priv, int type) | ||
5243 | { | 5456 | { |
5244 | struct ipw_wep_key *key; | 5457 | struct ipw_wep_key *key; |
5245 | int i; | 5458 | int i; |
@@ -5252,15 +5465,18 @@ static void ipw_send_wep_keys(struct ipw_priv *priv) | |||
5252 | key->cmd_id = DINO_CMD_WEP_KEY; | 5465 | key->cmd_id = DINO_CMD_WEP_KEY; |
5253 | key->seq_num = 0; | 5466 | key->seq_num = 0; |
5254 | 5467 | ||
5468 | /* Note: AES keys cannot be set for multiple times. | ||
5469 | * Only set it at the first time. */ | ||
5255 | for (i = 0; i < 4; i++) { | 5470 | for (i = 0; i < 4; i++) { |
5256 | key->key_index = i; | 5471 | key->key_index = i | type; |
5257 | if (!(priv->sec.flags & (1 << i))) | 5472 | if (!(priv->ieee->sec.flags & (1 << i))) { |
5258 | key->key_size = 0; | 5473 | key->key_size = 0; |
5259 | else { | 5474 | continue; |
5260 | key->key_size = priv->sec.key_sizes[i]; | ||
5261 | memcpy(key->key, priv->sec.keys[i], key->key_size); | ||
5262 | } | 5475 | } |
5263 | 5476 | ||
5477 | key->key_size = priv->ieee->sec.key_sizes[i]; | ||
5478 | memcpy(key->key, priv->ieee->sec.keys[i], key->key_size); | ||
5479 | |||
5264 | if (ipw_send_cmd(priv, &cmd)) { | 5480 | if (ipw_send_cmd(priv, &cmd)) { |
5265 | IPW_ERROR("failed to send WEP_KEY command\n"); | 5481 | IPW_ERROR("failed to send WEP_KEY command\n"); |
5266 | return; | 5482 | return; |
@@ -5268,6 +5484,52 @@ static void ipw_send_wep_keys(struct ipw_priv *priv) | |||
5268 | } | 5484 | } |
5269 | } | 5485 | } |
5270 | 5486 | ||
5487 | static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) | ||
5488 | { | ||
5489 | switch (priv->ieee->sec.level) { | ||
5490 | case SEC_LEVEL_3: | ||
5491 | if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) | ||
5492 | ipw_send_tgi_tx_key(priv, | ||
5493 | DCT_FLAG_EXT_SECURITY_CCM, | ||
5494 | priv->ieee->sec.active_key); | ||
5495 | ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); | ||
5496 | |||
5497 | priv->sys_config.disable_unicast_decryption = 0; | ||
5498 | priv->sys_config.disable_multicast_decryption = 0; | ||
5499 | priv->ieee->host_decrypt = 0; | ||
5500 | if (ipw_send_system_config(priv, &priv->sys_config)) | ||
5501 | IPW_ERROR("ipw_send_system_config failed\n"); | ||
5502 | |||
5503 | break; | ||
5504 | case SEC_LEVEL_2: | ||
5505 | if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) | ||
5506 | ipw_send_tgi_tx_key(priv, | ||
5507 | DCT_FLAG_EXT_SECURITY_TKIP, | ||
5508 | priv->ieee->sec.active_key); | ||
5509 | |||
5510 | priv->sys_config.disable_unicast_decryption = 1; | ||
5511 | priv->sys_config.disable_multicast_decryption = 1; | ||
5512 | priv->ieee->host_decrypt = 1; | ||
5513 | if (ipw_send_system_config(priv, &priv->sys_config)) | ||
5514 | IPW_ERROR("ipw_send_system_config failed\n"); | ||
5515 | |||
5516 | break; | ||
5517 | case SEC_LEVEL_1: | ||
5518 | ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); | ||
5519 | |||
5520 | priv->sys_config.disable_unicast_decryption = 0; | ||
5521 | priv->sys_config.disable_multicast_decryption = 0; | ||
5522 | priv->ieee->host_decrypt = 0; | ||
5523 | if (ipw_send_system_config(priv, &priv->sys_config)) | ||
5524 | IPW_ERROR("ipw_send_system_config failed\n"); | ||
5525 | |||
5526 | break; | ||
5527 | case SEC_LEVEL_0: | ||
5528 | default: | ||
5529 | break; | ||
5530 | } | ||
5531 | } | ||
5532 | |||
5271 | static void ipw_adhoc_check(void *data) | 5533 | static void ipw_adhoc_check(void *data) |
5272 | { | 5534 | { |
5273 | struct ipw_priv *priv = data; | 5535 | struct ipw_priv *priv = data; |
@@ -5321,8 +5583,7 @@ static void ipw_debug_config(struct ipw_priv *priv) | |||
5321 | #define ipw_debug_config(x) do {} while (0) | 5583 | #define ipw_debug_config(x) do {} while (0) |
5322 | #endif | 5584 | #endif |
5323 | 5585 | ||
5324 | static inline void ipw_set_fixed_rate(struct ipw_priv *priv, | 5586 | static inline void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) |
5325 | struct ieee80211_network *network) | ||
5326 | { | 5587 | { |
5327 | /* TODO: Verify that this works... */ | 5588 | /* TODO: Verify that this works... */ |
5328 | struct ipw_fixed_rate fr = { | 5589 | struct ipw_fixed_rate fr = { |
@@ -5350,7 +5611,7 @@ static inline void ipw_set_fixed_rate(struct ipw_priv *priv, | |||
5350 | 5611 | ||
5351 | default: /* 2.4Ghz or Mixed */ | 5612 | default: /* 2.4Ghz or Mixed */ |
5352 | /* IEEE_B */ | 5613 | /* IEEE_B */ |
5353 | if (network->mode == IEEE_B) { | 5614 | if (mode == IEEE_B) { |
5354 | if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) { | 5615 | if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) { |
5355 | /* Invalid fixed rate mask */ | 5616 | /* Invalid fixed rate mask */ |
5356 | IPW_DEBUG_WX | 5617 | IPW_DEBUG_WX |
@@ -5412,78 +5673,98 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
5412 | { | 5673 | { |
5413 | struct ipw_scan_request_ext scan; | 5674 | struct ipw_scan_request_ext scan; |
5414 | int channel_index = 0; | 5675 | int channel_index = 0; |
5415 | int i, err, scan_type; | 5676 | int i, err = 0, scan_type; |
5677 | const struct ieee80211_geo *geo; | ||
5678 | #ifdef CONFIG_IPW2200_MONITOR | ||
5679 | u8 channel; | ||
5680 | #endif | ||
5416 | 5681 | ||
5417 | if (priv->status & STATUS_EXIT_PENDING) { | 5682 | down(&priv->sem); |
5418 | IPW_DEBUG_SCAN("Aborting scan due to device shutdown\n"); | 5683 | |
5419 | priv->status |= STATUS_SCAN_PENDING; | 5684 | geo = ieee80211_get_geo(priv->ieee); |
5420 | return 0; | ||
5421 | } | ||
5422 | 5685 | ||
5423 | if (priv->status & STATUS_SCANNING) { | 5686 | if (priv->status & STATUS_SCANNING) { |
5424 | IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); | 5687 | IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); |
5425 | // IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n"); | ||
5426 | priv->status |= STATUS_SCAN_PENDING; | 5688 | priv->status |= STATUS_SCAN_PENDING; |
5427 | // ipw_abort_scan(priv); | 5689 | goto done; |
5428 | return 0; | ||
5429 | } | 5690 | } |
5430 | 5691 | ||
5431 | if (priv->status & STATUS_SCAN_ABORTING) { | 5692 | if (priv->status & STATUS_SCAN_ABORTING) { |
5432 | IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); | 5693 | IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); |
5433 | priv->status |= STATUS_SCAN_PENDING; | 5694 | priv->status |= STATUS_SCAN_PENDING; |
5434 | return 0; | 5695 | goto done; |
5435 | } | 5696 | } |
5436 | 5697 | ||
5437 | if (priv->status & STATUS_RF_KILL_MASK) { | 5698 | if (priv->status & STATUS_RF_KILL_MASK) { |
5438 | IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n"); | 5699 | IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n"); |
5439 | priv->status |= STATUS_SCAN_PENDING; | 5700 | priv->status |= STATUS_SCAN_PENDING; |
5440 | return 0; | 5701 | goto done; |
5441 | } | 5702 | } |
5442 | 5703 | ||
5443 | memset(&scan, 0, sizeof(scan)); | 5704 | memset(&scan, 0, sizeof(scan)); |
5444 | 5705 | ||
5445 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = cpu_to_le16(20); | 5706 | if (priv->config & CFG_SPEED_SCAN) |
5707 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = | ||
5708 | cpu_to_le16(30); | ||
5709 | else | ||
5710 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = | ||
5711 | cpu_to_le16(20); | ||
5712 | |||
5446 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = | 5713 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = |
5447 | cpu_to_le16(20); | 5714 | cpu_to_le16(20); |
5448 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); | 5715 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); |
5449 | 5716 | ||
5450 | scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); | 5717 | scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); |
5451 | 5718 | ||
5452 | #ifdef CONFIG_IPW_MONITOR | 5719 | #ifdef CONFIG_IPW2200_MONITOR |
5453 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | 5720 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { |
5454 | u8 band = 0, channel = priv->channel; | 5721 | u8 band = 0; |
5455 | 5722 | ||
5456 | if (is_valid_channel(IEEE_A, channel)) | 5723 | switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { |
5724 | case IEEE80211_52GHZ_BAND: | ||
5457 | band = (u8) (IPW_A_MODE << 6) | 1; | 5725 | band = (u8) (IPW_A_MODE << 6) | 1; |
5726 | channel = priv->channel; | ||
5727 | break; | ||
5458 | 5728 | ||
5459 | if (is_valid_channel(IEEE_B | IEEE_G, channel)) | 5729 | case IEEE80211_24GHZ_BAND: |
5460 | band = (u8) (IPW_B_MODE << 6) | 1; | 5730 | band = (u8) (IPW_B_MODE << 6) | 1; |
5731 | channel = priv->channel; | ||
5732 | break; | ||
5461 | 5733 | ||
5462 | if (band == 0) { | 5734 | default: |
5463 | band = (u8) (IPW_B_MODE << 6) | 1; | 5735 | band = (u8) (IPW_B_MODE << 6) | 1; |
5464 | channel = 9; | 5736 | channel = 9; |
5737 | break; | ||
5465 | } | 5738 | } |
5466 | 5739 | ||
5467 | scan.channels_list[channel_index++] = band; | 5740 | scan.channels_list[0] = band; |
5468 | scan.channels_list[channel_index] = channel; | 5741 | scan.channels_list[1] = channel; |
5469 | ipw_set_scan_type(&scan, channel_index, | 5742 | ipw_set_scan_type(&scan, 1, IPW_SCAN_PASSIVE_FULL_DWELL_SCAN); |
5470 | IPW_SCAN_PASSIVE_FULL_DWELL_SCAN); | ||
5471 | 5743 | ||
5744 | /* NOTE: The card will sit on this channel for this time | ||
5745 | * period. Scan aborts are timing sensitive and frequently | ||
5746 | * result in firmware restarts. As such, it is best to | ||
5747 | * set a small dwell_time here and just keep re-issuing | ||
5748 | * scans. Otherwise fast channel hopping will not actually | ||
5749 | * hop channels. | ||
5750 | * | ||
5751 | * TODO: Move SPEED SCAN support to all modes and bands */ | ||
5472 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = | 5752 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = |
5473 | cpu_to_le16(2000); | 5753 | cpu_to_le16(2000); |
5474 | } else { | 5754 | } else { |
5475 | #endif /* CONFIG_IPW_MONITOR */ | 5755 | #endif /* CONFIG_IPW2200_MONITOR */ |
5476 | /* If we are roaming, then make this a directed scan for the current | 5756 | /* If we are roaming, then make this a directed scan for the |
5477 | * network. Otherwise, ensure that every other scan is a fast | 5757 | * current network. Otherwise, ensure that every other scan |
5478 | * channel hop scan */ | 5758 | * is a fast channel hop scan */ |
5479 | if ((priv->status & STATUS_ROAMING) || (!(priv->status & STATUS_ASSOCIATED) && (priv->config & CFG_STATIC_ESSID) && (le32_to_cpu(scan.full_scan_index) % 2))) { /* || ( | 5759 | if ((priv->status & STATUS_ROAMING) |
5480 | (priv->status & STATUS_ASSOCIATED) && | 5760 | || (!(priv->status & STATUS_ASSOCIATED) |
5481 | (priv->ieee->iw_mode == IW_MODE_ADHOC))) { */ | 5761 | && (priv->config & CFG_STATIC_ESSID) |
5762 | && (le32_to_cpu(scan.full_scan_index) % 2))) { | ||
5482 | err = ipw_send_ssid(priv, priv->essid, priv->essid_len); | 5763 | err = ipw_send_ssid(priv, priv->essid, priv->essid_len); |
5483 | if (err) { | 5764 | if (err) { |
5484 | IPW_DEBUG_HC | 5765 | IPW_DEBUG_HC("Attempt to send SSID command " |
5485 | ("Attempt to send SSID command failed.\n"); | 5766 | "failed.\n"); |
5486 | return err; | 5767 | goto done; |
5487 | } | 5768 | } |
5488 | 5769 | ||
5489 | scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; | 5770 | scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; |
@@ -5491,17 +5772,16 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
5491 | scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN; | 5772 | scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN; |
5492 | } | 5773 | } |
5493 | 5774 | ||
5775 | /* Add channels to the scan list */ | ||
5494 | if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { | 5776 | if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { |
5495 | int start = channel_index; | 5777 | int start = channel_index; |
5496 | for (i = 0; i < MAX_A_CHANNELS; i++) { | 5778 | for (i = 0; i < geo->a_channels; i++) { |
5497 | if (band_a_active_channel[i] == 0) | ||
5498 | break; | ||
5499 | if ((priv->status & STATUS_ASSOCIATED) && | 5779 | if ((priv->status & STATUS_ASSOCIATED) && |
5500 | band_a_active_channel[i] == priv->channel) | 5780 | geo->a[i].channel == priv->channel) |
5501 | continue; | 5781 | continue; |
5502 | channel_index++; | 5782 | channel_index++; |
5503 | scan.channels_list[channel_index] = | 5783 | scan.channels_list[channel_index] = |
5504 | band_a_active_channel[i]; | 5784 | geo->a[i].channel; |
5505 | ipw_set_scan_type(&scan, channel_index, | 5785 | ipw_set_scan_type(&scan, channel_index, |
5506 | scan_type); | 5786 | scan_type); |
5507 | } | 5787 | } |
@@ -5516,17 +5796,55 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
5516 | 5796 | ||
5517 | if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { | 5797 | if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { |
5518 | int start = channel_index; | 5798 | int start = channel_index; |
5519 | for (i = 0; i < MAX_B_CHANNELS; i++) { | 5799 | if (priv->config & CFG_SPEED_SCAN) { |
5520 | if (band_b_active_channel[i] == 0) | 5800 | u8 channels[IEEE80211_24GHZ_CHANNELS] = { |
5521 | break; | 5801 | /* nop out the list */ |
5522 | if ((priv->status & STATUS_ASSOCIATED) && | 5802 | [0] = 0 |
5523 | band_b_active_channel[i] == priv->channel) | 5803 | }; |
5524 | continue; | 5804 | |
5525 | channel_index++; | 5805 | u8 channel; |
5526 | scan.channels_list[channel_index] = | 5806 | while (channel_index < IPW_SCAN_CHANNELS) { |
5527 | band_b_active_channel[i]; | 5807 | channel = |
5528 | ipw_set_scan_type(&scan, channel_index, | 5808 | priv->speed_scan[priv-> |
5529 | scan_type); | 5809 | speed_scan_pos]; |
5810 | if (channel == 0) { | ||
5811 | priv->speed_scan_pos = 0; | ||
5812 | channel = priv->speed_scan[0]; | ||
5813 | } | ||
5814 | if ((priv->status & STATUS_ASSOCIATED) | ||
5815 | && channel == priv->channel) { | ||
5816 | priv->speed_scan_pos++; | ||
5817 | continue; | ||
5818 | } | ||
5819 | |||
5820 | /* If this channel has already been | ||
5821 | * added in scan, break from loop | ||
5822 | * and this will be the first channel | ||
5823 | * in the next scan. | ||
5824 | */ | ||
5825 | if (channels[channel - 1] != 0) | ||
5826 | break; | ||
5827 | |||
5828 | channels[channel - 1] = 1; | ||
5829 | priv->speed_scan_pos++; | ||
5830 | channel_index++; | ||
5831 | scan.channels_list[channel_index] = | ||
5832 | channel; | ||
5833 | ipw_set_scan_type(&scan, channel_index, | ||
5834 | scan_type); | ||
5835 | } | ||
5836 | } else { | ||
5837 | for (i = 0; i < geo->bg_channels; i++) { | ||
5838 | if ((priv->status & STATUS_ASSOCIATED) | ||
5839 | && geo->bg[i].channel == | ||
5840 | priv->channel) | ||
5841 | continue; | ||
5842 | channel_index++; | ||
5843 | scan.channels_list[channel_index] = | ||
5844 | geo->bg[i].channel; | ||
5845 | ipw_set_scan_type(&scan, channel_index, | ||
5846 | scan_type); | ||
5847 | } | ||
5530 | } | 5848 | } |
5531 | 5849 | ||
5532 | if (start != channel_index) { | 5850 | if (start != channel_index) { |
@@ -5535,28 +5853,22 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
5535 | start); | 5853 | start); |
5536 | } | 5854 | } |
5537 | } | 5855 | } |
5538 | #ifdef CONFIG_IPW_MONITOR | 5856 | #ifdef CONFIG_IPW2200_MONITOR |
5539 | } | 5857 | } |
5540 | #endif | 5858 | #endif |
5541 | 5859 | ||
5542 | err = ipw_send_scan_request_ext(priv, &scan); | 5860 | err = ipw_send_scan_request_ext(priv, &scan); |
5543 | if (err) { | 5861 | if (err) { |
5544 | IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); | 5862 | IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); |
5545 | return -EIO; | 5863 | goto done; |
5546 | } | 5864 | } |
5547 | 5865 | ||
5548 | priv->status |= STATUS_SCANNING; | 5866 | priv->status |= STATUS_SCANNING; |
5549 | priv->status &= ~STATUS_SCAN_PENDING; | 5867 | priv->status &= ~STATUS_SCAN_PENDING; |
5550 | 5868 | ||
5551 | return 0; | 5869 | done: |
5552 | } | ||
5553 | |||
5554 | static void ipw_bg_request_scan(void *data) | ||
5555 | { | ||
5556 | struct ipw_priv *priv = data; | ||
5557 | down(&priv->sem); | ||
5558 | ipw_request_scan(data); | ||
5559 | up(&priv->sem); | 5870 | up(&priv->sem); |
5871 | return err; | ||
5560 | } | 5872 | } |
5561 | 5873 | ||
5562 | static void ipw_bg_abort_scan(void *data) | 5874 | static void ipw_bg_abort_scan(void *data) |
@@ -5608,7 +5920,8 @@ struct ipw_param { | |||
5608 | } wpa_param; | 5920 | } wpa_param; |
5609 | struct { | 5921 | struct { |
5610 | u32 len; | 5922 | u32 len; |
5611 | u8 *data; | 5923 | u8 reserved[32]; |
5924 | u8 data[0]; | ||
5612 | } wpa_ie; | 5925 | } wpa_ie; |
5613 | struct { | 5926 | struct { |
5614 | int command; | 5927 | int command; |
@@ -5631,29 +5944,9 @@ struct ipw_param { | |||
5631 | 5944 | ||
5632 | static int ipw_wpa_enable(struct ipw_priv *priv, int value) | 5945 | static int ipw_wpa_enable(struct ipw_priv *priv, int value) |
5633 | { | 5946 | { |
5634 | struct ieee80211_device *ieee = priv->ieee; | 5947 | /* This is called when wpa_supplicant loads and closes the driver |
5635 | struct ieee80211_security sec = { | 5948 | * interface. */ |
5636 | .flags = SEC_LEVEL | SEC_ENABLED, | 5949 | return 0; |
5637 | }; | ||
5638 | int ret = 0; | ||
5639 | |||
5640 | ieee->wpa_enabled = value; | ||
5641 | |||
5642 | if (value) { | ||
5643 | sec.level = SEC_LEVEL_3; | ||
5644 | sec.enabled = 1; | ||
5645 | } else { | ||
5646 | sec.level = SEC_LEVEL_0; | ||
5647 | sec.enabled = 0; | ||
5648 | ieee->wpa_ie_len = 0; | ||
5649 | } | ||
5650 | |||
5651 | if (ieee->set_security) | ||
5652 | ieee->set_security(ieee->dev, &sec); | ||
5653 | else | ||
5654 | ret = -EOPNOTSUPP; | ||
5655 | |||
5656 | return ret; | ||
5657 | } | 5950 | } |
5658 | 5951 | ||
5659 | #define AUTH_ALG_OPEN_SYSTEM 0x1 | 5952 | #define AUTH_ALG_OPEN_SYSTEM 0x1 |
@@ -5714,9 +6007,37 @@ static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value) | |||
5714 | 6007 | ||
5715 | break; | 6008 | break; |
5716 | 6009 | ||
5717 | case IPW_PARAM_DROP_UNENCRYPTED: | 6010 | case IPW_PARAM_DROP_UNENCRYPTED:{ |
5718 | priv->ieee->drop_unencrypted = value; | 6011 | /* HACK: |
5719 | break; | 6012 | * |
6013 | * wpa_supplicant calls set_wpa_enabled when the driver | ||
6014 | * is loaded and unloaded, regardless of if WPA is being | ||
6015 | * used. No other calls are made which can be used to | ||
6016 | * determine if encryption will be used or not prior to | ||
6017 | * association being expected. If encryption is not being | ||
6018 | * used, drop_unencrypted is set to false, else true -- we | ||
6019 | * can use this to determine if the CAP_PRIVACY_ON bit should | ||
6020 | * be set. | ||
6021 | */ | ||
6022 | struct ieee80211_security sec = { | ||
6023 | .flags = SEC_ENABLED, | ||
6024 | .enabled = value, | ||
6025 | }; | ||
6026 | priv->ieee->drop_unencrypted = value; | ||
6027 | /* We only change SEC_LEVEL for open mode. Others | ||
6028 | * are set by ipw_wpa_set_encryption. | ||
6029 | */ | ||
6030 | if (!value) { | ||
6031 | sec.flags |= SEC_LEVEL; | ||
6032 | sec.level = SEC_LEVEL_0; | ||
6033 | } else { | ||
6034 | sec.flags |= SEC_LEVEL; | ||
6035 | sec.level = SEC_LEVEL_1; | ||
6036 | } | ||
6037 | if (priv->ieee->set_security) | ||
6038 | priv->ieee->set_security(priv->ieee->dev, &sec); | ||
6039 | break; | ||
6040 | } | ||
5720 | 6041 | ||
5721 | case IPW_PARAM_PRIVACY_INVOKED: | 6042 | case IPW_PARAM_PRIVACY_INVOKED: |
5722 | priv->ieee->privacy_invoked = value; | 6043 | priv->ieee->privacy_invoked = value; |
@@ -5793,9 +6114,6 @@ static int ipw_wpa_set_wpa_ie(struct net_device *dev, | |||
5793 | struct ieee80211_device *ieee = priv->ieee; | 6114 | struct ieee80211_device *ieee = priv->ieee; |
5794 | u8 *buf; | 6115 | u8 *buf; |
5795 | 6116 | ||
5796 | if (!ieee->wpa_enabled) | ||
5797 | return -EOPNOTSUPP; | ||
5798 | |||
5799 | if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || | 6117 | if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || |
5800 | (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) | 6118 | (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) |
5801 | return -EINVAL; | 6119 | return -EINVAL; |
@@ -5857,6 +6175,7 @@ static int ipw_wpa_set_encryption(struct net_device *dev, | |||
5857 | if (strcmp(param->u.crypt.alg, "none") == 0) { | 6175 | if (strcmp(param->u.crypt.alg, "none") == 0) { |
5858 | if (crypt) { | 6176 | if (crypt) { |
5859 | sec.enabled = 0; | 6177 | sec.enabled = 0; |
6178 | sec.encrypt = 0; | ||
5860 | sec.level = SEC_LEVEL_0; | 6179 | sec.level = SEC_LEVEL_0; |
5861 | sec.flags |= SEC_ENABLED | SEC_LEVEL; | 6180 | sec.flags |= SEC_ENABLED | SEC_LEVEL; |
5862 | ieee80211_crypt_delayed_deinit(ieee, crypt); | 6181 | ieee80211_crypt_delayed_deinit(ieee, crypt); |
@@ -5864,8 +6183,14 @@ static int ipw_wpa_set_encryption(struct net_device *dev, | |||
5864 | goto done; | 6183 | goto done; |
5865 | } | 6184 | } |
5866 | sec.enabled = 1; | 6185 | sec.enabled = 1; |
6186 | sec.encrypt = 1; | ||
5867 | sec.flags |= SEC_ENABLED; | 6187 | sec.flags |= SEC_ENABLED; |
5868 | 6188 | ||
6189 | /* IPW HW cannot build TKIP MIC, host decryption still needed. */ | ||
6190 | if (!(ieee->host_encrypt || ieee->host_decrypt) && | ||
6191 | strcmp(param->u.crypt.alg, "TKIP")) | ||
6192 | goto skip_host_crypt; | ||
6193 | |||
5869 | ops = ieee80211_get_crypto_ops(param->u.crypt.alg); | 6194 | ops = ieee80211_get_crypto_ops(param->u.crypt.alg); |
5870 | if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { | 6195 | if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { |
5871 | request_module("ieee80211_crypt_wep"); | 6196 | request_module("ieee80211_crypt_wep"); |
@@ -5922,25 +6247,27 @@ static int ipw_wpa_set_encryption(struct net_device *dev, | |||
5922 | goto done; | 6247 | goto done; |
5923 | } | 6248 | } |
5924 | 6249 | ||
6250 | skip_host_crypt: | ||
5925 | if (param->u.crypt.set_tx) { | 6251 | if (param->u.crypt.set_tx) { |
5926 | ieee->tx_keyidx = param->u.crypt.idx; | 6252 | ieee->tx_keyidx = param->u.crypt.idx; |
5927 | sec.active_key = param->u.crypt.idx; | 6253 | sec.active_key = param->u.crypt.idx; |
5928 | sec.flags |= SEC_ACTIVE_KEY; | 6254 | sec.flags |= SEC_ACTIVE_KEY; |
5929 | } | 6255 | } else |
6256 | sec.flags &= ~SEC_ACTIVE_KEY; | ||
6257 | |||
6258 | if (param->u.crypt.alg != NULL) { | ||
6259 | memcpy(sec.keys[param->u.crypt.idx], | ||
6260 | param->u.crypt.key, param->u.crypt.key_len); | ||
6261 | sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; | ||
6262 | sec.flags |= (1 << param->u.crypt.idx); | ||
5930 | 6263 | ||
5931 | if (ops->name != NULL) { | 6264 | if (strcmp(param->u.crypt.alg, "WEP") == 0) { |
5932 | if (strcmp(ops->name, "WEP") == 0) { | ||
5933 | memcpy(sec.keys[param->u.crypt.idx], | ||
5934 | param->u.crypt.key, param->u.crypt.key_len); | ||
5935 | sec.key_sizes[param->u.crypt.idx] = | ||
5936 | param->u.crypt.key_len; | ||
5937 | sec.flags |= (1 << param->u.crypt.idx); | ||
5938 | sec.flags |= SEC_LEVEL; | 6265 | sec.flags |= SEC_LEVEL; |
5939 | sec.level = SEC_LEVEL_1; | 6266 | sec.level = SEC_LEVEL_1; |
5940 | } else if (strcmp(ops->name, "TKIP") == 0) { | 6267 | } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { |
5941 | sec.flags |= SEC_LEVEL; | 6268 | sec.flags |= SEC_LEVEL; |
5942 | sec.level = SEC_LEVEL_2; | 6269 | sec.level = SEC_LEVEL_2; |
5943 | } else if (strcmp(ops->name, "CCMP") == 0) { | 6270 | } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { |
5944 | sec.flags |= SEC_LEVEL; | 6271 | sec.flags |= SEC_LEVEL; |
5945 | sec.level = SEC_LEVEL_3; | 6272 | sec.level = SEC_LEVEL_3; |
5946 | } | 6273 | } |
@@ -6017,6 +6344,518 @@ static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p) | |||
6017 | return ret; | 6344 | return ret; |
6018 | } | 6345 | } |
6019 | 6346 | ||
6347 | #ifdef CONFIG_IPW_QOS | ||
6348 | |||
6349 | /* QoS */ | ||
6350 | /* | ||
6351 | * get the modulation type of the current network or | ||
6352 | * the card current mode | ||
6353 | */ | ||
6354 | u8 ipw_qos_current_mode(struct ipw_priv * priv) | ||
6355 | { | ||
6356 | u8 mode = 0; | ||
6357 | |||
6358 | if (priv->status & STATUS_ASSOCIATED) { | ||
6359 | unsigned long flags; | ||
6360 | |||
6361 | spin_lock_irqsave(&priv->ieee->lock, flags); | ||
6362 | mode = priv->assoc_network->mode; | ||
6363 | spin_unlock_irqrestore(&priv->ieee->lock, flags); | ||
6364 | } else { | ||
6365 | mode = priv->ieee->mode; | ||
6366 | } | ||
6367 | IPW_DEBUG_QOS("QoS network/card mode %d \n", mode); | ||
6368 | return mode; | ||
6369 | } | ||
6370 | |||
6371 | /* | ||
6372 | * Handle management frame beacon and probe response | ||
6373 | */ | ||
6374 | static int ipw_qos_handle_probe_reponse(struct ipw_priv *priv, | ||
6375 | int active_network, | ||
6376 | struct ieee80211_network *network) | ||
6377 | { | ||
6378 | u32 size = sizeof(struct ieee80211_qos_parameters); | ||
6379 | |||
6380 | if ((network->capability & WLAN_CAPABILITY_IBSS)) | ||
6381 | network->qos_data.active = network->qos_data.supported; | ||
6382 | |||
6383 | if (network->flags & NETWORK_HAS_QOS_MASK) { | ||
6384 | if (active_network | ||
6385 | && (network->flags & NETWORK_HAS_QOS_PARAMETERS)) | ||
6386 | network->qos_data.active = network->qos_data.supported; | ||
6387 | |||
6388 | if ((network->qos_data.active == 1) && (active_network == 1) && | ||
6389 | (network->flags & NETWORK_HAS_QOS_PARAMETERS) && | ||
6390 | (network->qos_data.old_param_count != | ||
6391 | network->qos_data.param_count)) { | ||
6392 | network->qos_data.old_param_count = | ||
6393 | network->qos_data.param_count; | ||
6394 | schedule_work(&priv->qos_activate); | ||
6395 | IPW_DEBUG_QOS | ||
6396 | ("QoS parameters change call qos_activate\n"); | ||
6397 | } | ||
6398 | } else { | ||
6399 | if ((priv->ieee->mode == IEEE_B) || (network->mode == IEEE_B)) { | ||
6400 | memcpy(&(network->qos_data.parameters), | ||
6401 | &def_parameters_CCK, size); | ||
6402 | } else { | ||
6403 | memcpy(&(network->qos_data.parameters), | ||
6404 | &def_parameters_OFDM, size); | ||
6405 | } | ||
6406 | if ((network->qos_data.active == 1) && (active_network == 1)) { | ||
6407 | IPW_DEBUG_QOS("QoS was disabled call qos_activate \n"); | ||
6408 | schedule_work(&priv->qos_activate); | ||
6409 | } | ||
6410 | |||
6411 | network->qos_data.active = 0; | ||
6412 | network->qos_data.supported = 0; | ||
6413 | } | ||
6414 | if ((priv->status & STATUS_ASSOCIATED) | ||
6415 | && (priv->ieee->iw_mode == IW_MODE_ADHOC) | ||
6416 | && (active_network == 0)) { | ||
6417 | |||
6418 | if (memcmp(network->bssid, priv->bssid, ETH_ALEN)) { | ||
6419 | if ((network->capability & WLAN_CAPABILITY_IBSS) | ||
6420 | && !(network->flags & NETWORK_EMPTY_ESSID)) { | ||
6421 | if ((network->ssid_len == | ||
6422 | priv->assoc_network->ssid_len) | ||
6423 | && !memcmp(network->ssid, | ||
6424 | priv->assoc_network->ssid, | ||
6425 | network->ssid_len)) { | ||
6426 | queue_work(priv->workqueue, | ||
6427 | &priv->merge_networks); | ||
6428 | } | ||
6429 | |||
6430 | } | ||
6431 | } | ||
6432 | } | ||
6433 | |||
6434 | return 0; | ||
6435 | } | ||
6436 | |||
6437 | /* | ||
6438 | * This function set up the firmware to support QoS. It sends | ||
6439 | * IPW_CMD_QOS_PARAMETERS and IPW_CMD_WME_INFO | ||
6440 | */ | ||
6441 | static int ipw_qos_activate(struct ipw_priv *priv, | ||
6442 | struct ieee80211_qos_data *qos_network_data) | ||
6443 | { | ||
6444 | int err; | ||
6445 | struct ieee80211_qos_parameters qos_parameters[QOS_QOS_SETS]; | ||
6446 | struct ieee80211_qos_parameters *active_one = NULL; | ||
6447 | u32 size = sizeof(struct ieee80211_qos_parameters); | ||
6448 | u32 burst_duration; | ||
6449 | int i; | ||
6450 | u8 type; | ||
6451 | |||
6452 | type = ipw_qos_current_mode(priv); | ||
6453 | |||
6454 | active_one = &(qos_parameters[QOS_PARAM_SET_DEF_CCK]); | ||
6455 | memcpy(active_one, priv->qos_data.def_qos_parm_CCK, size); | ||
6456 | active_one = &(qos_parameters[QOS_PARAM_SET_DEF_OFDM]); | ||
6457 | memcpy(active_one, priv->qos_data.def_qos_parm_OFDM, size); | ||
6458 | |||
6459 | if (qos_network_data == NULL) { | ||
6460 | if (type == IEEE_B) { | ||
6461 | IPW_DEBUG_QOS("QoS activate network mode %d\n", type); | ||
6462 | active_one = &def_parameters_CCK; | ||
6463 | } else | ||
6464 | active_one = &def_parameters_OFDM; | ||
6465 | |||
6466 | memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, | ||
6467 | size); | ||
6468 | burst_duration = ipw_qos_get_burst_duration(priv); | ||
6469 | for (i = 0; i < QOS_QUEUE_NUM; i++) | ||
6470 | qos_parameters[QOS_PARAM_SET_ACTIVE]. | ||
6471 | tx_op_limit[i] = (u16) burst_duration; | ||
6472 | } else if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { | ||
6473 | if (type == IEEE_B) { | ||
6474 | IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n", | ||
6475 | type); | ||
6476 | if (priv->qos_data.qos_enable == 0) | ||
6477 | active_one = &def_parameters_CCK; | ||
6478 | else | ||
6479 | active_one = priv->qos_data.def_qos_parm_CCK; | ||
6480 | } else { | ||
6481 | if (priv->qos_data.qos_enable == 0) | ||
6482 | active_one = &def_parameters_OFDM; | ||
6483 | else | ||
6484 | active_one = priv->qos_data.def_qos_parm_OFDM; | ||
6485 | } | ||
6486 | memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, | ||
6487 | size); | ||
6488 | } else { | ||
6489 | unsigned long flags; | ||
6490 | int active; | ||
6491 | |||
6492 | spin_lock_irqsave(&priv->ieee->lock, flags); | ||
6493 | active_one = &(qos_network_data->parameters); | ||
6494 | qos_network_data->old_param_count = | ||
6495 | qos_network_data->param_count; | ||
6496 | memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, | ||
6497 | size); | ||
6498 | active = qos_network_data->supported; | ||
6499 | spin_unlock_irqrestore(&priv->ieee->lock, flags); | ||
6500 | |||
6501 | if (active == 0) { | ||
6502 | burst_duration = ipw_qos_get_burst_duration(priv); | ||
6503 | for (i = 0; i < QOS_QUEUE_NUM; i++) | ||
6504 | qos_parameters[QOS_PARAM_SET_ACTIVE]. | ||
6505 | tx_op_limit[i] = (u16) burst_duration; | ||
6506 | } | ||
6507 | } | ||
6508 | |||
6509 | IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n"); | ||
6510 | err = | ||
6511 | ipw_send_qos_params_command(priv, | ||
6512 | (struct ieee80211_qos_parameters *) | ||
6513 | &(qos_parameters[0])); | ||
6514 | if (err) | ||
6515 | IPW_DEBUG_QOS("QoS IPW_CMD_QOS_PARAMETERS failed\n"); | ||
6516 | |||
6517 | return err; | ||
6518 | } | ||
6519 | |||
6520 | /* | ||
6521 | * send IPW_CMD_WME_INFO to the firmware | ||
6522 | */ | ||
6523 | static int ipw_qos_set_info_element(struct ipw_priv *priv) | ||
6524 | { | ||
6525 | int ret = 0; | ||
6526 | struct ieee80211_qos_information_element qos_info; | ||
6527 | |||
6528 | if (priv == NULL) | ||
6529 | return -1; | ||
6530 | |||
6531 | qos_info.elementID = QOS_ELEMENT_ID; | ||
6532 | qos_info.length = sizeof(struct ieee80211_qos_information_element) - 2; | ||
6533 | |||
6534 | qos_info.version = QOS_VERSION_1; | ||
6535 | qos_info.ac_info = 0; | ||
6536 | |||
6537 | memcpy(qos_info.qui, qos_oui, QOS_OUI_LEN); | ||
6538 | qos_info.qui_type = QOS_OUI_TYPE; | ||
6539 | qos_info.qui_subtype = QOS_OUI_INFO_SUB_TYPE; | ||
6540 | |||
6541 | ret = ipw_send_qos_info_command(priv, &qos_info); | ||
6542 | if (ret != 0) { | ||
6543 | IPW_DEBUG_QOS("QoS error calling ipw_send_qos_info_command\n"); | ||
6544 | } | ||
6545 | return ret; | ||
6546 | } | ||
6547 | |||
6548 | /* | ||
6549 | * Set the QoS parameter with the association request structure | ||
6550 | */ | ||
6551 | static int ipw_qos_association(struct ipw_priv *priv, | ||
6552 | struct ieee80211_network *network) | ||
6553 | { | ||
6554 | int err = 0; | ||
6555 | struct ieee80211_qos_data *qos_data = NULL; | ||
6556 | struct ieee80211_qos_data ibss_data = { | ||
6557 | .supported = 1, | ||
6558 | .active = 1, | ||
6559 | }; | ||
6560 | |||
6561 | switch (priv->ieee->iw_mode) { | ||
6562 | case IW_MODE_ADHOC: | ||
6563 | if (!(network->capability & WLAN_CAPABILITY_IBSS)) | ||
6564 | BUG(); | ||
6565 | |||
6566 | qos_data = &ibss_data; | ||
6567 | break; | ||
6568 | |||
6569 | case IW_MODE_INFRA: | ||
6570 | qos_data = &network->qos_data; | ||
6571 | break; | ||
6572 | |||
6573 | default: | ||
6574 | BUG(); | ||
6575 | break; | ||
6576 | } | ||
6577 | |||
6578 | err = ipw_qos_activate(priv, qos_data); | ||
6579 | if (err) { | ||
6580 | priv->assoc_request.policy_support &= ~HC_QOS_SUPPORT_ASSOC; | ||
6581 | return err; | ||
6582 | } | ||
6583 | |||
6584 | if (priv->qos_data.qos_enable && qos_data->supported) { | ||
6585 | IPW_DEBUG_QOS("QoS will be enabled for this association\n"); | ||
6586 | priv->assoc_request.policy_support |= HC_QOS_SUPPORT_ASSOC; | ||
6587 | return ipw_qos_set_info_element(priv); | ||
6588 | } | ||
6589 | |||
6590 | return 0; | ||
6591 | } | ||
6592 | |||
6593 | /* | ||
6594 | * handling the beaconing responces. if we get different QoS setting | ||
6595 | * of the network from the the associated setting adjust the QoS | ||
6596 | * setting | ||
6597 | */ | ||
6598 | static int ipw_qos_association_resp(struct ipw_priv *priv, | ||
6599 | struct ieee80211_network *network) | ||
6600 | { | ||
6601 | int ret = 0; | ||
6602 | unsigned long flags; | ||
6603 | u32 size = sizeof(struct ieee80211_qos_parameters); | ||
6604 | int set_qos_param = 0; | ||
6605 | |||
6606 | if ((priv == NULL) || (network == NULL) | ||
6607 | || (priv->assoc_network == NULL)) | ||
6608 | |||
6609 | return ret; | ||
6610 | |||
6611 | if (!(priv->status & STATUS_ASSOCIATED)) | ||
6612 | return ret; | ||
6613 | |||
6614 | if ((priv->ieee->iw_mode != IW_MODE_INFRA)) { | ||
6615 | return ret; | ||
6616 | } | ||
6617 | |||
6618 | spin_lock_irqsave(&priv->ieee->lock, flags); | ||
6619 | if (network->flags & NETWORK_HAS_QOS_PARAMETERS) { | ||
6620 | memcpy(&(priv->assoc_network->qos_data), &(network->qos_data), | ||
6621 | sizeof(struct ieee80211_qos_data)); | ||
6622 | priv->assoc_network->qos_data.active = 1; | ||
6623 | if ((network->qos_data.old_param_count != | ||
6624 | network->qos_data.param_count)) { | ||
6625 | set_qos_param = 1; | ||
6626 | network->qos_data.old_param_count = | ||
6627 | network->qos_data.param_count; | ||
6628 | } | ||
6629 | |||
6630 | } else { | ||
6631 | if ((network->mode == IEEE_B) || (priv->ieee->mode == IEEE_B)) { | ||
6632 | memcpy(&(priv->assoc_network->qos_data.parameters), | ||
6633 | &def_parameters_CCK, size); | ||
6634 | } else { | ||
6635 | memcpy(&(priv->assoc_network->qos_data.parameters), | ||
6636 | &def_parameters_OFDM, size); | ||
6637 | } | ||
6638 | priv->assoc_network->qos_data.active = 0; | ||
6639 | priv->assoc_network->qos_data.supported = 0; | ||
6640 | set_qos_param = 1; | ||
6641 | } | ||
6642 | |||
6643 | spin_unlock_irqrestore(&priv->ieee->lock, flags); | ||
6644 | |||
6645 | if (set_qos_param == 1) | ||
6646 | schedule_work(&priv->qos_activate); | ||
6647 | |||
6648 | return ret; | ||
6649 | } | ||
6650 | |||
6651 | static u32 ipw_qos_get_burst_duration(struct ipw_priv *priv) | ||
6652 | { | ||
6653 | u32 ret = 0; | ||
6654 | |||
6655 | if ((priv == NULL)) | ||
6656 | return 0; | ||
6657 | |||
6658 | if (!(priv->ieee->modulation & IEEE80211_OFDM_MODULATION)) { | ||
6659 | ret = priv->qos_data.burst_duration_CCK; | ||
6660 | } else { | ||
6661 | ret = priv->qos_data.burst_duration_OFDM; | ||
6662 | } | ||
6663 | return ret; | ||
6664 | } | ||
6665 | |||
6666 | /* | ||
6667 | * Initialize the setting of QoS global | ||
6668 | */ | ||
6669 | static void ipw_qos_init(struct ipw_priv *priv, int enable, | ||
6670 | int burst_enable, u32 burst_duration_CCK, | ||
6671 | u32 burst_duration_OFDM) | ||
6672 | { | ||
6673 | priv->qos_data.qos_enable = enable; | ||
6674 | |||
6675 | if (priv->qos_data.qos_enable) { | ||
6676 | priv->qos_data.def_qos_parm_CCK = &def_qos_parameters_CCK; | ||
6677 | priv->qos_data.def_qos_parm_OFDM = &def_qos_parameters_OFDM; | ||
6678 | IPW_DEBUG_QOS("QoS is enabled\n"); | ||
6679 | } else { | ||
6680 | priv->qos_data.def_qos_parm_CCK = &def_parameters_CCK; | ||
6681 | priv->qos_data.def_qos_parm_OFDM = &def_parameters_OFDM; | ||
6682 | IPW_DEBUG_QOS("QoS is not enabled\n"); | ||
6683 | } | ||
6684 | |||
6685 | priv->qos_data.burst_enable = burst_enable; | ||
6686 | |||
6687 | if (burst_enable) { | ||
6688 | priv->qos_data.burst_duration_CCK = burst_duration_CCK; | ||
6689 | priv->qos_data.burst_duration_OFDM = burst_duration_OFDM; | ||
6690 | } else { | ||
6691 | priv->qos_data.burst_duration_CCK = 0; | ||
6692 | priv->qos_data.burst_duration_OFDM = 0; | ||
6693 | } | ||
6694 | } | ||
6695 | |||
6696 | /* | ||
6697 | * map the packet priority to the right TX Queue | ||
6698 | */ | ||
6699 | static int ipw_get_tx_queue_number(struct ipw_priv *priv, u16 priority) | ||
6700 | { | ||
6701 | if (priority > 7 || !priv->qos_data.qos_enable) | ||
6702 | priority = 0; | ||
6703 | |||
6704 | return from_priority_to_tx_queue[priority] - 1; | ||
6705 | } | ||
6706 | |||
6707 | /* | ||
6708 | * add QoS parameter to the TX command | ||
6709 | */ | ||
6710 | static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, | ||
6711 | u16 priority, | ||
6712 | struct tfd_data *tfd, u8 unicast) | ||
6713 | { | ||
6714 | int ret = 0; | ||
6715 | int tx_queue_id = 0; | ||
6716 | struct ieee80211_qos_data *qos_data = NULL; | ||
6717 | int active, supported; | ||
6718 | unsigned long flags; | ||
6719 | |||
6720 | if (!(priv->status & STATUS_ASSOCIATED)) | ||
6721 | return 0; | ||
6722 | |||
6723 | qos_data = &priv->assoc_network->qos_data; | ||
6724 | |||
6725 | spin_lock_irqsave(&priv->ieee->lock, flags); | ||
6726 | |||
6727 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) { | ||
6728 | if (unicast == 0) | ||
6729 | qos_data->active = 0; | ||
6730 | else | ||
6731 | qos_data->active = qos_data->supported; | ||
6732 | } | ||
6733 | |||
6734 | active = qos_data->active; | ||
6735 | supported = qos_data->supported; | ||
6736 | |||
6737 | spin_unlock_irqrestore(&priv->ieee->lock, flags); | ||
6738 | |||
6739 | IPW_DEBUG_QOS | ||
6740 | ("QoS %d network is QoS active %d supported %d unicast %d\n", | ||
6741 | priv->qos_data.qos_enable, active, supported, unicast); | ||
6742 | if (active && priv->qos_data.qos_enable) { | ||
6743 | ret = from_priority_to_tx_queue[priority]; | ||
6744 | tx_queue_id = ret - 1; | ||
6745 | IPW_DEBUG_QOS("QoS packet priority is %d \n", priority); | ||
6746 | if (priority <= 7) { | ||
6747 | tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; | ||
6748 | tfd->tfd.tfd_26.mchdr.qos_ctrl = priority; | ||
6749 | tfd->tfd.tfd_26.mchdr.frame_ctl |= | ||
6750 | IEEE80211_STYPE_QOS_DATA; | ||
6751 | |||
6752 | if (priv->qos_data.qos_no_ack_mask & | ||
6753 | (1UL << tx_queue_id)) { | ||
6754 | tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; | ||
6755 | tfd->tfd.tfd_26.mchdr.qos_ctrl |= | ||
6756 | CTRL_QOS_NO_ACK; | ||
6757 | } | ||
6758 | } | ||
6759 | } | ||
6760 | |||
6761 | return ret; | ||
6762 | } | ||
6763 | |||
6764 | /* | ||
6765 | * background support to run QoS activate functionality | ||
6766 | */ | ||
6767 | static void ipw_bg_qos_activate(void *data) | ||
6768 | { | ||
6769 | struct ipw_priv *priv = data; | ||
6770 | |||
6771 | if (priv == NULL) | ||
6772 | return; | ||
6773 | |||
6774 | down(&priv->sem); | ||
6775 | |||
6776 | if (priv->status & STATUS_ASSOCIATED) | ||
6777 | ipw_qos_activate(priv, &(priv->assoc_network->qos_data)); | ||
6778 | |||
6779 | up(&priv->sem); | ||
6780 | } | ||
6781 | |||
6782 | /* | ||
6783 | * Handler for probe responce and beacon frame | ||
6784 | */ | ||
6785 | static int ipw_handle_management_frame(struct net_device *dev, | ||
6786 | struct ieee80211_network *network, | ||
6787 | u16 type) | ||
6788 | { | ||
6789 | struct ipw_priv *priv = ieee80211_priv(dev); | ||
6790 | int active_network; | ||
6791 | |||
6792 | if (priv->status & STATUS_ASSOCIATED && network == priv->assoc_network) | ||
6793 | active_network = 1; | ||
6794 | else | ||
6795 | active_network = 0; | ||
6796 | |||
6797 | switch (type) { | ||
6798 | case IEEE80211_STYPE_PROBE_RESP: | ||
6799 | case IEEE80211_STYPE_BEACON: | ||
6800 | ipw_qos_handle_probe_reponse(priv, active_network, network); | ||
6801 | break; | ||
6802 | case IEEE80211_STYPE_ASSOC_RESP: | ||
6803 | ipw_qos_association_resp(priv, network); | ||
6804 | break; | ||
6805 | default: | ||
6806 | break; | ||
6807 | } | ||
6808 | |||
6809 | return 0; | ||
6810 | } | ||
6811 | |||
6812 | static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters | ||
6813 | *qos_param) | ||
6814 | { | ||
6815 | struct host_cmd cmd = { | ||
6816 | .cmd = IPW_CMD_QOS_PARAMETERS, | ||
6817 | .len = (sizeof(struct ieee80211_qos_parameters) * 3) | ||
6818 | }; | ||
6819 | |||
6820 | if (!priv || !qos_param) { | ||
6821 | IPW_ERROR("Invalid args\n"); | ||
6822 | return -1; | ||
6823 | } | ||
6824 | |||
6825 | memcpy(&cmd.param, qos_param, | ||
6826 | (sizeof(struct ieee80211_qos_parameters) * 3)); | ||
6827 | if (ipw_send_cmd(priv, &cmd)) { | ||
6828 | IPW_ERROR("failed to send IPW_CMD_QOS_PARAMETERS command\n"); | ||
6829 | return -1; | ||
6830 | } | ||
6831 | |||
6832 | return 0; | ||
6833 | } | ||
6834 | |||
6835 | static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element | ||
6836 | *qos_param) | ||
6837 | { | ||
6838 | struct host_cmd cmd = { | ||
6839 | .cmd = IPW_CMD_WME_INFO, | ||
6840 | .len = sizeof(*qos_param) | ||
6841 | }; | ||
6842 | |||
6843 | if (!priv || !qos_param) { | ||
6844 | IPW_ERROR("Invalid args\n"); | ||
6845 | return -1; | ||
6846 | } | ||
6847 | |||
6848 | memcpy(&cmd.param, qos_param, sizeof(*qos_param)); | ||
6849 | if (ipw_send_cmd(priv, &cmd)) { | ||
6850 | IPW_ERROR("failed to send CMD_QOS_INFO command\n"); | ||
6851 | return -1; | ||
6852 | } | ||
6853 | |||
6854 | return 0; | ||
6855 | } | ||
6856 | |||
6857 | #endif /* CONFIG_IPW_QOS */ | ||
6858 | |||
6020 | static int ipw_associate_network(struct ipw_priv *priv, | 6859 | static int ipw_associate_network(struct ipw_priv *priv, |
6021 | struct ieee80211_network *network, | 6860 | struct ieee80211_network *network, |
6022 | struct ipw_supported_rates *rates, int roaming) | 6861 | struct ipw_supported_rates *rates, int roaming) |
@@ -6024,7 +6863,7 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
6024 | int err; | 6863 | int err; |
6025 | 6864 | ||
6026 | if (priv->config & CFG_FIXED_RATE) | 6865 | if (priv->config & CFG_FIXED_RATE) |
6027 | ipw_set_fixed_rate(priv, network); | 6866 | ipw_set_fixed_rate(priv, network->mode); |
6028 | 6867 | ||
6029 | if (!(priv->config & CFG_STATIC_ESSID)) { | 6868 | if (!(priv->config & CFG_STATIC_ESSID)) { |
6030 | priv->essid_len = min(network->ssid_len, | 6869 | priv->essid_len = min(network->ssid_len, |
@@ -6039,15 +6878,17 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
6039 | if ((priv->capability & CAP_PRIVACY_ON) && | 6878 | if ((priv->capability & CAP_PRIVACY_ON) && |
6040 | (priv->capability & CAP_SHARED_KEY)) { | 6879 | (priv->capability & CAP_SHARED_KEY)) { |
6041 | priv->assoc_request.auth_type = AUTH_SHARED_KEY; | 6880 | priv->assoc_request.auth_type = AUTH_SHARED_KEY; |
6042 | priv->assoc_request.auth_key = priv->sec.active_key; | 6881 | priv->assoc_request.auth_key = priv->ieee->sec.active_key; |
6882 | |||
6883 | if ((priv->capability & CAP_PRIVACY_ON) && | ||
6884 | (priv->ieee->sec.level == SEC_LEVEL_1) && | ||
6885 | !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) | ||
6886 | ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); | ||
6043 | } else { | 6887 | } else { |
6044 | priv->assoc_request.auth_type = AUTH_OPEN; | 6888 | priv->assoc_request.auth_type = AUTH_OPEN; |
6045 | priv->assoc_request.auth_key = 0; | 6889 | priv->assoc_request.auth_key = 0; |
6046 | } | 6890 | } |
6047 | 6891 | ||
6048 | if (priv->capability & CAP_PRIVACY_ON) | ||
6049 | ipw_send_wep_keys(priv); | ||
6050 | |||
6051 | if (priv->ieee->wpa_ie_len) { | 6892 | if (priv->ieee->wpa_ie_len) { |
6052 | priv->assoc_request.policy_support = 0x02; /* RSN active */ | 6893 | priv->assoc_request.policy_support = 0x02; /* RSN active */ |
6053 | ipw_set_rsn_capa(priv, priv->ieee->wpa_ie, | 6894 | ipw_set_rsn_capa(priv, priv->ieee->wpa_ie, |
@@ -6095,7 +6936,7 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
6095 | "(open)") : "", | 6936 | "(open)") : "", |
6096 | priv->capability & CAP_PRIVACY_ON ? " key=" : "", | 6937 | priv->capability & CAP_PRIVACY_ON ? " key=" : "", |
6097 | priv->capability & CAP_PRIVACY_ON ? | 6938 | priv->capability & CAP_PRIVACY_ON ? |
6098 | '1' + priv->sec.active_key : '.', | 6939 | '1' + priv->ieee->sec.active_key : '.', |
6099 | priv->capability & CAP_PRIVACY_ON ? '.' : ' '); | 6940 | priv->capability & CAP_PRIVACY_ON ? '.' : ' '); |
6100 | 6941 | ||
6101 | priv->assoc_request.beacon_interval = network->beacon_interval; | 6942 | priv->assoc_request.beacon_interval = network->beacon_interval; |
@@ -6170,6 +7011,10 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
6170 | 7011 | ||
6171 | priv->assoc_network = network; | 7012 | priv->assoc_network = network; |
6172 | 7013 | ||
7014 | #ifdef CONFIG_IPW_QOS | ||
7015 | ipw_qos_association(priv, network); | ||
7016 | #endif | ||
7017 | |||
6173 | err = ipw_send_associate(priv, &priv->assoc_request); | 7018 | err = ipw_send_associate(priv, &priv->assoc_request); |
6174 | if (err) { | 7019 | if (err) { |
6175 | IPW_DEBUG_HC("Attempt to send associate command failed.\n"); | 7020 | IPW_DEBUG_HC("Attempt to send associate command failed.\n"); |
@@ -6268,6 +7113,11 @@ static int ipw_associate(void *data) | |||
6268 | struct list_head *element; | 7113 | struct list_head *element; |
6269 | unsigned long flags; | 7114 | unsigned long flags; |
6270 | 7115 | ||
7116 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | ||
7117 | IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n"); | ||
7118 | return 0; | ||
7119 | } | ||
7120 | |||
6271 | if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { | 7121 | if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { |
6272 | IPW_DEBUG_ASSOC | 7122 | IPW_DEBUG_ASSOC |
6273 | ("Not attempting association (already in progress)\n"); | 7123 | ("Not attempting association (already in progress)\n"); |
@@ -6315,9 +7165,15 @@ static int ipw_associate(void *data) | |||
6315 | if (!network) { | 7165 | if (!network) { |
6316 | ipw_debug_config(priv); | 7166 | ipw_debug_config(priv); |
6317 | 7167 | ||
6318 | if (!(priv->status & STATUS_SCANNING)) | 7168 | if (!(priv->status & STATUS_SCANNING)) { |
6319 | queue_delayed_work(priv->workqueue, &priv->request_scan, | 7169 | if (!(priv->config & CFG_SPEED_SCAN)) |
6320 | SCAN_INTERVAL); | 7170 | queue_delayed_work(priv->workqueue, |
7171 | &priv->request_scan, | ||
7172 | SCAN_INTERVAL); | ||
7173 | else | ||
7174 | queue_work(priv->workqueue, | ||
7175 | &priv->request_scan); | ||
7176 | } | ||
6321 | 7177 | ||
6322 | return 0; | 7178 | return 0; |
6323 | } | 7179 | } |
@@ -6335,9 +7191,48 @@ static void ipw_bg_associate(void *data) | |||
6335 | up(&priv->sem); | 7191 | up(&priv->sem); |
6336 | } | 7192 | } |
6337 | 7193 | ||
6338 | static inline void ipw_handle_data_packet(struct ipw_priv *priv, | 7194 | static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, |
6339 | struct ipw_rx_mem_buffer *rxb, | 7195 | struct sk_buff *skb) |
6340 | struct ieee80211_rx_stats *stats) | 7196 | { |
7197 | struct ieee80211_hdr *hdr; | ||
7198 | u16 fc; | ||
7199 | |||
7200 | hdr = (struct ieee80211_hdr *)skb->data; | ||
7201 | fc = le16_to_cpu(hdr->frame_ctl); | ||
7202 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
7203 | return; | ||
7204 | |||
7205 | fc &= ~IEEE80211_FCTL_PROTECTED; | ||
7206 | hdr->frame_ctl = cpu_to_le16(fc); | ||
7207 | switch (priv->ieee->sec.level) { | ||
7208 | case SEC_LEVEL_3: | ||
7209 | /* Remove CCMP HDR */ | ||
7210 | memmove(skb->data + IEEE80211_3ADDR_LEN, | ||
7211 | skb->data + IEEE80211_3ADDR_LEN + 8, | ||
7212 | skb->len - IEEE80211_3ADDR_LEN - 8); | ||
7213 | skb_trim(skb, skb->len - 8); /* MIC */ | ||
7214 | break; | ||
7215 | case SEC_LEVEL_2: | ||
7216 | break; | ||
7217 | case SEC_LEVEL_1: | ||
7218 | /* Remove IV */ | ||
7219 | memmove(skb->data + IEEE80211_3ADDR_LEN, | ||
7220 | skb->data + IEEE80211_3ADDR_LEN + 4, | ||
7221 | skb->len - IEEE80211_3ADDR_LEN - 4); | ||
7222 | skb_trim(skb, skb->len - 4); /* ICV */ | ||
7223 | break; | ||
7224 | case SEC_LEVEL_0: | ||
7225 | break; | ||
7226 | default: | ||
7227 | printk(KERN_ERR "Unknow security level %d\n", | ||
7228 | priv->ieee->sec.level); | ||
7229 | break; | ||
7230 | } | ||
7231 | } | ||
7232 | |||
7233 | static void ipw_handle_data_packet(struct ipw_priv *priv, | ||
7234 | struct ipw_rx_mem_buffer *rxb, | ||
7235 | struct ieee80211_rx_stats *stats) | ||
6341 | { | 7236 | { |
6342 | struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; | 7237 | struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; |
6343 | 7238 | ||
@@ -6367,11 +7262,15 @@ static inline void ipw_handle_data_packet(struct ipw_priv *priv, | |||
6367 | 7262 | ||
6368 | IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); | 7263 | IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); |
6369 | 7264 | ||
7265 | /* HW decrypt will not clear the WEP bit, MIC, PN, etc. */ | ||
7266 | if (!priv->ieee->host_decrypt) | ||
7267 | ipw_rebuild_decrypted_skb(priv, rxb->skb); | ||
7268 | |||
6370 | if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) | 7269 | if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) |
6371 | priv->ieee->stats.rx_errors++; | 7270 | priv->ieee->stats.rx_errors++; |
6372 | else { /* ieee80211_rx succeeded, so it now owns the SKB */ | 7271 | else { /* ieee80211_rx succeeded, so it now owns the SKB */ |
6373 | rxb->skb = NULL; | 7272 | rxb->skb = NULL; |
6374 | ipw_led_activity_on(priv); | 7273 | __ipw_led_activity_on(priv); |
6375 | } | 7274 | } |
6376 | } | 7275 | } |
6377 | 7276 | ||
@@ -6413,6 +7312,53 @@ static inline int is_network_packet(struct ipw_priv *priv, | |||
6413 | return 1; | 7312 | return 1; |
6414 | } | 7313 | } |
6415 | 7314 | ||
7315 | static void ipw_handle_mgmt_packet(struct ipw_priv *priv, | ||
7316 | struct ipw_rx_mem_buffer *rxb, | ||
7317 | struct ieee80211_rx_stats *stats) | ||
7318 | { | ||
7319 | struct sk_buff *skb = rxb->skb; | ||
7320 | struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)skb->data; | ||
7321 | struct ieee80211_hdr_4addr *header = (struct ieee80211_hdr_4addr *) | ||
7322 | (skb->data + IPW_RX_FRAME_SIZE); | ||
7323 | |||
7324 | ieee80211_rx_mgt(priv->ieee, header, stats); | ||
7325 | |||
7326 | if (priv->ieee->iw_mode == IW_MODE_ADHOC && | ||
7327 | ((WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) == | ||
7328 | IEEE80211_STYPE_PROBE_RESP) || | ||
7329 | (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) == | ||
7330 | IEEE80211_STYPE_BEACON))) { | ||
7331 | if (!memcmp(header->addr3, priv->bssid, ETH_ALEN)) | ||
7332 | ipw_add_station(priv, header->addr2); | ||
7333 | } | ||
7334 | |||
7335 | if (priv->config & CFG_NET_STATS) { | ||
7336 | IPW_DEBUG_HC("sending stat packet\n"); | ||
7337 | |||
7338 | /* Set the size of the skb to the size of the full | ||
7339 | * ipw header and 802.11 frame */ | ||
7340 | skb_put(skb, le16_to_cpu(pkt->u.frame.length) + | ||
7341 | IPW_RX_FRAME_SIZE); | ||
7342 | |||
7343 | /* Advance past the ipw packet header to the 802.11 frame */ | ||
7344 | skb_pull(skb, IPW_RX_FRAME_SIZE); | ||
7345 | |||
7346 | /* Push the ieee80211_rx_stats before the 802.11 frame */ | ||
7347 | memcpy(skb_push(skb, sizeof(*stats)), stats, sizeof(*stats)); | ||
7348 | |||
7349 | skb->dev = priv->ieee->dev; | ||
7350 | |||
7351 | /* Point raw at the ieee80211_stats */ | ||
7352 | skb->mac.raw = skb->data; | ||
7353 | |||
7354 | skb->pkt_type = PACKET_OTHERHOST; | ||
7355 | skb->protocol = __constant_htons(ETH_P_80211_STATS); | ||
7356 | memset(skb->cb, 0, sizeof(rxb->skb->cb)); | ||
7357 | netif_rx(skb); | ||
7358 | rxb->skb = NULL; | ||
7359 | } | ||
7360 | } | ||
7361 | |||
6416 | /* | 7362 | /* |
6417 | * Main entry function for recieving a packet with 80211 headers. This | 7363 | * Main entry function for recieving a packet with 80211 headers. This |
6418 | * should be called when ever the FW has notified us that there is a new | 7364 | * should be called when ever the FW has notified us that there is a new |
@@ -6426,8 +7372,8 @@ static void ipw_rx(struct ipw_priv *priv) | |||
6426 | u32 r, w, i; | 7372 | u32 r, w, i; |
6427 | u8 network_packet; | 7373 | u8 network_packet; |
6428 | 7374 | ||
6429 | r = ipw_read32(priv, CX2_RX_READ_INDEX); | 7375 | r = ipw_read32(priv, IPW_RX_READ_INDEX); |
6430 | w = ipw_read32(priv, CX2_RX_WRITE_INDEX); | 7376 | w = ipw_read32(priv, IPW_RX_WRITE_INDEX); |
6431 | i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE; | 7377 | i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE; |
6432 | 7378 | ||
6433 | while (i != r) { | 7379 | while (i != r) { |
@@ -6441,7 +7387,7 @@ static void ipw_rx(struct ipw_priv *priv) | |||
6441 | priv->rxq->queue[i] = NULL; | 7387 | priv->rxq->queue[i] = NULL; |
6442 | 7388 | ||
6443 | pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, | 7389 | pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, |
6444 | CX2_RX_BUF_SIZE, | 7390 | IPW_RX_BUF_SIZE, |
6445 | PCI_DMA_FROMDEVICE); | 7391 | PCI_DMA_FROMDEVICE); |
6446 | 7392 | ||
6447 | pkt = (struct ipw_rx_packet *)rxb->skb->data; | 7393 | pkt = (struct ipw_rx_packet *)rxb->skb->data; |
@@ -6482,7 +7428,7 @@ static void ipw_rx(struct ipw_priv *priv) | |||
6482 | 7428 | ||
6483 | priv->rx_packets++; | 7429 | priv->rx_packets++; |
6484 | 7430 | ||
6485 | #ifdef CONFIG_IPW_MONITOR | 7431 | #ifdef CONFIG_IPW2200_MONITOR |
6486 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | 7432 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { |
6487 | ipw_handle_data_packet(priv, rxb, | 7433 | ipw_handle_data_packet(priv, rxb, |
6488 | &stats); | 7434 | &stats); |
@@ -6525,56 +7471,17 @@ static void ipw_rx(struct ipw_priv *priv) | |||
6525 | 7471 | ||
6526 | switch (WLAN_FC_GET_TYPE | 7472 | switch (WLAN_FC_GET_TYPE |
6527 | (le16_to_cpu(header->frame_ctl))) { | 7473 | (le16_to_cpu(header->frame_ctl))) { |
7474 | |||
6528 | case IEEE80211_FTYPE_MGMT: | 7475 | case IEEE80211_FTYPE_MGMT: |
6529 | ieee80211_rx_mgt(priv->ieee, header, | 7476 | ipw_handle_mgmt_packet(priv, rxb, |
6530 | &stats); | 7477 | &stats); |
6531 | if (priv->ieee->iw_mode == IW_MODE_ADHOC | ||
6532 | && | ||
6533 | ((WLAN_FC_GET_STYPE | ||
6534 | (le16_to_cpu(header->frame_ctl)) | ||
6535 | == IEEE80211_STYPE_PROBE_RESP) | ||
6536 | || | ||
6537 | (WLAN_FC_GET_STYPE | ||
6538 | (le16_to_cpu(header->frame_ctl)) | ||
6539 | == IEEE80211_STYPE_BEACON))) { | ||
6540 | if (!memcmp | ||
6541 | (header->addr3, priv->bssid, | ||
6542 | ETH_ALEN)) | ||
6543 | ipw_add_station(priv, | ||
6544 | header-> | ||
6545 | addr2); | ||
6546 | else { | ||
6547 | struct | ||
6548 | ieee80211_probe_response | ||
6549 | *beacon; | ||
6550 | beacon = | ||
6551 | (struct | ||
6552 | ieee80211_probe_response | ||
6553 | *)header; | ||
6554 | if (le16_to_cpu | ||
6555 | (beacon-> | ||
6556 | capability) & | ||
6557 | WLAN_CAPABILITY_IBSS) | ||
6558 | { | ||
6559 | queue_work | ||
6560 | (priv-> | ||
6561 | workqueue, | ||
6562 | &priv-> | ||
6563 | merge_networks); | ||
6564 | } | ||
6565 | } | ||
6566 | } | ||
6567 | break; | 7478 | break; |
6568 | 7479 | ||
6569 | case IEEE80211_FTYPE_CTL: | 7480 | case IEEE80211_FTYPE_CTL: |
6570 | break; | 7481 | break; |
6571 | 7482 | ||
6572 | case IEEE80211_FTYPE_DATA: | 7483 | case IEEE80211_FTYPE_DATA: |
6573 | if (network_packet) | 7484 | if (unlikely(!network_packet)) { |
6574 | ipw_handle_data_packet(priv, | ||
6575 | rxb, | ||
6576 | &stats); | ||
6577 | else | ||
6578 | IPW_DEBUG_DROP("Dropping: " | 7485 | IPW_DEBUG_DROP("Dropping: " |
6579 | MAC_FMT ", " | 7486 | MAC_FMT ", " |
6580 | MAC_FMT ", " | 7487 | MAC_FMT ", " |
@@ -6585,6 +7492,12 @@ static void ipw_rx(struct ipw_priv *priv) | |||
6585 | addr2), | 7492 | addr2), |
6586 | MAC_ARG(header-> | 7493 | MAC_ARG(header-> |
6587 | addr3)); | 7494 | addr3)); |
7495 | break; | ||
7496 | } | ||
7497 | |||
7498 | ipw_handle_data_packet(priv, rxb, | ||
7499 | &stats); | ||
7500 | |||
6588 | break; | 7501 | break; |
6589 | } | 7502 | } |
6590 | break; | 7503 | break; |
@@ -6615,7 +7528,7 @@ static void ipw_rx(struct ipw_priv *priv) | |||
6615 | } | 7528 | } |
6616 | 7529 | ||
6617 | pci_unmap_single(priv->pci_dev, rxb->dma_addr, | 7530 | pci_unmap_single(priv->pci_dev, rxb->dma_addr, |
6618 | CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); | 7531 | IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); |
6619 | list_add_tail(&rxb->list, &priv->rxq->rx_used); | 7532 | list_add_tail(&rxb->list, &priv->rxq->rx_used); |
6620 | 7533 | ||
6621 | i = (i + 1) % RX_QUEUE_SIZE; | 7534 | i = (i + 1) % RX_QUEUE_SIZE; |
@@ -6657,6 +7570,8 @@ static int ipw_wx_get_name(struct net_device *dev, | |||
6657 | 7570 | ||
6658 | static int ipw_set_channel(struct ipw_priv *priv, u8 channel) | 7571 | static int ipw_set_channel(struct ipw_priv *priv, u8 channel) |
6659 | { | 7572 | { |
7573 | int i; | ||
7574 | |||
6660 | if (channel == 0) { | 7575 | if (channel == 0) { |
6661 | IPW_DEBUG_INFO("Setting channel to ANY (0)\n"); | 7576 | IPW_DEBUG_INFO("Setting channel to ANY (0)\n"); |
6662 | priv->config &= ~CFG_STATIC_CHANNEL; | 7577 | priv->config &= ~CFG_STATIC_CHANNEL; |
@@ -6677,6 +7592,27 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel) | |||
6677 | IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel); | 7592 | IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel); |
6678 | priv->channel = channel; | 7593 | priv->channel = channel; |
6679 | 7594 | ||
7595 | #ifdef CONFIG_IPW2200_MONITOR | ||
7596 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | ||
7597 | if (priv->status & STATUS_SCANNING) { | ||
7598 | IPW_DEBUG_SCAN("scan abort triggered due to " | ||
7599 | "channel change.\n"); | ||
7600 | queue_work(priv->workqueue, &priv->abort_scan); | ||
7601 | } | ||
7602 | |||
7603 | for (i = 1000; i && (priv->status & STATUS_SCANNING); i--) | ||
7604 | udelay(10); | ||
7605 | |||
7606 | if (priv->status & STATUS_SCANNING) | ||
7607 | IPW_DEBUG_SCAN("Still scanning...\n"); | ||
7608 | else | ||
7609 | IPW_DEBUG_SCAN("Took %dms to abort current scan\n", | ||
7610 | 1000 - i); | ||
7611 | |||
7612 | return 0; | ||
7613 | } | ||
7614 | #endif /* CONFIG_IPW2200_MONITOR */ | ||
7615 | |||
6680 | /* Network configuration changed -- force [re]association */ | 7616 | /* Network configuration changed -- force [re]association */ |
6681 | IPW_DEBUG_ASSOC("[re]association triggered due to channel change.\n"); | 7617 | IPW_DEBUG_ASSOC("[re]association triggered due to channel change.\n"); |
6682 | if (!ipw_disassociate(priv)) | 7618 | if (!ipw_disassociate(priv)) |
@@ -6692,29 +7628,30 @@ static int ipw_wx_set_freq(struct net_device *dev, | |||
6692 | struct ipw_priv *priv = ieee80211_priv(dev); | 7628 | struct ipw_priv *priv = ieee80211_priv(dev); |
6693 | struct iw_freq *fwrq = &wrqu->freq; | 7629 | struct iw_freq *fwrq = &wrqu->freq; |
6694 | int ret = 0; | 7630 | int ret = 0; |
7631 | u8 channel; | ||
7632 | |||
7633 | if (fwrq->m == 0) { | ||
7634 | IPW_DEBUG_WX("SET Freq/Channel -> any\n"); | ||
7635 | down(&priv->sem); | ||
7636 | ret = ipw_set_channel(priv, 0); | ||
7637 | up(&priv->sem); | ||
7638 | return ret; | ||
7639 | } | ||
6695 | 7640 | ||
6696 | /* if setting by freq convert to channel */ | 7641 | /* if setting by freq convert to channel */ |
6697 | if (fwrq->e == 1) { | 7642 | if (fwrq->e == 1) { |
6698 | if ((fwrq->m >= (int)2.412e8 && fwrq->m <= (int)2.487e8)) { | 7643 | channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m); |
6699 | int f = fwrq->m / 100000; | 7644 | if (channel == 0) |
6700 | int c = 0; | 7645 | return -EINVAL; |
6701 | 7646 | } else | |
6702 | while ((c < REG_MAX_CHANNEL) && | 7647 | channel = fwrq->m; |
6703 | (f != ipw_frequencies[c])) | ||
6704 | c++; | ||
6705 | |||
6706 | /* hack to fall through */ | ||
6707 | fwrq->e = 0; | ||
6708 | fwrq->m = c + 1; | ||
6709 | } | ||
6710 | } | ||
6711 | 7648 | ||
6712 | if (fwrq->e > 0 || fwrq->m > 1000) | 7649 | if (!ieee80211_is_valid_channel(priv->ieee, channel)) |
6713 | return -EOPNOTSUPP; | 7650 | return -EINVAL; |
6714 | 7651 | ||
6715 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); | 7652 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); |
6716 | down(&priv->sem); | 7653 | down(&priv->sem); |
6717 | ret = ipw_set_channel(priv, (u8) fwrq->m); | 7654 | ret = ipw_set_channel(priv, channel); |
6718 | up(&priv->sem); | 7655 | up(&priv->sem); |
6719 | return ret; | 7656 | return ret; |
6720 | } | 7657 | } |
@@ -6749,14 +7686,9 @@ static int ipw_wx_set_mode(struct net_device *dev, | |||
6749 | int err = 0; | 7686 | int err = 0; |
6750 | 7687 | ||
6751 | IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode); | 7688 | IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode); |
6752 | down(&priv->sem); | ||
6753 | if (wrqu->mode == priv->ieee->iw_mode) { | ||
6754 | up(&priv->sem); | ||
6755 | return 0; | ||
6756 | } | ||
6757 | 7689 | ||
6758 | switch (wrqu->mode) { | 7690 | switch (wrqu->mode) { |
6759 | #ifdef CONFIG_IPW_MONITOR | 7691 | #ifdef CONFIG_IPW2200_MONITOR |
6760 | case IW_MODE_MONITOR: | 7692 | case IW_MODE_MONITOR: |
6761 | #endif | 7693 | #endif |
6762 | case IW_MODE_ADHOC: | 7694 | case IW_MODE_ADHOC: |
@@ -6766,17 +7698,19 @@ static int ipw_wx_set_mode(struct net_device *dev, | |||
6766 | wrqu->mode = IW_MODE_INFRA; | 7698 | wrqu->mode = IW_MODE_INFRA; |
6767 | break; | 7699 | break; |
6768 | default: | 7700 | default: |
6769 | up(&priv->sem); | ||
6770 | return -EINVAL; | 7701 | return -EINVAL; |
6771 | } | 7702 | } |
7703 | if (wrqu->mode == priv->ieee->iw_mode) | ||
7704 | return 0; | ||
6772 | 7705 | ||
6773 | #ifdef CONFIG_IPW_MONITOR | 7706 | down(&priv->sem); |
7707 | #ifdef CONFIG_IPW2200_MONITOR | ||
6774 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) | 7708 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) |
6775 | priv->net_dev->type = ARPHRD_ETHER; | 7709 | priv->net_dev->type = ARPHRD_ETHER; |
6776 | 7710 | ||
6777 | if (wrqu->mode == IW_MODE_MONITOR) | 7711 | if (wrqu->mode == IW_MODE_MONITOR) |
6778 | priv->net_dev->type = ARPHRD_IEEE80211; | 7712 | priv->net_dev->type = ARPHRD_IEEE80211; |
6779 | #endif /* CONFIG_IPW_MONITOR */ | 7713 | #endif /* CONFIG_IPW2200_MONITOR */ |
6780 | 7714 | ||
6781 | #ifdef CONFIG_PM | 7715 | #ifdef CONFIG_PM |
6782 | /* Free the existing firmware and reset the fw_loaded | 7716 | /* Free the existing firmware and reset the fw_loaded |
@@ -6839,8 +7773,8 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
6839 | { | 7773 | { |
6840 | struct ipw_priv *priv = ieee80211_priv(dev); | 7774 | struct ipw_priv *priv = ieee80211_priv(dev); |
6841 | struct iw_range *range = (struct iw_range *)extra; | 7775 | struct iw_range *range = (struct iw_range *)extra; |
6842 | u16 val; | 7776 | const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); |
6843 | int i; | 7777 | int i = 0, j; |
6844 | 7778 | ||
6845 | wrqu->data.length = sizeof(*range); | 7779 | wrqu->data.length = sizeof(*range); |
6846 | memset(range, 0, sizeof(*range)); | 7780 | memset(range, 0, sizeof(*range)); |
@@ -6879,19 +7813,28 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
6879 | range->we_version_compiled = WIRELESS_EXT; | 7813 | range->we_version_compiled = WIRELESS_EXT; |
6880 | range->we_version_source = 16; | 7814 | range->we_version_source = 16; |
6881 | 7815 | ||
6882 | range->num_channels = FREQ_COUNT; | 7816 | i = 0; |
6883 | 7817 | if (priv->ieee->mode & (IEEE_B | IEEE_G)) { | |
6884 | val = 0; | 7818 | for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; |
6885 | for (i = 0; i < FREQ_COUNT; i++) { | 7819 | i++, j++) { |
6886 | range->freq[val].i = i + 1; | 7820 | range->freq[i].i = geo->bg[j].channel; |
6887 | range->freq[val].m = ipw_frequencies[i] * 100000; | 7821 | range->freq[i].m = geo->bg[j].freq * 100000; |
6888 | range->freq[val].e = 1; | 7822 | range->freq[i].e = 1; |
6889 | val++; | 7823 | } |
7824 | } | ||
6890 | 7825 | ||
6891 | if (val == IW_MAX_FREQUENCIES) | 7826 | if (priv->ieee->mode & IEEE_A) { |
6892 | break; | 7827 | for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; |
7828 | i++, j++) { | ||
7829 | range->freq[i].i = geo->a[j].channel; | ||
7830 | range->freq[i].m = geo->a[j].freq * 100000; | ||
7831 | range->freq[i].e = 1; | ||
7832 | } | ||
6893 | } | 7833 | } |
6894 | range->num_frequency = val; | 7834 | |
7835 | range->num_channels = i; | ||
7836 | range->num_frequency = i; | ||
7837 | |||
6895 | up(&priv->sem); | 7838 | up(&priv->sem); |
6896 | IPW_DEBUG_WX("GET Range\n"); | 7839 | IPW_DEBUG_WX("GET Range\n"); |
6897 | return 0; | 7840 | return 0; |
@@ -7164,9 +8107,10 @@ static int ipw_wx_set_rate(struct net_device *dev, | |||
7164 | IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", | 8107 | IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", |
7165 | mask, fixed ? "fixed" : "sub-rates"); | 8108 | mask, fixed ? "fixed" : "sub-rates"); |
7166 | down(&priv->sem); | 8109 | down(&priv->sem); |
7167 | if (mask == IEEE80211_DEFAULT_RATES_MASK) | 8110 | if (mask == IEEE80211_DEFAULT_RATES_MASK) { |
7168 | priv->config &= ~CFG_FIXED_RATE; | 8111 | priv->config &= ~CFG_FIXED_RATE; |
7169 | else | 8112 | ipw_set_fixed_rate(priv, priv->ieee->mode); |
8113 | } else | ||
7170 | priv->config |= CFG_FIXED_RATE; | 8114 | priv->config |= CFG_FIXED_RATE; |
7171 | 8115 | ||
7172 | if (priv->rates_mask == mask) { | 8116 | if (priv->rates_mask == mask) { |
@@ -7242,18 +8186,23 @@ static int ipw_wx_set_txpow(struct net_device *dev, | |||
7242 | struct ipw_priv *priv = ieee80211_priv(dev); | 8186 | struct ipw_priv *priv = ieee80211_priv(dev); |
7243 | struct ipw_tx_power tx_power; | 8187 | struct ipw_tx_power tx_power; |
7244 | int i; | 8188 | int i; |
8189 | |||
7245 | down(&priv->sem); | 8190 | down(&priv->sem); |
7246 | if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { | 8191 | if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { |
7247 | up(&priv->sem); | 8192 | up(&priv->sem); |
7248 | return -EINPROGRESS; | 8193 | return -EINPROGRESS; |
7249 | } | 8194 | } |
7250 | 8195 | ||
8196 | if (!wrqu->power.fixed) | ||
8197 | wrqu->power.value = IPW_TX_POWER_DEFAULT; | ||
8198 | |||
7251 | if (wrqu->power.flags != IW_TXPOW_DBM) { | 8199 | if (wrqu->power.flags != IW_TXPOW_DBM) { |
7252 | up(&priv->sem); | 8200 | up(&priv->sem); |
7253 | return -EINVAL; | 8201 | return -EINVAL; |
7254 | } | 8202 | } |
7255 | 8203 | ||
7256 | if ((wrqu->power.value > 20) || (wrqu->power.value < -12)) { | 8204 | if ((wrqu->power.value > IPW_TX_POWER_MAX) || |
8205 | (wrqu->power.value < -IPW_TX_POWER_MAX) || !wrqu->power.fixed) { | ||
7257 | up(&priv->sem); | 8206 | up(&priv->sem); |
7258 | return -EINVAL; | 8207 | return -EINVAL; |
7259 | } | 8208 | } |
@@ -7313,8 +8262,10 @@ static int ipw_wx_set_frag(struct net_device *dev, | |||
7313 | priv->ieee->fts = DEFAULT_FTS; | 8262 | priv->ieee->fts = DEFAULT_FTS; |
7314 | else { | 8263 | else { |
7315 | if (wrqu->frag.value < MIN_FRAG_THRESHOLD || | 8264 | if (wrqu->frag.value < MIN_FRAG_THRESHOLD || |
7316 | wrqu->frag.value > MAX_FRAG_THRESHOLD) | 8265 | wrqu->frag.value > MAX_FRAG_THRESHOLD) { |
8266 | up(&priv->sem); | ||
7317 | return -EINVAL; | 8267 | return -EINVAL; |
8268 | } | ||
7318 | 8269 | ||
7319 | priv->ieee->fts = wrqu->frag.value & ~0x1; | 8270 | priv->ieee->fts = wrqu->frag.value & ~0x1; |
7320 | } | 8271 | } |
@@ -7362,12 +8313,9 @@ static int ipw_wx_set_scan(struct net_device *dev, | |||
7362 | { | 8313 | { |
7363 | struct ipw_priv *priv = ieee80211_priv(dev); | 8314 | struct ipw_priv *priv = ieee80211_priv(dev); |
7364 | IPW_DEBUG_WX("Start scan\n"); | 8315 | IPW_DEBUG_WX("Start scan\n"); |
7365 | down(&priv->sem); | 8316 | |
7366 | if (ipw_request_scan(priv)) { | 8317 | queue_work(priv->workqueue, &priv->request_scan); |
7367 | up(&priv->sem); | 8318 | |
7368 | return -EIO; | ||
7369 | } | ||
7370 | up(&priv->sem); | ||
7371 | return 0; | 8319 | return 0; |
7372 | } | 8320 | } |
7373 | 8321 | ||
@@ -7676,7 +8624,7 @@ static int ipw_wx_get_preamble(struct net_device *dev, | |||
7676 | return 0; | 8624 | return 0; |
7677 | } | 8625 | } |
7678 | 8626 | ||
7679 | #ifdef CONFIG_IPW_MONITOR | 8627 | #ifdef CONFIG_IPW2200_MONITOR |
7680 | static int ipw_wx_set_monitor(struct net_device *dev, | 8628 | static int ipw_wx_set_monitor(struct net_device *dev, |
7681 | struct iw_request_info *info, | 8629 | struct iw_request_info *info, |
7682 | union iwreq_data *wrqu, char *extra) | 8630 | union iwreq_data *wrqu, char *extra) |
@@ -7705,6 +8653,8 @@ static int ipw_wx_set_monitor(struct net_device *dev, | |||
7705 | return 0; | 8653 | return 0; |
7706 | } | 8654 | } |
7707 | 8655 | ||
8656 | #endif // CONFIG_IPW2200_MONITOR | ||
8657 | |||
7708 | static int ipw_wx_reset(struct net_device *dev, | 8658 | static int ipw_wx_reset(struct net_device *dev, |
7709 | struct iw_request_info *info, | 8659 | struct iw_request_info *info, |
7710 | union iwreq_data *wrqu, char *extra) | 8660 | union iwreq_data *wrqu, char *extra) |
@@ -7714,7 +8664,148 @@ static int ipw_wx_reset(struct net_device *dev, | |||
7714 | queue_work(priv->workqueue, &priv->adapter_restart); | 8664 | queue_work(priv->workqueue, &priv->adapter_restart); |
7715 | return 0; | 8665 | return 0; |
7716 | } | 8666 | } |
7717 | #endif // CONFIG_IPW_MONITOR | 8667 | |
8668 | static void ipw_sw_reset(struct ipw_priv *priv, int init) | ||
8669 | { | ||
8670 | int band, modulation; | ||
8671 | |||
8672 | /* Initialize module parameter values here */ | ||
8673 | priv->config = 0; | ||
8674 | |||
8675 | /* We default to disabling the LED code as right now it causes | ||
8676 | * too many systems to lock up... */ | ||
8677 | if (!led) | ||
8678 | priv->config |= CFG_NO_LED; | ||
8679 | |||
8680 | if (associate) | ||
8681 | priv->config |= CFG_ASSOCIATE; | ||
8682 | else | ||
8683 | IPW_DEBUG_INFO("Auto associate disabled.\n"); | ||
8684 | |||
8685 | if (auto_create) | ||
8686 | priv->config |= CFG_ADHOC_CREATE; | ||
8687 | else | ||
8688 | IPW_DEBUG_INFO("Auto adhoc creation disabled.\n"); | ||
8689 | |||
8690 | if (disable) { | ||
8691 | priv->status |= STATUS_RF_KILL_SW; | ||
8692 | IPW_DEBUG_INFO("Radio disabled.\n"); | ||
8693 | } | ||
8694 | |||
8695 | if (channel != 0) { | ||
8696 | priv->config |= CFG_STATIC_CHANNEL; | ||
8697 | priv->channel = channel; | ||
8698 | IPW_DEBUG_INFO("Bind to static channel %d\n", channel); | ||
8699 | /* TODO: Validate that provided channel is in range */ | ||
8700 | } | ||
8701 | #ifdef CONFIG_IPW_QOS | ||
8702 | ipw_qos_init(priv, qos_enable, qos_burst_enable, | ||
8703 | burst_duration_CCK, burst_duration_OFDM); | ||
8704 | #endif /* CONFIG_IPW_QOS */ | ||
8705 | |||
8706 | switch (mode) { | ||
8707 | case 1: | ||
8708 | priv->ieee->iw_mode = IW_MODE_ADHOC; | ||
8709 | priv->net_dev->type = ARPHRD_ETHER; | ||
8710 | |||
8711 | break; | ||
8712 | #ifdef CONFIG_IPW2200_MONITOR | ||
8713 | case 2: | ||
8714 | priv->ieee->iw_mode = IW_MODE_MONITOR; | ||
8715 | priv->net_dev->type = ARPHRD_IEEE80211; | ||
8716 | break; | ||
8717 | #endif | ||
8718 | default: | ||
8719 | case 0: | ||
8720 | priv->net_dev->type = ARPHRD_ETHER; | ||
8721 | priv->ieee->iw_mode = IW_MODE_INFRA; | ||
8722 | break; | ||
8723 | } | ||
8724 | |||
8725 | if (hwcrypto) { | ||
8726 | priv->ieee->host_encrypt = 0; | ||
8727 | priv->ieee->host_decrypt = 0; | ||
8728 | } | ||
8729 | IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); | ||
8730 | |||
8731 | if ((priv->pci_dev->device == 0x4223) || | ||
8732 | (priv->pci_dev->device == 0x4224)) { | ||
8733 | if (init) | ||
8734 | printk(KERN_INFO DRV_NAME | ||
8735 | ": Detected Intel PRO/Wireless 2915ABG Network " | ||
8736 | "Connection\n"); | ||
8737 | priv->ieee->abg_true = 1; | ||
8738 | band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND; | ||
8739 | modulation = IEEE80211_OFDM_MODULATION | | ||
8740 | IEEE80211_CCK_MODULATION; | ||
8741 | priv->adapter = IPW_2915ABG; | ||
8742 | priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; | ||
8743 | } else { | ||
8744 | if (init) | ||
8745 | printk(KERN_INFO DRV_NAME | ||
8746 | ": Detected Intel PRO/Wireless 2200BG Network " | ||
8747 | "Connection\n"); | ||
8748 | |||
8749 | priv->ieee->abg_true = 0; | ||
8750 | band = IEEE80211_24GHZ_BAND; | ||
8751 | modulation = IEEE80211_OFDM_MODULATION | | ||
8752 | IEEE80211_CCK_MODULATION; | ||
8753 | priv->adapter = IPW_2200BG; | ||
8754 | priv->ieee->mode = IEEE_G | IEEE_B; | ||
8755 | } | ||
8756 | |||
8757 | priv->ieee->freq_band = band; | ||
8758 | priv->ieee->modulation = modulation; | ||
8759 | |||
8760 | priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK; | ||
8761 | |||
8762 | priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; | ||
8763 | priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; | ||
8764 | |||
8765 | priv->rts_threshold = DEFAULT_RTS_THRESHOLD; | ||
8766 | |||
8767 | /* If power management is turned on, default to AC mode */ | ||
8768 | priv->power_mode = IPW_POWER_AC; | ||
8769 | priv->tx_power = IPW_TX_POWER_DEFAULT; | ||
8770 | } | ||
8771 | |||
8772 | static int ipw_wx_sw_reset(struct net_device *dev, | ||
8773 | struct iw_request_info *info, | ||
8774 | union iwreq_data *wrqu, char *extra) | ||
8775 | { | ||
8776 | struct ipw_priv *priv = ieee80211_priv(dev); | ||
8777 | union iwreq_data wrqu_sec = { | ||
8778 | .encoding = { | ||
8779 | .flags = IW_ENCODE_DISABLED, | ||
8780 | }, | ||
8781 | }; | ||
8782 | |||
8783 | IPW_DEBUG_WX("SW_RESET\n"); | ||
8784 | |||
8785 | down(&priv->sem); | ||
8786 | |||
8787 | ipw_sw_reset(priv, 0); | ||
8788 | |||
8789 | /* The SW reset bit might have been toggled on by the 'disable' | ||
8790 | * module parameter, so take appropriate action */ | ||
8791 | ipw_radio_kill_sw(priv, priv->status & STATUS_RF_KILL_SW); | ||
8792 | |||
8793 | up(&priv->sem); | ||
8794 | ieee80211_wx_set_encode(priv->ieee, info, &wrqu_sec, NULL); | ||
8795 | down(&priv->sem); | ||
8796 | |||
8797 | if (!(priv->status & STATUS_RF_KILL_MASK)) { | ||
8798 | /* Configuration likely changed -- force [re]association */ | ||
8799 | IPW_DEBUG_ASSOC("[re]association triggered due to sw " | ||
8800 | "reset.\n"); | ||
8801 | if (!ipw_disassociate(priv)) | ||
8802 | ipw_associate(priv); | ||
8803 | } | ||
8804 | |||
8805 | up(&priv->sem); | ||
8806 | |||
8807 | return 0; | ||
8808 | } | ||
7718 | 8809 | ||
7719 | /* Rebase the WE IOCTLs to zero for the handler array */ | 8810 | /* Rebase the WE IOCTLs to zero for the handler array */ |
7720 | #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] | 8811 | #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] |
@@ -7753,14 +8844,19 @@ static iw_handler ipw_wx_handlers[] = { | |||
7753 | IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, | 8844 | IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, |
7754 | }; | 8845 | }; |
7755 | 8846 | ||
7756 | #define IPW_PRIV_SET_POWER SIOCIWFIRSTPRIV | 8847 | enum { |
7757 | #define IPW_PRIV_GET_POWER SIOCIWFIRSTPRIV+1 | 8848 | IPW_PRIV_SET_POWER = SIOCIWFIRSTPRIV, |
7758 | #define IPW_PRIV_SET_MODE SIOCIWFIRSTPRIV+2 | 8849 | IPW_PRIV_GET_POWER, |
7759 | #define IPW_PRIV_GET_MODE SIOCIWFIRSTPRIV+3 | 8850 | IPW_PRIV_SET_MODE, |
7760 | #define IPW_PRIV_SET_PREAMBLE SIOCIWFIRSTPRIV+4 | 8851 | IPW_PRIV_GET_MODE, |
7761 | #define IPW_PRIV_GET_PREAMBLE SIOCIWFIRSTPRIV+5 | 8852 | IPW_PRIV_SET_PREAMBLE, |
7762 | #define IPW_PRIV_SET_MONITOR SIOCIWFIRSTPRIV+6 | 8853 | IPW_PRIV_GET_PREAMBLE, |
7763 | #define IPW_PRIV_RESET SIOCIWFIRSTPRIV+7 | 8854 | IPW_PRIV_RESET, |
8855 | IPW_PRIV_SW_RESET, | ||
8856 | #ifdef CONFIG_IPW2200_MONITOR | ||
8857 | IPW_PRIV_SET_MONITOR, | ||
8858 | #endif | ||
8859 | }; | ||
7764 | 8860 | ||
7765 | static struct iw_priv_args ipw_priv_args[] = { | 8861 | static struct iw_priv_args ipw_priv_args[] = { |
7766 | { | 8862 | { |
@@ -7787,14 +8883,17 @@ static struct iw_priv_args ipw_priv_args[] = { | |||
7787 | .cmd = IPW_PRIV_GET_PREAMBLE, | 8883 | .cmd = IPW_PRIV_GET_PREAMBLE, |
7788 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, | 8884 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, |
7789 | .name = "get_preamble"}, | 8885 | .name = "get_preamble"}, |
7790 | #ifdef CONFIG_IPW_MONITOR | ||
7791 | { | ||
7792 | IPW_PRIV_SET_MONITOR, | ||
7793 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"}, | ||
7794 | { | 8886 | { |
7795 | IPW_PRIV_RESET, | 8887 | IPW_PRIV_RESET, |
7796 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"}, | 8888 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"}, |
7797 | #endif /* CONFIG_IPW_MONITOR */ | 8889 | { |
8890 | IPW_PRIV_SW_RESET, | ||
8891 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "sw_reset"}, | ||
8892 | #ifdef CONFIG_IPW2200_MONITOR | ||
8893 | { | ||
8894 | IPW_PRIV_SET_MONITOR, | ||
8895 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"}, | ||
8896 | #endif /* CONFIG_IPW2200_MONITOR */ | ||
7798 | }; | 8897 | }; |
7799 | 8898 | ||
7800 | static iw_handler ipw_priv_handler[] = { | 8899 | static iw_handler ipw_priv_handler[] = { |
@@ -7804,9 +8903,10 @@ static iw_handler ipw_priv_handler[] = { | |||
7804 | ipw_wx_get_wireless_mode, | 8903 | ipw_wx_get_wireless_mode, |
7805 | ipw_wx_set_preamble, | 8904 | ipw_wx_set_preamble, |
7806 | ipw_wx_get_preamble, | 8905 | ipw_wx_get_preamble, |
7807 | #ifdef CONFIG_IPW_MONITOR | ||
7808 | ipw_wx_set_monitor, | ||
7809 | ipw_wx_reset, | 8906 | ipw_wx_reset, |
8907 | ipw_wx_sw_reset, | ||
8908 | #ifdef CONFIG_IPW2200_MONITOR | ||
8909 | ipw_wx_set_monitor, | ||
7810 | #endif | 8910 | #endif |
7811 | }; | 8911 | }; |
7812 | 8912 | ||
@@ -7915,13 +9015,19 @@ modify to send one tfd per fragment instead of using chunking. otherwise | |||
7915 | we need to heavily modify the ieee80211_skb_to_txb. | 9015 | we need to heavily modify the ieee80211_skb_to_txb. |
7916 | */ | 9016 | */ |
7917 | 9017 | ||
7918 | static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) | 9018 | static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, |
9019 | int pri) | ||
7919 | { | 9020 | { |
7920 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) | 9021 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) |
7921 | txb->fragments[0]->data; | 9022 | txb->fragments[0]->data; |
7922 | int i = 0; | 9023 | int i = 0; |
7923 | struct tfd_frame *tfd; | 9024 | struct tfd_frame *tfd; |
9025 | #ifdef CONFIG_IPW_QOS | ||
9026 | int tx_id = ipw_get_tx_queue_number(priv, pri); | ||
9027 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; | ||
9028 | #else | ||
7924 | struct clx2_tx_queue *txq = &priv->txq[0]; | 9029 | struct clx2_tx_queue *txq = &priv->txq[0]; |
9030 | #endif | ||
7925 | struct clx2_queue *q = &txq->q; | 9031 | struct clx2_queue *q = &txq->q; |
7926 | u8 id, hdr_len, unicast; | 9032 | u8 id, hdr_len, unicast; |
7927 | u16 remaining_bytes; | 9033 | u16 remaining_bytes; |
@@ -7964,15 +9070,11 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) | |||
7964 | tfd->u.data.cmd_id = DINO_CMD_TX; | 9070 | tfd->u.data.cmd_id = DINO_CMD_TX; |
7965 | tfd->u.data.len = cpu_to_le16(txb->payload_size); | 9071 | tfd->u.data.len = cpu_to_le16(txb->payload_size); |
7966 | remaining_bytes = txb->payload_size; | 9072 | remaining_bytes = txb->payload_size; |
7967 | if (unlikely(!unicast)) | ||
7968 | tfd->u.data.tx_flags = DCT_FLAG_NO_WEP; | ||
7969 | else | ||
7970 | tfd->u.data.tx_flags = DCT_FLAG_NO_WEP | DCT_FLAG_ACK_REQD; | ||
7971 | 9073 | ||
7972 | if (priv->assoc_request.ieee_mode == IPW_B_MODE) | 9074 | if (priv->assoc_request.ieee_mode == IPW_B_MODE) |
7973 | tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_CCK; | 9075 | tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_CCK; |
7974 | else | 9076 | else |
7975 | tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_OFDM; | 9077 | tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_OFDM; |
7976 | 9078 | ||
7977 | if (priv->assoc_request.preamble_length == DCT_FLAG_SHORT_PREAMBLE) | 9079 | if (priv->assoc_request.preamble_length == DCT_FLAG_SHORT_PREAMBLE) |
7978 | tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREAMBLE; | 9080 | tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREAMBLE; |
@@ -7982,6 +9084,58 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) | |||
7982 | 9084 | ||
7983 | memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len); | 9085 | memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len); |
7984 | 9086 | ||
9087 | if (likely(unicast)) | ||
9088 | tfd->u.data.tx_flags |= DCT_FLAG_ACK_REQD; | ||
9089 | |||
9090 | if (txb->encrypted && !priv->ieee->host_encrypt) { | ||
9091 | switch (priv->ieee->sec.level) { | ||
9092 | case SEC_LEVEL_3: | ||
9093 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= | ||
9094 | IEEE80211_FCTL_PROTECTED; | ||
9095 | /* XXX: ACK flag must be set for CCMP even if it | ||
9096 | * is a multicast/broadcast packet, because CCMP | ||
9097 | * group communication encrypted by GTK is | ||
9098 | * actually done by the AP. */ | ||
9099 | if (!unicast) | ||
9100 | tfd->u.data.tx_flags |= DCT_FLAG_ACK_REQD; | ||
9101 | |||
9102 | tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP; | ||
9103 | tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_CCM; | ||
9104 | tfd->u.data.key_index = 0; | ||
9105 | tfd->u.data.key_index |= DCT_WEP_INDEX_USE_IMMEDIATE; | ||
9106 | break; | ||
9107 | case SEC_LEVEL_2: | ||
9108 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= | ||
9109 | IEEE80211_FCTL_PROTECTED; | ||
9110 | tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP; | ||
9111 | tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_TKIP; | ||
9112 | tfd->u.data.key_index = DCT_WEP_INDEX_USE_IMMEDIATE; | ||
9113 | break; | ||
9114 | case SEC_LEVEL_1: | ||
9115 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= | ||
9116 | IEEE80211_FCTL_PROTECTED; | ||
9117 | tfd->u.data.key_index = priv->ieee->tx_keyidx; | ||
9118 | if (priv->ieee->sec.key_sizes[priv->ieee->tx_keyidx] <= | ||
9119 | 40) | ||
9120 | tfd->u.data.key_index |= DCT_WEP_KEY_64Bit; | ||
9121 | else | ||
9122 | tfd->u.data.key_index |= DCT_WEP_KEY_128Bit; | ||
9123 | break; | ||
9124 | case SEC_LEVEL_0: | ||
9125 | break; | ||
9126 | default: | ||
9127 | printk(KERN_ERR "Unknow security level %d\n", | ||
9128 | priv->ieee->sec.level); | ||
9129 | break; | ||
9130 | } | ||
9131 | } else | ||
9132 | /* No hardware encryption */ | ||
9133 | tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; | ||
9134 | |||
9135 | #ifdef CONFIG_IPW_QOS | ||
9136 | ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast); | ||
9137 | #endif /* CONFIG_IPW_QOS */ | ||
9138 | |||
7985 | /* payload */ | 9139 | /* payload */ |
7986 | tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), | 9140 | tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), |
7987 | txb->nr_frags)); | 9141 | txb->nr_frags)); |
@@ -8071,16 +9225,14 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, | |||
8071 | goto fail_unlock; | 9225 | goto fail_unlock; |
8072 | } | 9226 | } |
8073 | 9227 | ||
8074 | ipw_tx_skb(priv, txb); | 9228 | ipw_tx_skb(priv, txb, pri); |
9229 | __ipw_led_activity_on(priv); | ||
8075 | spin_unlock_irqrestore(&priv->lock, flags); | 9230 | spin_unlock_irqrestore(&priv->lock, flags); |
8076 | ipw_led_activity_on(priv); | ||
8077 | 9231 | ||
8078 | // up(&priv->sem); | ||
8079 | return 0; | 9232 | return 0; |
8080 | 9233 | ||
8081 | fail_unlock: | 9234 | fail_unlock: |
8082 | spin_unlock_irqrestore(&priv->lock, flags); | 9235 | spin_unlock_irqrestore(&priv->lock, flags); |
8083 | // up(&priv->sem); | ||
8084 | return 1; | 9236 | return 1; |
8085 | } | 9237 | } |
8086 | 9238 | ||
@@ -8133,7 +9285,7 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev, | |||
8133 | snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)", | 9285 | snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)", |
8134 | vers, date); | 9286 | vers, date); |
8135 | strcpy(info->bus_info, pci_name(p->pci_dev)); | 9287 | strcpy(info->bus_info, pci_name(p->pci_dev)); |
8136 | info->eedump_len = CX2_EEPROM_IMAGE_SIZE; | 9288 | info->eedump_len = IPW_EEPROM_IMAGE_SIZE; |
8137 | } | 9289 | } |
8138 | 9290 | ||
8139 | static u32 ipw_ethtool_get_link(struct net_device *dev) | 9291 | static u32 ipw_ethtool_get_link(struct net_device *dev) |
@@ -8144,7 +9296,7 @@ static u32 ipw_ethtool_get_link(struct net_device *dev) | |||
8144 | 9296 | ||
8145 | static int ipw_ethtool_get_eeprom_len(struct net_device *dev) | 9297 | static int ipw_ethtool_get_eeprom_len(struct net_device *dev) |
8146 | { | 9298 | { |
8147 | return CX2_EEPROM_IMAGE_SIZE; | 9299 | return IPW_EEPROM_IMAGE_SIZE; |
8148 | } | 9300 | } |
8149 | 9301 | ||
8150 | static int ipw_ethtool_get_eeprom(struct net_device *dev, | 9302 | static int ipw_ethtool_get_eeprom(struct net_device *dev, |
@@ -8152,7 +9304,7 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev, | |||
8152 | { | 9304 | { |
8153 | struct ipw_priv *p = ieee80211_priv(dev); | 9305 | struct ipw_priv *p = ieee80211_priv(dev); |
8154 | 9306 | ||
8155 | if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE) | 9307 | if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) |
8156 | return -EINVAL; | 9308 | return -EINVAL; |
8157 | down(&p->sem); | 9309 | down(&p->sem); |
8158 | memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len); | 9310 | memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len); |
@@ -8166,12 +9318,12 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, | |||
8166 | struct ipw_priv *p = ieee80211_priv(dev); | 9318 | struct ipw_priv *p = ieee80211_priv(dev); |
8167 | int i; | 9319 | int i; |
8168 | 9320 | ||
8169 | if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE) | 9321 | if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) |
8170 | return -EINVAL; | 9322 | return -EINVAL; |
8171 | down(&p->sem); | 9323 | down(&p->sem); |
8172 | memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len); | 9324 | memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len); |
8173 | for (i = IPW_EEPROM_DATA; | 9325 | for (i = IPW_EEPROM_DATA; |
8174 | i < IPW_EEPROM_DATA + CX2_EEPROM_IMAGE_SIZE; i++) | 9326 | i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++) |
8175 | ipw_write8(p, i, p->eeprom[i]); | 9327 | ipw_write8(p, i, p->eeprom[i]); |
8176 | up(&p->sem); | 9328 | up(&p->sem); |
8177 | return 0; | 9329 | return 0; |
@@ -8197,13 +9349,11 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) | |||
8197 | 9349 | ||
8198 | if (!(priv->status & STATUS_INT_ENABLED)) { | 9350 | if (!(priv->status & STATUS_INT_ENABLED)) { |
8199 | /* Shared IRQ */ | 9351 | /* Shared IRQ */ |
8200 | // ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); | ||
8201 | // return IRQ_HANDLED; | ||
8202 | goto none; | 9352 | goto none; |
8203 | } | 9353 | } |
8204 | 9354 | ||
8205 | inta = ipw_read32(priv, CX2_INTA_RW); | 9355 | inta = ipw_read32(priv, IPW_INTA_RW); |
8206 | inta_mask = ipw_read32(priv, CX2_INTA_MASK_R); | 9356 | inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); |
8207 | 9357 | ||
8208 | if (inta == 0xFFFFFFFF) { | 9358 | if (inta == 0xFFFFFFFF) { |
8209 | /* Hardware disappeared */ | 9359 | /* Hardware disappeared */ |
@@ -8211,7 +9361,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) | |||
8211 | goto none; | 9361 | goto none; |
8212 | } | 9362 | } |
8213 | 9363 | ||
8214 | if (!(inta & (CX2_INTA_MASK_ALL & inta_mask))) { | 9364 | if (!(inta & (IPW_INTA_MASK_ALL & inta_mask))) { |
8215 | /* Shared interrupt */ | 9365 | /* Shared interrupt */ |
8216 | goto none; | 9366 | goto none; |
8217 | } | 9367 | } |
@@ -8220,8 +9370,8 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) | |||
8220 | ipw_disable_interrupts(priv); | 9370 | ipw_disable_interrupts(priv); |
8221 | 9371 | ||
8222 | /* ack current interrupts */ | 9372 | /* ack current interrupts */ |
8223 | inta &= (CX2_INTA_MASK_ALL & inta_mask); | 9373 | inta &= (IPW_INTA_MASK_ALL & inta_mask); |
8224 | ipw_write32(priv, CX2_INTA_RW, inta); | 9374 | ipw_write32(priv, IPW_INTA_RW, inta); |
8225 | 9375 | ||
8226 | /* Cache INTA value for our tasklet */ | 9376 | /* Cache INTA value for our tasklet */ |
8227 | priv->isr_inta = inta; | 9377 | priv->isr_inta = inta; |
@@ -8348,7 +9498,7 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) | |||
8348 | INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv); | 9498 | INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv); |
8349 | INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); | 9499 | INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); |
8350 | INIT_WORK(&priv->request_scan, | 9500 | INIT_WORK(&priv->request_scan, |
8351 | (void (*)(void *))ipw_bg_request_scan, priv); | 9501 | (void (*)(void *))ipw_request_scan, priv); |
8352 | INIT_WORK(&priv->gather_stats, | 9502 | INIT_WORK(&priv->gather_stats, |
8353 | (void (*)(void *))ipw_bg_gather_stats, priv); | 9503 | (void (*)(void *))ipw_bg_gather_stats, priv); |
8354 | INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); | 9504 | INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); |
@@ -8365,6 +9515,11 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) | |||
8365 | INIT_WORK(&priv->merge_networks, | 9515 | INIT_WORK(&priv->merge_networks, |
8366 | (void (*)(void *))ipw_merge_adhoc_network, priv); | 9516 | (void (*)(void *))ipw_merge_adhoc_network, priv); |
8367 | 9517 | ||
9518 | #ifdef CONFIG_IPW_QOS | ||
9519 | INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, | ||
9520 | priv); | ||
9521 | #endif /* CONFIG_IPW_QOS */ | ||
9522 | |||
8368 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 9523 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
8369 | ipw_irq_tasklet, (unsigned long)priv); | 9524 | ipw_irq_tasklet, (unsigned long)priv); |
8370 | 9525 | ||
@@ -8379,31 +9534,33 @@ static void shim__set_security(struct net_device *dev, | |||
8379 | down(&priv->sem); | 9534 | down(&priv->sem); |
8380 | for (i = 0; i < 4; i++) { | 9535 | for (i = 0; i < 4; i++) { |
8381 | if (sec->flags & (1 << i)) { | 9536 | if (sec->flags & (1 << i)) { |
8382 | priv->sec.key_sizes[i] = sec->key_sizes[i]; | 9537 | priv->ieee->sec.key_sizes[i] = sec->key_sizes[i]; |
8383 | if (sec->key_sizes[i] == 0) | 9538 | if (sec->key_sizes[i] == 0) |
8384 | priv->sec.flags &= ~(1 << i); | 9539 | priv->ieee->sec.flags &= ~(1 << i); |
8385 | else | 9540 | else { |
8386 | memcpy(priv->sec.keys[i], sec->keys[i], | 9541 | memcpy(priv->ieee->sec.keys[i], sec->keys[i], |
8387 | sec->key_sizes[i]); | 9542 | sec->key_sizes[i]); |
8388 | priv->sec.flags |= (1 << i); | 9543 | priv->ieee->sec.flags |= (1 << i); |
9544 | } | ||
8389 | priv->status |= STATUS_SECURITY_UPDATED; | 9545 | priv->status |= STATUS_SECURITY_UPDATED; |
8390 | } | 9546 | } else if (sec->level != SEC_LEVEL_1) |
9547 | priv->ieee->sec.flags &= ~(1 << i); | ||
8391 | } | 9548 | } |
8392 | 9549 | ||
8393 | if ((sec->flags & SEC_ACTIVE_KEY) && | 9550 | if (sec->flags & SEC_ACTIVE_KEY) { |
8394 | priv->sec.active_key != sec->active_key) { | ||
8395 | if (sec->active_key <= 3) { | 9551 | if (sec->active_key <= 3) { |
8396 | priv->sec.active_key = sec->active_key; | 9552 | priv->ieee->sec.active_key = sec->active_key; |
8397 | priv->sec.flags |= SEC_ACTIVE_KEY; | 9553 | priv->ieee->sec.flags |= SEC_ACTIVE_KEY; |
8398 | } else | 9554 | } else |
8399 | priv->sec.flags &= ~SEC_ACTIVE_KEY; | 9555 | priv->ieee->sec.flags &= ~SEC_ACTIVE_KEY; |
8400 | priv->status |= STATUS_SECURITY_UPDATED; | 9556 | priv->status |= STATUS_SECURITY_UPDATED; |
8401 | } | 9557 | } else |
9558 | priv->ieee->sec.flags &= ~SEC_ACTIVE_KEY; | ||
8402 | 9559 | ||
8403 | if ((sec->flags & SEC_AUTH_MODE) && | 9560 | if ((sec->flags & SEC_AUTH_MODE) && |
8404 | (priv->sec.auth_mode != sec->auth_mode)) { | 9561 | (priv->ieee->sec.auth_mode != sec->auth_mode)) { |
8405 | priv->sec.auth_mode = sec->auth_mode; | 9562 | priv->ieee->sec.auth_mode = sec->auth_mode; |
8406 | priv->sec.flags |= SEC_AUTH_MODE; | 9563 | priv->ieee->sec.flags |= SEC_AUTH_MODE; |
8407 | if (sec->auth_mode == WLAN_AUTH_SHARED_KEY) | 9564 | if (sec->auth_mode == WLAN_AUTH_SHARED_KEY) |
8408 | priv->capability |= CAP_SHARED_KEY; | 9565 | priv->capability |= CAP_SHARED_KEY; |
8409 | else | 9566 | else |
@@ -8411,22 +9568,26 @@ static void shim__set_security(struct net_device *dev, | |||
8411 | priv->status |= STATUS_SECURITY_UPDATED; | 9568 | priv->status |= STATUS_SECURITY_UPDATED; |
8412 | } | 9569 | } |
8413 | 9570 | ||
8414 | if (sec->flags & SEC_ENABLED && priv->sec.enabled != sec->enabled) { | 9571 | if (sec->flags & SEC_ENABLED && priv->ieee->sec.enabled != sec->enabled) { |
8415 | priv->sec.flags |= SEC_ENABLED; | 9572 | priv->ieee->sec.flags |= SEC_ENABLED; |
8416 | priv->sec.enabled = sec->enabled; | 9573 | priv->ieee->sec.enabled = sec->enabled; |
8417 | priv->status |= STATUS_SECURITY_UPDATED; | 9574 | priv->status |= STATUS_SECURITY_UPDATED; |
8418 | if (sec->enabled) | 9575 | if (sec->enabled) |
8419 | priv->capability |= CAP_PRIVACY_ON; | 9576 | priv->capability |= CAP_PRIVACY_ON; |
8420 | else | 9577 | else |
8421 | priv->capability &= ~CAP_PRIVACY_ON; | 9578 | priv->capability &= ~CAP_PRIVACY_ON; |
8422 | } | 9579 | } |
9580 | priv->ieee->sec.encrypt = sec->encrypt; | ||
8423 | 9581 | ||
8424 | if (sec->flags & SEC_LEVEL && priv->sec.level != sec->level) { | 9582 | if (sec->flags & SEC_LEVEL && priv->ieee->sec.level != sec->level) { |
8425 | priv->sec.level = sec->level; | 9583 | priv->ieee->sec.level = sec->level; |
8426 | priv->sec.flags |= SEC_LEVEL; | 9584 | priv->ieee->sec.flags |= SEC_LEVEL; |
8427 | priv->status |= STATUS_SECURITY_UPDATED; | 9585 | priv->status |= STATUS_SECURITY_UPDATED; |
8428 | } | 9586 | } |
8429 | 9587 | ||
9588 | if (!priv->ieee->host_encrypt) | ||
9589 | ipw_set_hwcrypto_keys(priv); | ||
9590 | |||
8430 | /* To match current functionality of ipw2100 (which works well w/ | 9591 | /* To match current functionality of ipw2100 (which works well w/ |
8431 | * various supplicants, we don't force a disassociate if the | 9592 | * various supplicants, we don't force a disassociate if the |
8432 | * privacy capability changes ... */ | 9593 | * privacy capability changes ... */ |
@@ -8524,6 +9685,10 @@ static int ipw_config(struct ipw_priv *priv) | |||
8524 | if (ipw_send_rts_threshold(priv, priv->rts_threshold)) | 9685 | if (ipw_send_rts_threshold(priv, priv->rts_threshold)) |
8525 | goto error; | 9686 | goto error; |
8526 | } | 9687 | } |
9688 | #ifdef CONFIG_IPW_QOS | ||
9689 | IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n"); | ||
9690 | ipw_qos_activate(priv, NULL); | ||
9691 | #endif /* CONFIG_IPW_QOS */ | ||
8527 | 9692 | ||
8528 | if (ipw_set_random_seed(priv)) | 9693 | if (ipw_set_random_seed(priv)) |
8529 | goto error; | 9694 | goto error; |
@@ -8533,10 +9698,8 @@ static int ipw_config(struct ipw_priv *priv) | |||
8533 | goto error; | 9698 | goto error; |
8534 | 9699 | ||
8535 | /* If configured to try and auto-associate, kick off a scan */ | 9700 | /* If configured to try and auto-associate, kick off a scan */ |
8536 | if ((priv->config & CFG_ASSOCIATE) && ipw_request_scan(priv)) { | 9701 | if (priv->config & CFG_ASSOCIATE) |
8537 | IPW_WARNING("error sending scan request\n"); | 9702 | queue_work(priv->workqueue, &priv->request_scan); |
8538 | goto error; | ||
8539 | } | ||
8540 | 9703 | ||
8541 | return 0; | 9704 | return 0; |
8542 | 9705 | ||
@@ -8566,7 +9729,15 @@ static int ipw_up(struct ipw_priv *priv) | |||
8566 | eeprom_parse_mac(priv, priv->mac_addr); | 9729 | eeprom_parse_mac(priv, priv->mac_addr); |
8567 | memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); | 9730 | memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); |
8568 | 9731 | ||
8569 | if (priv->status & STATUS_RF_KILL_MASK) { | 9732 | if (priv->status & STATUS_RF_KILL_SW) { |
9733 | IPW_WARNING("Radio disabled by module parameter.\n"); | ||
9734 | return 0; | ||
9735 | } else if (rf_kill_active(priv)) { | ||
9736 | IPW_WARNING("Radio Frequency Kill Switch is On:\n" | ||
9737 | "Kill switch must be turned off for " | ||
9738 | "wireless networking to work.\n"); | ||
9739 | queue_delayed_work(priv->workqueue, &priv->rf_kill, | ||
9740 | 2 * HZ); | ||
8570 | return 0; | 9741 | return 0; |
8571 | } | 9742 | } |
8572 | 9743 | ||
@@ -8604,18 +9775,61 @@ static void ipw_bg_up(void *data) | |||
8604 | up(&priv->sem); | 9775 | up(&priv->sem); |
8605 | } | 9776 | } |
8606 | 9777 | ||
8607 | static void ipw_down(struct ipw_priv *priv) | 9778 | static void ipw_deinit(struct ipw_priv *priv) |
8608 | { | 9779 | { |
8609 | #if 0 | 9780 | int i; |
9781 | |||
9782 | if (priv->status & STATUS_SCANNING) { | ||
9783 | IPW_DEBUG_INFO("Aborting scan during shutdown.\n"); | ||
9784 | ipw_abort_scan(priv); | ||
9785 | } | ||
9786 | |||
9787 | if (priv->status & STATUS_ASSOCIATED) { | ||
9788 | IPW_DEBUG_INFO("Disassociating during shutdown.\n"); | ||
9789 | ipw_disassociate(priv); | ||
9790 | } | ||
9791 | |||
9792 | ipw_led_shutdown(priv); | ||
9793 | |||
9794 | /* Wait up to 1s for status to change to not scanning and not | ||
9795 | * associated (disassociation can take a while for a ful 802.11 | ||
9796 | * exchange */ | ||
9797 | for (i = 1000; i && (priv->status & | ||
9798 | (STATUS_DISASSOCIATING | | ||
9799 | STATUS_ASSOCIATED | STATUS_SCANNING)); i--) | ||
9800 | udelay(10); | ||
9801 | |||
9802 | if (priv->status & (STATUS_DISASSOCIATING | | ||
9803 | STATUS_ASSOCIATED | STATUS_SCANNING)) | ||
9804 | IPW_DEBUG_INFO("Still associated or scanning...\n"); | ||
9805 | else | ||
9806 | IPW_DEBUG_INFO("Took %dms to de-init\n", 1000 - i); | ||
9807 | |||
8610 | /* Attempt to disable the card */ | 9808 | /* Attempt to disable the card */ |
8611 | ipw_send_card_disable(priv, 0); | 9809 | ipw_send_card_disable(priv, 0); |
8612 | #endif | 9810 | |
9811 | priv->status &= ~STATUS_INIT; | ||
9812 | } | ||
9813 | |||
9814 | static void ipw_down(struct ipw_priv *priv) | ||
9815 | { | ||
9816 | int exit_pending = priv->status & STATUS_EXIT_PENDING; | ||
9817 | |||
9818 | priv->status |= STATUS_EXIT_PENDING; | ||
9819 | |||
9820 | if (ipw_is_init(priv)) | ||
9821 | ipw_deinit(priv); | ||
9822 | |||
9823 | /* Wipe out the EXIT_PENDING status bit if we are not actually | ||
9824 | * exiting the module */ | ||
9825 | if (!exit_pending) | ||
9826 | priv->status &= ~STATUS_EXIT_PENDING; | ||
8613 | 9827 | ||
8614 | /* tell the device to stop sending interrupts */ | 9828 | /* tell the device to stop sending interrupts */ |
8615 | ipw_disable_interrupts(priv); | 9829 | ipw_disable_interrupts(priv); |
8616 | 9830 | ||
8617 | /* Clear all bits but the RF Kill */ | 9831 | /* Clear all bits but the RF Kill */ |
8618 | priv->status &= STATUS_RF_KILL_MASK; | 9832 | priv->status &= STATUS_RF_KILL_MASK | STATUS_EXIT_PENDING; |
8619 | netif_carrier_off(priv->net_dev); | 9833 | netif_carrier_off(priv->net_dev); |
8620 | netif_stop_queue(priv->net_dev); | 9834 | netif_stop_queue(priv->net_dev); |
8621 | 9835 | ||
@@ -8653,18 +9867,6 @@ static int ipw_net_init(struct net_device *dev) | |||
8653 | { | 9867 | { |
8654 | struct ipw_priv *priv = ieee80211_priv(dev); | 9868 | struct ipw_priv *priv = ieee80211_priv(dev); |
8655 | down(&priv->sem); | 9869 | down(&priv->sem); |
8656 | if (priv->status & STATUS_RF_KILL_SW) { | ||
8657 | IPW_WARNING("Radio disabled by module parameter.\n"); | ||
8658 | up(&priv->sem); | ||
8659 | return 0; | ||
8660 | } else if (rf_kill_active(priv)) { | ||
8661 | IPW_WARNING("Radio Frequency Kill Switch is On:\n" | ||
8662 | "Kill switch must be turned off for " | ||
8663 | "wireless networking to work.\n"); | ||
8664 | queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); | ||
8665 | up(&priv->sem); | ||
8666 | return 0; | ||
8667 | } | ||
8668 | 9870 | ||
8669 | if (ipw_up(priv)) { | 9871 | if (ipw_up(priv)) { |
8670 | up(&priv->sem); | 9872 | up(&priv->sem); |
@@ -8723,6 +9925,8 @@ static struct attribute *ipw_sysfs_entries[] = { | |||
8723 | &dev_attr_rtc.attr, | 9925 | &dev_attr_rtc.attr, |
8724 | &dev_attr_scan_age.attr, | 9926 | &dev_attr_scan_age.attr, |
8725 | &dev_attr_led.attr, | 9927 | &dev_attr_led.attr, |
9928 | &dev_attr_speed_scan.attr, | ||
9929 | &dev_attr_net_stats.attr, | ||
8726 | NULL | 9930 | NULL |
8727 | }; | 9931 | }; |
8728 | 9932 | ||
@@ -8738,7 +9942,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
8738 | void __iomem *base; | 9942 | void __iomem *base; |
8739 | u32 length, val; | 9943 | u32 length, val; |
8740 | struct ipw_priv *priv; | 9944 | struct ipw_priv *priv; |
8741 | int band, modulation; | ||
8742 | 9945 | ||
8743 | net_dev = alloc_ieee80211(sizeof(struct ipw_priv)); | 9946 | net_dev = alloc_ieee80211(sizeof(struct ipw_priv)); |
8744 | if (net_dev == NULL) { | 9947 | if (net_dev == NULL) { |
@@ -8803,88 +10006,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
8803 | goto out_iounmap; | 10006 | goto out_iounmap; |
8804 | } | 10007 | } |
8805 | 10008 | ||
8806 | /* Initialize module parameter values here */ | 10009 | ipw_sw_reset(priv, 1); |
8807 | |||
8808 | /* We default to disabling the LED code as right now it causes | ||
8809 | * too many systems to lock up... */ | ||
8810 | if (!led) | ||
8811 | priv->config |= CFG_NO_LED; | ||
8812 | |||
8813 | if (associate) | ||
8814 | priv->config |= CFG_ASSOCIATE; | ||
8815 | else | ||
8816 | IPW_DEBUG_INFO("Auto associate disabled.\n"); | ||
8817 | |||
8818 | if (auto_create) | ||
8819 | priv->config |= CFG_ADHOC_CREATE; | ||
8820 | else | ||
8821 | IPW_DEBUG_INFO("Auto adhoc creation disabled.\n"); | ||
8822 | |||
8823 | if (disable) { | ||
8824 | priv->status |= STATUS_RF_KILL_SW; | ||
8825 | IPW_DEBUG_INFO("Radio disabled.\n"); | ||
8826 | } | ||
8827 | |||
8828 | if (channel != 0) { | ||
8829 | priv->config |= CFG_STATIC_CHANNEL; | ||
8830 | priv->channel = channel; | ||
8831 | IPW_DEBUG_INFO("Bind to static channel %d\n", channel); | ||
8832 | IPW_DEBUG_INFO("Bind to static channel %d\n", channel); | ||
8833 | /* TODO: Validate that provided channel is in range */ | ||
8834 | } | ||
8835 | |||
8836 | switch (mode) { | ||
8837 | case 1: | ||
8838 | priv->ieee->iw_mode = IW_MODE_ADHOC; | ||
8839 | break; | ||
8840 | #ifdef CONFIG_IPW_MONITOR | ||
8841 | case 2: | ||
8842 | priv->ieee->iw_mode = IW_MODE_MONITOR; | ||
8843 | break; | ||
8844 | #endif | ||
8845 | default: | ||
8846 | case 0: | ||
8847 | priv->ieee->iw_mode = IW_MODE_INFRA; | ||
8848 | break; | ||
8849 | } | ||
8850 | |||
8851 | if ((priv->pci_dev->device == 0x4223) || | ||
8852 | (priv->pci_dev->device == 0x4224)) { | ||
8853 | printk(KERN_INFO DRV_NAME | ||
8854 | ": Detected Intel PRO/Wireless 2915ABG Network " | ||
8855 | "Connection\n"); | ||
8856 | priv->ieee->abg_true = 1; | ||
8857 | band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND; | ||
8858 | modulation = IEEE80211_OFDM_MODULATION | | ||
8859 | IEEE80211_CCK_MODULATION; | ||
8860 | priv->adapter = IPW_2915ABG; | ||
8861 | priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; | ||
8862 | } else { | ||
8863 | printk(KERN_INFO DRV_NAME | ||
8864 | ": Detected Intel PRO/Wireless 2200BG Network " | ||
8865 | "Connection\n"); | ||
8866 | |||
8867 | priv->ieee->abg_true = 0; | ||
8868 | band = IEEE80211_24GHZ_BAND; | ||
8869 | modulation = IEEE80211_OFDM_MODULATION | | ||
8870 | IEEE80211_CCK_MODULATION; | ||
8871 | priv->adapter = IPW_2200BG; | ||
8872 | priv->ieee->mode = IEEE_G | IEEE_B; | ||
8873 | } | ||
8874 | |||
8875 | priv->ieee->freq_band = band; | ||
8876 | priv->ieee->modulation = modulation; | ||
8877 | |||
8878 | priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK; | ||
8879 | |||
8880 | priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; | ||
8881 | priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; | ||
8882 | |||
8883 | priv->rts_threshold = DEFAULT_RTS_THRESHOLD; | ||
8884 | |||
8885 | /* If power management is turned on, default to AC mode */ | ||
8886 | priv->power_mode = IPW_POWER_AC; | ||
8887 | priv->tx_power = IPW_DEFAULT_TX_POWER; | ||
8888 | 10010 | ||
8889 | err = request_irq(pdev->irq, ipw_isr, SA_SHIRQ, DRV_NAME, priv); | 10011 | err = request_irq(pdev->irq, ipw_isr, SA_SHIRQ, DRV_NAME, priv); |
8890 | if (err) { | 10012 | if (err) { |
@@ -8903,6 +10025,10 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
8903 | priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; | 10025 | priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; |
8904 | priv->ieee->set_security = shim__set_security; | 10026 | priv->ieee->set_security = shim__set_security; |
8905 | 10027 | ||
10028 | #ifdef CONFIG_IPW_QOS | ||
10029 | priv->ieee->handle_management_frame = ipw_handle_management_frame; | ||
10030 | #endif /* CONFIG_IPW_QOS */ | ||
10031 | |||
8906 | priv->ieee->perfect_rssi = -20; | 10032 | priv->ieee->perfect_rssi = -20; |
8907 | priv->ieee->worst_rssi = -85; | 10033 | priv->ieee->worst_rssi = -85; |
8908 | 10034 | ||
@@ -8960,14 +10086,14 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
8960 | static void ipw_pci_remove(struct pci_dev *pdev) | 10086 | static void ipw_pci_remove(struct pci_dev *pdev) |
8961 | { | 10087 | { |
8962 | struct ipw_priv *priv = pci_get_drvdata(pdev); | 10088 | struct ipw_priv *priv = pci_get_drvdata(pdev); |
10089 | |||
8963 | if (!priv) | 10090 | if (!priv) |
8964 | return; | 10091 | return; |
8965 | 10092 | ||
8966 | priv->status |= STATUS_EXIT_PENDING; | 10093 | down(&priv->sem); |
8967 | |||
8968 | sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); | ||
8969 | |||
8970 | ipw_down(priv); | 10094 | ipw_down(priv); |
10095 | sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); | ||
10096 | up(&priv->sem); | ||
8971 | 10097 | ||
8972 | unregister_netdev(priv->net_dev); | 10098 | unregister_netdev(priv->net_dev); |
8973 | 10099 | ||
@@ -8977,8 +10103,6 @@ static void ipw_pci_remove(struct pci_dev *pdev) | |||
8977 | } | 10103 | } |
8978 | ipw_tx_queue_free(priv); | 10104 | ipw_tx_queue_free(priv); |
8979 | 10105 | ||
8980 | ipw_led_shutdown(priv); | ||
8981 | |||
8982 | /* ipw_down will ensure that there is no more pending work | 10106 | /* ipw_down will ensure that there is no more pending work |
8983 | * in the workqueue's, so we can safely remove them now. */ | 10107 | * in the workqueue's, so we can safely remove them now. */ |
8984 | cancel_delayed_work(&priv->adhoc_check); | 10108 | cancel_delayed_work(&priv->adhoc_check); |
@@ -9119,7 +10243,24 @@ MODULE_PARM_DESC(debug, "debug output mask"); | |||
9119 | module_param(channel, int, 0444); | 10243 | module_param(channel, int, 0444); |
9120 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); | 10244 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); |
9121 | 10245 | ||
9122 | #ifdef CONFIG_IPW_MONITOR | 10246 | #ifdef CONFIG_IPW_QOS |
10247 | module_param(qos_enable, int, 0444); | ||
10248 | MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis"); | ||
10249 | |||
10250 | module_param(qos_burst_enable, int, 0444); | ||
10251 | MODULE_PARM_DESC(qos_burst_enable, "enable QoS burst mode"); | ||
10252 | |||
10253 | module_param(qos_no_ack_mask, int, 0444); | ||
10254 | MODULE_PARM_DESC(qos_no_ack_mask, "mask Tx_Queue to no ack"); | ||
10255 | |||
10256 | module_param(burst_duration_CCK, int, 0444); | ||
10257 | MODULE_PARM_DESC(burst_duration_CCK, "set CCK burst value"); | ||
10258 | |||
10259 | module_param(burst_duration_OFDM, int, 0444); | ||
10260 | MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); | ||
10261 | #endif /* CONFIG_IPW_QOS */ | ||
10262 | |||
10263 | #ifdef CONFIG_IPW2200_MONITOR | ||
9123 | module_param(mode, int, 0444); | 10264 | module_param(mode, int, 0444); |
9124 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); | 10265 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); |
9125 | #else | 10266 | #else |
@@ -9127,5 +10268,8 @@ module_param(mode, int, 0444); | |||
9127 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); | 10268 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); |
9128 | #endif | 10269 | #endif |
9129 | 10270 | ||
10271 | module_param(hwcrypto, int, 0444); | ||
10272 | MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default on)"); | ||
10273 | |||
9130 | module_exit(ipw_exit); | 10274 | module_exit(ipw_exit); |
9131 | module_init(ipw_init); | 10275 | module_init(ipw_init); |