diff options
author | David S. Miller <davem@davemloft.net> | 2009-11-18 13:55:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-18 13:55:32 -0500 |
commit | dfef948ed2ba69cf041840b5e860d6b4e16fa0b1 (patch) | |
tree | eab385cabe589346bcf19385c997ab8dabaef7bd /drivers/net/wireless/iwlwifi | |
parent | ea31ba359c55e0734ff895692185d4c50cf0c537 (diff) | |
parent | c85e9d7739fc8d879c4293ea020760926d6f87cd (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 106 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 79 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-commands.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 54 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 22 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-hcmd.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-io.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-prph.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 42 |
16 files changed, 234 insertions, 192 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 09a7bd2c0be4..26a1134f84a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -564,7 +564,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
564 | return; | 564 | return; |
565 | } | 565 | } |
566 | 566 | ||
567 | skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC); | 567 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); |
568 | if (!skb) { | 568 | if (!skb) { |
569 | IWL_ERR(priv, "alloc_skb failed\n"); | 569 | IWL_ERR(priv, "alloc_skb failed\n"); |
570 | return; | 570 | return; |
@@ -575,6 +575,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
575 | (struct ieee80211_hdr *)rxb_addr(rxb), | 575 | (struct ieee80211_hdr *)rxb_addr(rxb), |
576 | le32_to_cpu(rx_end->status), stats); | 576 | le32_to_cpu(rx_end->status), stats); |
577 | 577 | ||
578 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
578 | skb_add_rx_frag(skb, 0, rxb->page, | 579 | skb_add_rx_frag(skb, 0, rxb->page, |
579 | (void *)rx_hdr->payload - (void *)pkt, len); | 580 | (void *)rx_hdr->payload - (void *)pkt, len); |
580 | 581 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1ff465ad40d8..1d22ea390c00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -1449,14 +1449,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1449 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); | 1449 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); |
1450 | 1450 | ||
1451 | if (is_ht40 && | 1451 | if (is_ht40 && |
1452 | (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) | 1452 | (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) |
1453 | ctrl_chan_high = 1; | 1453 | ctrl_chan_high = 1; |
1454 | 1454 | ||
1455 | cmd.band = band; | 1455 | cmd.band = band; |
1456 | cmd.expect_beacon = 0; | 1456 | cmd.expect_beacon = 0; |
1457 | cmd.channel = cpu_to_le16(channel); | 1457 | cmd.channel = cpu_to_le16(channel); |
1458 | cmd.rxon_flags = priv->active_rxon.flags; | 1458 | cmd.rxon_flags = priv->staging_rxon.flags; |
1459 | cmd.rxon_filter_flags = priv->active_rxon.filter_flags; | 1459 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
1460 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 1460 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); |
1461 | if (ch_info) | 1461 | if (ch_info) |
1462 | cmd.expect_beacon = is_channel_radar(ch_info); | 1462 | cmd.expect_beacon = is_channel_radar(ch_info); |
@@ -1473,8 +1473,10 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1473 | return rc; | 1473 | return rc; |
1474 | } | 1474 | } |
1475 | 1475 | ||
1476 | rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | 1476 | priv->switch_rxon.channel = cpu_to_le16(channel); |
1477 | return rc; | 1477 | priv->switch_rxon.switch_in_progress = true; |
1478 | |||
1479 | return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | ||
1478 | } | 1480 | } |
1479 | 1481 | ||
1480 | /** | 1482 | /** |
@@ -2228,7 +2230,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2228 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | 2230 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, |
2229 | .mod_params = &iwl4965_mod_params, | 2231 | .mod_params = &iwl4965_mod_params, |
2230 | .valid_tx_ant = ANT_AB, | 2232 | .valid_tx_ant = ANT_AB, |
2231 | .valid_rx_ant = ANT_AB, | 2233 | .valid_rx_ant = ANT_ABC, |
2232 | .pll_cfg_val = 0, | 2234 | .pll_cfg_val = 0, |
2233 | .set_l0s = true, | 2235 | .set_l0s = true, |
2234 | .use_bsm = true, | 2236 | .use_bsm = true, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 910217f0ad8a..6eaf26b07636 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -661,9 +661,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
661 | iwl_txq_ctx_activate(priv, i); | 661 | iwl_txq_ctx_activate(priv, i); |
662 | iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | 662 | iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); |
663 | } | 663 | } |
664 | /* TODO - need to initialize those FIFOs inside the loop above, | 664 | |
665 | * not only mark them as active */ | 665 | /* |
666 | iwl_txq_ctx_activate(priv, 4); | 666 | * TODO - need to initialize these queues and map them to FIFOs |
667 | * in the loop above, not only mark them as active. We do this | ||
668 | * because we want the first aggregation queue to be queue #10, | ||
669 | * but do not use 8 or 9 otherwise yet. | ||
670 | */ | ||
667 | iwl_txq_ctx_activate(priv, 7); | 671 | iwl_txq_ctx_activate(priv, 7); |
668 | iwl_txq_ctx_activate(priv, 8); | 672 | iwl_txq_ctx_activate(priv, 8); |
669 | iwl_txq_ctx_activate(priv, 9); | 673 | iwl_txq_ctx_activate(priv, 9); |
@@ -1387,8 +1391,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1387 | priv->active_rxon.channel, channel); | 1391 | priv->active_rxon.channel, channel); |
1388 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 1392 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
1389 | cmd.channel = cpu_to_le16(channel); | 1393 | cmd.channel = cpu_to_le16(channel); |
1390 | cmd.rxon_flags = priv->active_rxon.flags; | 1394 | cmd.rxon_flags = priv->staging_rxon.flags; |
1391 | cmd.rxon_filter_flags = priv->active_rxon.filter_flags; | 1395 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
1392 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 1396 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); |
1393 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | 1397 | ch_info = iwl_get_channel_info(priv, priv->band, channel); |
1394 | if (ch_info) | 1398 | if (ch_info) |
@@ -1398,6 +1402,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1398 | priv->active_rxon.channel, channel); | 1402 | priv->active_rxon.channel, channel); |
1399 | return -EFAULT; | 1403 | return -EFAULT; |
1400 | } | 1404 | } |
1405 | priv->switch_rxon.channel = cpu_to_le16(channel); | ||
1406 | priv->switch_rxon.switch_in_progress = true; | ||
1401 | 1407 | ||
1402 | return iwl_send_cmd_sync(priv, &hcmd); | 1408 | return iwl_send_cmd_sync(priv, &hcmd); |
1403 | } | 1409 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 70e117f8d0c4..f732f6d194a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -90,11 +90,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
90 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | 90 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); |
91 | 91 | ||
92 | /* no locking required for register write */ | 92 | /* no locking required for register write */ |
93 | if (priv->cfg->pa_type == IWL_PA_HYBRID) { | 93 | if (priv->cfg->pa_type == IWL_PA_INTERNAL) { |
94 | /* 2x2 hybrid phy type */ | ||
95 | iwl_write32(priv, CSR_GP_DRIVER_REG, | ||
96 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB); | ||
97 | } else if (priv->cfg->pa_type == IWL_PA_INTERNAL) { | ||
98 | /* 2x2 IPA phy type */ | 94 | /* 2x2 IPA phy type */ |
99 | iwl_write32(priv, CSR_GP_DRIVER_REG, | 95 | iwl_write32(priv, CSR_GP_DRIVER_REG, |
100 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | 96 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); |
@@ -166,9 +162,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
166 | BIT(IWL_CALIB_XTAL) | | 162 | BIT(IWL_CALIB_XTAL) | |
167 | BIT(IWL_CALIB_LO) | | 163 | BIT(IWL_CALIB_LO) | |
168 | BIT(IWL_CALIB_TX_IQ) | | 164 | BIT(IWL_CALIB_TX_IQ) | |
169 | BIT(IWL_CALIB_TX_IQ_PERD) | | ||
170 | BIT(IWL_CALIB_BASE_BAND); | 165 | BIT(IWL_CALIB_BASE_BAND); |
171 | |||
172 | return 0; | 166 | return 0; |
173 | } | 167 | } |
174 | 168 | ||
@@ -188,8 +182,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
188 | 182 | ||
189 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 183 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
190 | cmd.channel = cpu_to_le16(channel); | 184 | cmd.channel = cpu_to_le16(channel); |
191 | cmd.rxon_flags = priv->active_rxon.flags; | 185 | cmd.rxon_flags = priv->staging_rxon.flags; |
192 | cmd.rxon_filter_flags = priv->active_rxon.filter_flags; | 186 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
193 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 187 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); |
194 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | 188 | ch_info = iwl_get_channel_info(priv, priv->band, channel); |
195 | if (ch_info) | 189 | if (ch_info) |
@@ -199,6 +193,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
199 | priv->active_rxon.channel, channel); | 193 | priv->active_rxon.channel, channel); |
200 | return -EFAULT; | 194 | return -EFAULT; |
201 | } | 195 | } |
196 | priv->switch_rxon.channel = cpu_to_le16(channel); | ||
197 | priv->switch_rxon.switch_in_progress = true; | ||
202 | 198 | ||
203 | return iwl_send_cmd_sync(priv, &hcmd); | 199 | return iwl_send_cmd_sync(priv, &hcmd); |
204 | } | 200 | } |
@@ -279,98 +275,6 @@ static struct iwl_ops iwl6050_ops = { | |||
279 | .led = &iwlagn_led_ops, | 275 | .led = &iwlagn_led_ops, |
280 | }; | 276 | }; |
281 | 277 | ||
282 | |||
283 | /* | ||
284 | * "h": Hybrid configuration, use both internal and external Power Amplifier | ||
285 | */ | ||
286 | struct iwl_cfg iwl6000h_2agn_cfg = { | ||
287 | .name = "6000 Series 2x2 AGN", | ||
288 | .fw_name_pre = IWL6000_FW_PRE, | ||
289 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
290 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
291 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
292 | .ops = &iwl6000_ops, | ||
293 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
294 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
295 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
296 | .num_of_queues = IWL50_NUM_QUEUES, | ||
297 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
298 | .mod_params = &iwl50_mod_params, | ||
299 | .valid_tx_ant = ANT_AB, | ||
300 | .valid_rx_ant = ANT_AB, | ||
301 | .pll_cfg_val = 0, | ||
302 | .set_l0s = true, | ||
303 | .use_bsm = false, | ||
304 | .pa_type = IWL_PA_HYBRID, | ||
305 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
306 | .shadow_ram_support = true, | ||
307 | .ht_greenfield_support = true, | ||
308 | .led_compensation = 51, | ||
309 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
310 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
311 | .supports_idle = true, | ||
312 | .adv_thermal_throttle = true, | ||
313 | .support_ct_kill_exit = true, | ||
314 | }; | ||
315 | |||
316 | struct iwl_cfg iwl6000h_2abg_cfg = { | ||
317 | .name = "6000 Series 2x2 ABG", | ||
318 | .fw_name_pre = IWL6000_FW_PRE, | ||
319 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
320 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
321 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
322 | .ops = &iwl6000_ops, | ||
323 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
324 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
325 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
326 | .num_of_queues = IWL50_NUM_QUEUES, | ||
327 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
328 | .mod_params = &iwl50_mod_params, | ||
329 | .valid_tx_ant = ANT_AB, | ||
330 | .valid_rx_ant = ANT_AB, | ||
331 | .pll_cfg_val = 0, | ||
332 | .set_l0s = true, | ||
333 | .use_bsm = false, | ||
334 | .pa_type = IWL_PA_HYBRID, | ||
335 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
336 | .shadow_ram_support = true, | ||
337 | .ht_greenfield_support = true, | ||
338 | .led_compensation = 51, | ||
339 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
340 | .supports_idle = true, | ||
341 | .adv_thermal_throttle = true, | ||
342 | .support_ct_kill_exit = true, | ||
343 | }; | ||
344 | |||
345 | struct iwl_cfg iwl6000h_2bg_cfg = { | ||
346 | .name = "6000 Series 2x2 BG", | ||
347 | .fw_name_pre = IWL6000_FW_PRE, | ||
348 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
349 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
350 | .sku = IWL_SKU_G, | ||
351 | .ops = &iwl6000_ops, | ||
352 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
353 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
354 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
355 | .num_of_queues = IWL50_NUM_QUEUES, | ||
356 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
357 | .mod_params = &iwl50_mod_params, | ||
358 | .valid_tx_ant = ANT_AB, | ||
359 | .valid_rx_ant = ANT_AB, | ||
360 | .pll_cfg_val = 0, | ||
361 | .set_l0s = true, | ||
362 | .use_bsm = false, | ||
363 | .pa_type = IWL_PA_HYBRID, | ||
364 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
365 | .shadow_ram_support = true, | ||
366 | .ht_greenfield_support = true, | ||
367 | .led_compensation = 51, | ||
368 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
369 | .supports_idle = true, | ||
370 | .adv_thermal_throttle = true, | ||
371 | .support_ct_kill_exit = true, | ||
372 | }; | ||
373 | |||
374 | /* | 278 | /* |
375 | * "i": Internal configuration, use internal Power Amplifier | 279 | * "i": Internal configuration, use internal Power Amplifier |
376 | */ | 280 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b5fe8f87aa7e..da0b38e866ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -122,6 +122,17 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
122 | return -EINVAL; | 122 | return -EINVAL; |
123 | } | 123 | } |
124 | 124 | ||
125 | /* | ||
126 | * receive commit_rxon request | ||
127 | * abort any previous channel switch if still in process | ||
128 | */ | ||
129 | if (priv->switch_rxon.switch_in_progress && | ||
130 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { | ||
131 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", | ||
132 | le16_to_cpu(priv->switch_rxon.channel)); | ||
133 | priv->switch_rxon.switch_in_progress = false; | ||
134 | } | ||
135 | |||
125 | /* If we don't need to send a full RXON, we can use | 136 | /* If we don't need to send a full RXON, we can use |
126 | * iwl_rxon_assoc_cmd which is used to reconfigure filter | 137 | * iwl_rxon_assoc_cmd which is used to reconfigure filter |
127 | * and other flags for the current radio configuration. */ | 138 | * and other flags for the current radio configuration. */ |
@@ -133,6 +144,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
133 | } | 144 | } |
134 | 145 | ||
135 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 146 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
147 | iwl_print_rx_config_cmd(priv); | ||
136 | return 0; | 148 | return 0; |
137 | } | 149 | } |
138 | 150 | ||
@@ -228,6 +240,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
228 | } | 240 | } |
229 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 241 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
230 | } | 242 | } |
243 | iwl_print_rx_config_cmd(priv); | ||
231 | 244 | ||
232 | iwl_init_sensitivity(priv); | 245 | iwl_init_sensitivity(priv); |
233 | 246 | ||
@@ -1071,6 +1084,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1071 | u32 inta = 0; | 1084 | u32 inta = 0; |
1072 | u32 handled = 0; | 1085 | u32 handled = 0; |
1073 | unsigned long flags; | 1086 | unsigned long flags; |
1087 | u32 i; | ||
1074 | #ifdef CONFIG_IWLWIFI_DEBUG | 1088 | #ifdef CONFIG_IWLWIFI_DEBUG |
1075 | u32 inta_mask; | 1089 | u32 inta_mask; |
1076 | #endif | 1090 | #endif |
@@ -1181,12 +1195,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1181 | if (inta & CSR_INT_BIT_WAKEUP) { | 1195 | if (inta & CSR_INT_BIT_WAKEUP) { |
1182 | IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); | 1196 | IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); |
1183 | iwl_rx_queue_update_write_ptr(priv, &priv->rxq); | 1197 | iwl_rx_queue_update_write_ptr(priv, &priv->rxq); |
1184 | iwl_txq_update_write_ptr(priv, &priv->txq[0]); | 1198 | for (i = 0; i < priv->hw_params.max_txq_num; i++) |
1185 | iwl_txq_update_write_ptr(priv, &priv->txq[1]); | 1199 | iwl_txq_update_write_ptr(priv, &priv->txq[i]); |
1186 | iwl_txq_update_write_ptr(priv, &priv->txq[2]); | ||
1187 | iwl_txq_update_write_ptr(priv, &priv->txq[3]); | ||
1188 | iwl_txq_update_write_ptr(priv, &priv->txq[4]); | ||
1189 | iwl_txq_update_write_ptr(priv, &priv->txq[5]); | ||
1190 | 1200 | ||
1191 | priv->isr_stats.wakeup++; | 1201 | priv->isr_stats.wakeup++; |
1192 | 1202 | ||
@@ -1653,6 +1663,7 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1653 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | 1663 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ |
1654 | u32 ptr; /* SRAM byte address of log data */ | 1664 | u32 ptr; /* SRAM byte address of log data */ |
1655 | u32 ev, time, data; /* event log data */ | 1665 | u32 ev, time, data; /* event log data */ |
1666 | unsigned long reg_flags; | ||
1656 | 1667 | ||
1657 | if (num_events == 0) | 1668 | if (num_events == 0) |
1658 | return; | 1669 | return; |
@@ -1668,27 +1679,39 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1668 | 1679 | ||
1669 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | 1680 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); |
1670 | 1681 | ||
1682 | /* Make sure device is powered up for SRAM reads */ | ||
1683 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | ||
1684 | iwl_grab_nic_access(priv); | ||
1685 | |||
1686 | /* Set starting address; reads will auto-increment */ | ||
1687 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); | ||
1688 | rmb(); | ||
1689 | |||
1671 | /* "time" is actually "data" for mode 0 (no timestamp). | 1690 | /* "time" is actually "data" for mode 0 (no timestamp). |
1672 | * place event id # at far right for easier visual parsing. */ | 1691 | * place event id # at far right for easier visual parsing. */ |
1673 | for (i = 0; i < num_events; i++) { | 1692 | for (i = 0; i < num_events; i++) { |
1674 | ev = iwl_read_targ_mem(priv, ptr); | 1693 | ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1675 | ptr += sizeof(u32); | 1694 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1676 | time = iwl_read_targ_mem(priv, ptr); | ||
1677 | ptr += sizeof(u32); | ||
1678 | if (mode == 0) { | 1695 | if (mode == 0) { |
1679 | /* data, ev */ | 1696 | /* data, ev */ |
1680 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | 1697 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); |
1681 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); | 1698 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); |
1682 | } else { | 1699 | } else { |
1683 | data = iwl_read_targ_mem(priv, ptr); | 1700 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1684 | ptr += sizeof(u32); | ||
1685 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | 1701 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", |
1686 | time, data, ev); | 1702 | time, data, ev); |
1687 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | 1703 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); |
1688 | } | 1704 | } |
1689 | } | 1705 | } |
1706 | |||
1707 | /* Allow device to power down */ | ||
1708 | iwl_release_nic_access(priv); | ||
1709 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
1690 | } | 1710 | } |
1691 | 1711 | ||
1712 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | ||
1713 | #define MAX_EVENT_LOG_SIZE (512) | ||
1714 | |||
1692 | void iwl_dump_nic_event_log(struct iwl_priv *priv) | 1715 | void iwl_dump_nic_event_log(struct iwl_priv *priv) |
1693 | { | 1716 | { |
1694 | u32 base; /* SRAM byte address of event log header */ | 1717 | u32 base; /* SRAM byte address of event log header */ |
@@ -1714,6 +1737,18 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) | |||
1714 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 1737 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
1715 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 1738 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
1716 | 1739 | ||
1740 | if (capacity > MAX_EVENT_LOG_SIZE) { | ||
1741 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | ||
1742 | capacity, MAX_EVENT_LOG_SIZE); | ||
1743 | capacity = MAX_EVENT_LOG_SIZE; | ||
1744 | } | ||
1745 | |||
1746 | if (next_entry > MAX_EVENT_LOG_SIZE) { | ||
1747 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | ||
1748 | next_entry, MAX_EVENT_LOG_SIZE); | ||
1749 | next_entry = MAX_EVENT_LOG_SIZE; | ||
1750 | } | ||
1751 | |||
1717 | size = num_wraps ? capacity : next_entry; | 1752 | size = num_wraps ? capacity : next_entry; |
1718 | 1753 | ||
1719 | /* bail out if nothing in log */ | 1754 | /* bail out if nothing in log */ |
@@ -1899,19 +1934,17 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1899 | 1934 | ||
1900 | /* device going down, Stop using ICT table */ | 1935 | /* device going down, Stop using ICT table */ |
1901 | iwl_disable_ict(priv); | 1936 | iwl_disable_ict(priv); |
1902 | spin_lock_irqsave(&priv->lock, flags); | ||
1903 | iwl_clear_bit(priv, CSR_GP_CNTRL, | ||
1904 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
1905 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1906 | 1937 | ||
1907 | iwl_txq_ctx_stop(priv); | 1938 | iwl_txq_ctx_stop(priv); |
1908 | iwl_rxq_stop(priv); | 1939 | iwl_rxq_stop(priv); |
1909 | 1940 | ||
1910 | iwl_write_prph(priv, APMG_CLK_DIS_REG, | 1941 | /* Power-down device's busmaster DMA clocks */ |
1911 | APMG_CLK_VAL_DMA_CLK_RQT); | 1942 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); |
1912 | |||
1913 | udelay(5); | 1943 | udelay(5); |
1914 | 1944 | ||
1945 | /* Make sure (redundant) we've released our request to stay awake */ | ||
1946 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
1947 | |||
1915 | /* Stop the device, and put it in low power state */ | 1948 | /* Stop the device, and put it in low power state */ |
1916 | priv->cfg->ops->lib->apm_ops.stop(priv); | 1949 | priv->cfg->ops->lib->apm_ops.stop(priv); |
1917 | 1950 | ||
@@ -3439,14 +3472,6 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
3439 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3472 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, |
3440 | 3473 | ||
3441 | /* 6x00 Series */ | 3474 | /* 6x00 Series */ |
3442 | {IWL_PCI_DEVICE(0x008D, 0x1301, iwl6000h_2agn_cfg)}, | ||
3443 | {IWL_PCI_DEVICE(0x008D, 0x1321, iwl6000h_2agn_cfg)}, | ||
3444 | {IWL_PCI_DEVICE(0x008D, 0x1326, iwl6000h_2abg_cfg)}, | ||
3445 | {IWL_PCI_DEVICE(0x008D, 0x1306, iwl6000h_2abg_cfg)}, | ||
3446 | {IWL_PCI_DEVICE(0x008D, 0x1307, iwl6000h_2bg_cfg)}, | ||
3447 | {IWL_PCI_DEVICE(0x008E, 0x1311, iwl6000h_2agn_cfg)}, | ||
3448 | {IWL_PCI_DEVICE(0x008E, 0x1316, iwl6000h_2abg_cfg)}, | ||
3449 | |||
3450 | {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, | 3475 | {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, |
3451 | {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)}, | 3476 | {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)}, |
3452 | {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)}, | 3477 | {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index b62c90ec9e1e..2857287be4fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -2566,9 +2566,10 @@ struct iwl_scan_channel { | |||
2566 | /** | 2566 | /** |
2567 | * struct iwl_ssid_ie - directed scan network information element | 2567 | * struct iwl_ssid_ie - directed scan network information element |
2568 | * | 2568 | * |
2569 | * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field | 2569 | * Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in |
2570 | * in struct iwl_scan_channel; each channel may select different ssids from | 2570 | * 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel; |
2571 | * among the 4 entries. SSID IEs get transmitted in reverse order of entry. | 2571 | * each channel may select different ssids from among the 20 (4) entries. |
2572 | * SSID IEs get transmitted in reverse order of entry. | ||
2572 | */ | 2573 | */ |
2573 | struct iwl_ssid_ie { | 2574 | struct iwl_ssid_ie { |
2574 | u8 id; | 2575 | u8 id; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e0b5b4aef41d..d09e74815323 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -1316,19 +1316,24 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1316 | struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; | 1316 | struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; |
1317 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | 1317 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); |
1318 | 1318 | ||
1319 | if (!le32_to_cpu(csa->status)) { | 1319 | if (priv->switch_rxon.switch_in_progress) { |
1320 | rxon->channel = csa->channel; | 1320 | if (!le32_to_cpu(csa->status) && |
1321 | priv->staging_rxon.channel = csa->channel; | 1321 | (csa->channel == priv->switch_rxon.channel)) { |
1322 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | 1322 | rxon->channel = csa->channel; |
1323 | le16_to_cpu(csa->channel)); | 1323 | priv->staging_rxon.channel = csa->channel; |
1324 | } else | 1324 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", |
1325 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | 1325 | le16_to_cpu(csa->channel)); |
1326 | le16_to_cpu(csa->channel)); | 1326 | } else |
1327 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | ||
1328 | le16_to_cpu(csa->channel)); | ||
1329 | |||
1330 | priv->switch_rxon.switch_in_progress = false; | ||
1331 | } | ||
1327 | } | 1332 | } |
1328 | EXPORT_SYMBOL(iwl_rx_csa); | 1333 | EXPORT_SYMBOL(iwl_rx_csa); |
1329 | 1334 | ||
1330 | #ifdef CONFIG_IWLWIFI_DEBUG | 1335 | #ifdef CONFIG_IWLWIFI_DEBUG |
1331 | static void iwl_print_rx_config_cmd(struct iwl_priv *priv) | 1336 | void iwl_print_rx_config_cmd(struct iwl_priv *priv) |
1332 | { | 1337 | { |
1333 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 1338 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
1334 | 1339 | ||
@@ -1346,6 +1351,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv) | |||
1346 | IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); | 1351 | IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); |
1347 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); | 1352 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); |
1348 | } | 1353 | } |
1354 | EXPORT_SYMBOL(iwl_print_rx_config_cmd); | ||
1349 | #endif | 1355 | #endif |
1350 | /** | 1356 | /** |
1351 | * iwl_irq_handle_error - called for HW or SW error interrupt from card | 1357 | * iwl_irq_handle_error - called for HW or SW error interrupt from card |
@@ -2310,12 +2316,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
2310 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | 2316 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; |
2311 | maxstreams += 1; | 2317 | maxstreams += 1; |
2312 | 2318 | ||
2313 | ht_conf->sm_ps = | ||
2314 | (u8)((ht_cap->cap & IEEE80211_HT_CAP_SM_PS) | ||
2315 | >> 2); | ||
2316 | IWL_DEBUG_MAC80211(priv, "sm_ps: 0x%x\n", | ||
2317 | ht_conf->sm_ps); | ||
2318 | |||
2319 | if ((ht_cap->mcs.rx_mask[1] == 0) && | 2319 | if ((ht_cap->mcs.rx_mask[1] == 0) && |
2320 | (ht_cap->mcs.rx_mask[2] == 0)) | 2320 | (ht_cap->mcs.rx_mask[2] == 0)) |
2321 | ht_conf->single_chain_sufficient = true; | 2321 | ht_conf->single_chain_sufficient = true; |
@@ -2689,14 +2689,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2689 | goto set_ch_out; | 2689 | goto set_ch_out; |
2690 | } | 2690 | } |
2691 | 2691 | ||
2692 | if (iwl_is_associated(priv) && | ||
2693 | (le16_to_cpu(priv->active_rxon.channel) != ch) && | ||
2694 | priv->cfg->ops->lib->set_channel_switch) { | ||
2695 | ret = priv->cfg->ops->lib->set_channel_switch(priv, | ||
2696 | ch); | ||
2697 | goto out; | ||
2698 | } | ||
2699 | |||
2700 | spin_lock_irqsave(&priv->lock, flags); | 2692 | spin_lock_irqsave(&priv->lock, flags); |
2701 | 2693 | ||
2702 | /* Configure HT40 channels */ | 2694 | /* Configure HT40 channels */ |
@@ -2731,6 +2723,22 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2731 | 2723 | ||
2732 | iwl_set_flags_for_band(priv, conf->channel->band); | 2724 | iwl_set_flags_for_band(priv, conf->channel->band); |
2733 | spin_unlock_irqrestore(&priv->lock, flags); | 2725 | spin_unlock_irqrestore(&priv->lock, flags); |
2726 | if (iwl_is_associated(priv) && | ||
2727 | (le16_to_cpu(priv->active_rxon.channel) != ch) && | ||
2728 | priv->cfg->ops->lib->set_channel_switch) { | ||
2729 | iwl_set_rate(priv); | ||
2730 | /* | ||
2731 | * at this point, staging_rxon has the | ||
2732 | * configuration for channel switch | ||
2733 | */ | ||
2734 | ret = priv->cfg->ops->lib->set_channel_switch(priv, | ||
2735 | ch); | ||
2736 | if (!ret) { | ||
2737 | iwl_print_rx_config_cmd(priv); | ||
2738 | goto out; | ||
2739 | } | ||
2740 | priv->switch_rxon.switch_in_progress = false; | ||
2741 | } | ||
2734 | set_ch_out: | 2742 | set_ch_out: |
2735 | /* The list of supported rates and rate mask can be different | 2743 | /* The list of supported rates and rate mask can be different |
2736 | * for each band; since the band may have changed, reset | 2744 | * for each band; since the band may have changed, reset |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 9574d8f33537..3f97036ac29b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -579,6 +579,7 @@ int iwl_pci_resume(struct pci_dev *pdev); | |||
579 | #ifdef CONFIG_IWLWIFI_DEBUG | 579 | #ifdef CONFIG_IWLWIFI_DEBUG |
580 | void iwl_dump_nic_event_log(struct iwl_priv *priv); | 580 | void iwl_dump_nic_event_log(struct iwl_priv *priv); |
581 | void iwl_dump_nic_error_log(struct iwl_priv *priv); | 581 | void iwl_dump_nic_error_log(struct iwl_priv *priv); |
582 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); | ||
582 | #else | 583 | #else |
583 | static inline void iwl_dump_nic_event_log(struct iwl_priv *priv) | 584 | static inline void iwl_dump_nic_event_log(struct iwl_priv *priv) |
584 | { | 585 | { |
@@ -587,6 +588,10 @@ static inline void iwl_dump_nic_event_log(struct iwl_priv *priv) | |||
587 | static inline void iwl_dump_nic_error_log(struct iwl_priv *priv) | 588 | static inline void iwl_dump_nic_error_log(struct iwl_priv *priv) |
588 | { | 589 | { |
589 | } | 590 | } |
591 | |||
592 | static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv) | ||
593 | { | ||
594 | } | ||
590 | #endif | 595 | #endif |
591 | 596 | ||
592 | void iwl_clear_isr_stats(struct iwl_priv *priv); | 597 | void iwl_clear_isr_stats(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index cb2642c18da4..9dea8fa08c0e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -324,8 +324,9 @@ struct iwl_channel_info { | |||
324 | #define IWL_MIN_NUM_QUEUES 10 | 324 | #define IWL_MIN_NUM_QUEUES 10 |
325 | 325 | ||
326 | /* | 326 | /* |
327 | * uCode queue management definitions ... | 327 | * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00, |
328 | * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00. | 328 | * the driver maps it into the appropriate device FIFO for the |
329 | * uCode. | ||
329 | */ | 330 | */ |
330 | #define IWL_CMD_QUEUE_NUM 4 | 331 | #define IWL_CMD_QUEUE_NUM 4 |
331 | 332 | ||
@@ -926,13 +927,11 @@ enum iwl_access_mode { | |||
926 | /** | 927 | /** |
927 | * enum iwl_pa_type - Power Amplifier type | 928 | * enum iwl_pa_type - Power Amplifier type |
928 | * @IWL_PA_SYSTEM: based on uCode configuration | 929 | * @IWL_PA_SYSTEM: based on uCode configuration |
929 | * @IWL_PA_HYBRID: use both Internal and external PA | ||
930 | * @IWL_PA_INTERNAL: use Internal only | 930 | * @IWL_PA_INTERNAL: use Internal only |
931 | */ | 931 | */ |
932 | enum iwl_pa_type { | 932 | enum iwl_pa_type { |
933 | IWL_PA_SYSTEM = 0, | 933 | IWL_PA_SYSTEM = 0, |
934 | IWL_PA_HYBRID = 1, | 934 | IWL_PA_INTERNAL = 1, |
935 | IWL_PA_INTERNAL = 2, | ||
936 | }; | 935 | }; |
937 | 936 | ||
938 | /* interrupt statistics */ | 937 | /* interrupt statistics */ |
@@ -993,6 +992,17 @@ struct traffic_stats { | |||
993 | }; | 992 | }; |
994 | #endif | 993 | #endif |
995 | 994 | ||
995 | /* | ||
996 | * iwl_switch_rxon: "channel switch" structure | ||
997 | * | ||
998 | * @ switch_in_progress: channel switch in progress | ||
999 | * @ channel: new channel | ||
1000 | */ | ||
1001 | struct iwl_switch_rxon { | ||
1002 | bool switch_in_progress; | ||
1003 | __le16 channel; | ||
1004 | }; | ||
1005 | |||
996 | struct iwl_priv { | 1006 | struct iwl_priv { |
997 | 1007 | ||
998 | /* ieee device used by generic ieee processing code */ | 1008 | /* ieee device used by generic ieee processing code */ |
@@ -1086,7 +1096,7 @@ struct iwl_priv { | |||
1086 | const struct iwl_rxon_cmd active_rxon; | 1096 | const struct iwl_rxon_cmd active_rxon; |
1087 | struct iwl_rxon_cmd staging_rxon; | 1097 | struct iwl_rxon_cmd staging_rxon; |
1088 | 1098 | ||
1089 | struct iwl_rxon_cmd recovery_rxon; | 1099 | struct iwl_switch_rxon switch_rxon; |
1090 | 1100 | ||
1091 | /* 1st responses from initialize and runtime uCode images. | 1101 | /* 1st responses from initialize and runtime uCode images. |
1092 | * 4965's initialize alive response contains some calibration data. */ | 1102 | * 4965's initialize alive response contains some calibration data. */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 905645d15a9b..e8002c1d3eba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -199,13 +199,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { | 201 | if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { |
202 | IWL_DEBUG_INFO(priv, "Command %s aborted: RF KILL Switch\n", | 202 | IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", |
203 | get_cmd_string(cmd->id)); | 203 | get_cmd_string(cmd->id)); |
204 | ret = -ECANCELED; | 204 | ret = -ECANCELED; |
205 | goto fail; | 205 | goto fail; |
206 | } | 206 | } |
207 | if (test_bit(STATUS_FW_ERROR, &priv->status)) { | 207 | if (test_bit(STATUS_FW_ERROR, &priv->status)) { |
208 | IWL_DEBUG_INFO(priv, "Command %s failed: FW Error\n", | 208 | IWL_ERR(priv, "Command %s failed: FW Error\n", |
209 | get_cmd_string(cmd->id)); | 209 | get_cmd_string(cmd->id)); |
210 | ret = -EIO; | 210 | ret = -EIO; |
211 | goto fail; | 211 | goto fail; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 0a078b082833..d0a358c9d96b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -200,6 +200,26 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv) | |||
200 | 200 | ||
201 | /* this bit wakes up the NIC */ | 201 | /* this bit wakes up the NIC */ |
202 | _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 202 | _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
203 | |||
204 | /* | ||
205 | * These bits say the device is running, and should keep running for | ||
206 | * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), | ||
207 | * but they do not indicate that embedded SRAM is restored yet; | ||
208 | * 3945 and 4965 have volatile SRAM, and must save/restore contents | ||
209 | * to/from host DRAM when sleeping/waking for power-saving. | ||
210 | * Each direction takes approximately 1/4 millisecond; with this | ||
211 | * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a | ||
212 | * series of register accesses are expected (e.g. reading Event Log), | ||
213 | * to keep device from sleeping. | ||
214 | * | ||
215 | * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that | ||
216 | * SRAM is okay/restored. We don't check that here because this call | ||
217 | * is just for hardware register access; but GP1 MAC_SLEEP check is a | ||
218 | * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). | ||
219 | * | ||
220 | * 5000 series and later (including 1000 series) have non-volatile SRAM, | ||
221 | * and do not save/restore SRAM when power cycling. | ||
222 | */ | ||
203 | ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, | 223 | ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, |
204 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, | 224 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, |
205 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | 225 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index d393e8f02102..6d95832db06d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -254,7 +254,8 @@ | |||
254 | * device. A queue maps to only one (selectable by driver) Tx DMA channel, | 254 | * device. A queue maps to only one (selectable by driver) Tx DMA channel, |
255 | * but one DMA channel may take input from several queues. | 255 | * but one DMA channel may take input from several queues. |
256 | * | 256 | * |
257 | * Tx DMA channels have dedicated purposes. For 4965, they are used as follows: | 257 | * Tx DMA channels have dedicated purposes. For 4965, they are used as follows |
258 | * (cf. default_queue_to_tx_fifo in iwl-4965.c): | ||
258 | * | 259 | * |
259 | * 0 -- EDCA BK (background) frames, lowest priority | 260 | * 0 -- EDCA BK (background) frames, lowest priority |
260 | * 1 -- EDCA BE (best effort) frames, normal priority | 261 | * 1 -- EDCA BE (best effort) frames, normal priority |
@@ -265,9 +266,21 @@ | |||
265 | * 6 -- HCCA long frames | 266 | * 6 -- HCCA long frames |
266 | * 7 -- not used by driver (device-internal only) | 267 | * 7 -- not used by driver (device-internal only) |
267 | * | 268 | * |
269 | * For 5000 series and up, they are used slightly differently | ||
270 | * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): | ||
271 | * | ||
272 | * 0 -- EDCA BK (background) frames, lowest priority | ||
273 | * 1 -- EDCA BE (best effort) frames, normal priority | ||
274 | * 2 -- EDCA VI (video) frames, higher priority | ||
275 | * 3 -- EDCA VO (voice) and management frames, highest priority | ||
276 | * 4 -- (TBD) | ||
277 | * 5 -- HCCA short frames | ||
278 | * 6 -- HCCA long frames | ||
279 | * 7 -- Commands | ||
280 | * | ||
268 | * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. | 281 | * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. |
269 | * In addition, driver can map queues 7-15 to Tx DMA/FIFO channels 0-3 to | 282 | * In addition, driver can map the remaining queues to Tx DMA/FIFO |
270 | * support 11n aggregation via EDCA DMA channels. | 283 | * channels 0-3 to support 11n aggregation via EDCA DMA channels. |
271 | * | 284 | * |
272 | * The driver sets up each queue to work in one of two modes: | 285 | * The driver sets up each queue to work in one of two modes: |
273 | * | 286 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index e5339c9ad13e..61b3b0e6ed73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -140,6 +140,8 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | |||
140 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | 140 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); |
141 | 141 | ||
142 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 142 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
143 | IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n", | ||
144 | reg); | ||
143 | iwl_set_bit(priv, CSR_GP_CNTRL, | 145 | iwl_set_bit(priv, CSR_GP_CNTRL, |
144 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 146 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
145 | goto exit_unlock; | 147 | goto exit_unlock; |
@@ -937,12 +939,13 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
937 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | 939 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) |
938 | return; | 940 | return; |
939 | 941 | ||
940 | skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC); | 942 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); |
941 | if (!skb) { | 943 | if (!skb) { |
942 | IWL_ERR(priv, "alloc_skb failed\n"); | 944 | IWL_ERR(priv, "alloc_skb failed\n"); |
943 | return; | 945 | return; |
944 | } | 946 | } |
945 | 947 | ||
948 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
946 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | 949 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); |
947 | 950 | ||
948 | /* mac80211 currently doesn't support paged SKB. Convert it to | 951 | /* mac80211 currently doesn't support paged SKB. Convert it to |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 1eb0d0bf1fe4..a2b2b8315ff9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -581,6 +581,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
581 | u8 rate; | 581 | u8 rate; |
582 | bool is_active = false; | 582 | bool is_active = false; |
583 | int chan_mod; | 583 | int chan_mod; |
584 | u8 active_chains; | ||
584 | 585 | ||
585 | conf = ieee80211_get_hw_conf(priv->hw); | 586 | conf = ieee80211_get_hw_conf(priv->hw); |
586 | 587 | ||
@@ -734,9 +735,22 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
734 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | 735 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); |
735 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | 736 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); |
736 | 737 | ||
738 | /* In power save mode use one chain, otherwise use all chains */ | ||
739 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | ||
740 | /* rx_ant has been set to all valid chains previously */ | ||
741 | active_chains = rx_ant & | ||
742 | ((u8)(priv->chain_noise_data.active_chains)); | ||
743 | if (!active_chains) | ||
744 | active_chains = rx_ant; | ||
745 | |||
746 | IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", | ||
747 | priv->chain_noise_data.active_chains); | ||
748 | |||
749 | rx_ant = first_antenna(active_chains); | ||
750 | } | ||
737 | /* MIMO is not used here, but value is required */ | 751 | /* MIMO is not used here, but value is required */ |
738 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS; | 752 | rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; |
739 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 753 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
740 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | 754 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; |
741 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 755 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
742 | scan->rx_chain = cpu_to_le16(rx_chain); | 756 | scan->rx_chain = cpu_to_le16(rx_chain); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 05e75109d842..9370e062000d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -96,7 +96,8 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
96 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | 96 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); |
97 | 97 | ||
98 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 98 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
99 | IWL_DEBUG_INFO(priv, "Requesting wakeup, GP1 = 0x%x\n", reg); | 99 | IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", |
100 | txq_id, reg); | ||
100 | iwl_set_bit(priv, CSR_GP_CNTRL, | 101 | iwl_set_bit(priv, CSR_GP_CNTRL, |
101 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 102 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
102 | return ret; | 103 | return ret; |
@@ -364,8 +365,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
364 | 365 | ||
365 | txq->need_update = 0; | 366 | txq->need_update = 0; |
366 | 367 | ||
367 | /* aggregation TX queues will get their ID when aggregation begins */ | 368 | /* |
368 | if (txq_id <= IWL_TX_FIFO_AC3) | 369 | * Aggregation TX queues will get their ID when aggregation begins; |
370 | * they overwrite the setting done here. The command FIFO doesn't | ||
371 | * need an swq_id so don't set one to catch errors, all others can | ||
372 | * be set up to the identity mapping. | ||
373 | */ | ||
374 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
369 | txq->swq_id = txq_id; | 375 | txq->swq_id = txq_id; |
370 | 376 | ||
371 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | 377 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 23b31e6dcacd..05f118529fea 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1570,6 +1570,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1570 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | 1570 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ |
1571 | u32 ptr; /* SRAM byte address of log data */ | 1571 | u32 ptr; /* SRAM byte address of log data */ |
1572 | u32 ev, time, data; /* event log data */ | 1572 | u32 ev, time, data; /* event log data */ |
1573 | unsigned long reg_flags; | ||
1573 | 1574 | ||
1574 | if (num_events == 0) | 1575 | if (num_events == 0) |
1575 | return; | 1576 | return; |
@@ -1583,26 +1584,38 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1583 | 1584 | ||
1584 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | 1585 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); |
1585 | 1586 | ||
1587 | /* Make sure device is powered up for SRAM reads */ | ||
1588 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | ||
1589 | iwl_grab_nic_access(priv); | ||
1590 | |||
1591 | /* Set starting address; reads will auto-increment */ | ||
1592 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); | ||
1593 | rmb(); | ||
1594 | |||
1586 | /* "time" is actually "data" for mode 0 (no timestamp). | 1595 | /* "time" is actually "data" for mode 0 (no timestamp). |
1587 | * place event id # at far right for easier visual parsing. */ | 1596 | * place event id # at far right for easier visual parsing. */ |
1588 | for (i = 0; i < num_events; i++) { | 1597 | for (i = 0; i < num_events; i++) { |
1589 | ev = iwl_read_targ_mem(priv, ptr); | 1598 | ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1590 | ptr += sizeof(u32); | 1599 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1591 | time = iwl_read_targ_mem(priv, ptr); | ||
1592 | ptr += sizeof(u32); | ||
1593 | if (mode == 0) { | 1600 | if (mode == 0) { |
1594 | /* data, ev */ | 1601 | /* data, ev */ |
1595 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | 1602 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); |
1596 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | 1603 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); |
1597 | } else { | 1604 | } else { |
1598 | data = iwl_read_targ_mem(priv, ptr); | 1605 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1599 | ptr += sizeof(u32); | ||
1600 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); | 1606 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); |
1601 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | 1607 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); |
1602 | } | 1608 | } |
1603 | } | 1609 | } |
1610 | |||
1611 | /* Allow device to power down */ | ||
1612 | iwl_release_nic_access(priv); | ||
1613 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
1604 | } | 1614 | } |
1605 | 1615 | ||
1616 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | ||
1617 | #define IWL3945_MAX_EVENT_LOG_SIZE (512) | ||
1618 | |||
1606 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | 1619 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv) |
1607 | { | 1620 | { |
1608 | u32 base; /* SRAM byte address of event log header */ | 1621 | u32 base; /* SRAM byte address of event log header */ |
@@ -1624,6 +1637,18 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | |||
1624 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 1637 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
1625 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 1638 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
1626 | 1639 | ||
1640 | if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) { | ||
1641 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | ||
1642 | capacity, IWL3945_MAX_EVENT_LOG_SIZE); | ||
1643 | capacity = IWL3945_MAX_EVENT_LOG_SIZE; | ||
1644 | } | ||
1645 | |||
1646 | if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) { | ||
1647 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | ||
1648 | next_entry, IWL3945_MAX_EVENT_LOG_SIZE); | ||
1649 | next_entry = IWL3945_MAX_EVENT_LOG_SIZE; | ||
1650 | } | ||
1651 | |||
1627 | size = num_wraps ? capacity : next_entry; | 1652 | size = num_wraps ? capacity : next_entry; |
1628 | 1653 | ||
1629 | /* bail out if nothing in log */ | 1654 | /* bail out if nothing in log */ |
@@ -2575,9 +2600,8 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2575 | iwl3945_hw_txq_ctx_stop(priv); | 2600 | iwl3945_hw_txq_ctx_stop(priv); |
2576 | iwl3945_hw_rxq_stop(priv); | 2601 | iwl3945_hw_rxq_stop(priv); |
2577 | 2602 | ||
2578 | iwl_write_prph(priv, APMG_CLK_DIS_REG, | 2603 | /* Power-down device's busmaster DMA clocks */ |
2579 | APMG_CLK_VAL_DMA_CLK_RQT); | 2604 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); |
2580 | |||
2581 | udelay(5); | 2605 | udelay(5); |
2582 | 2606 | ||
2583 | /* Stop the device, and put it in low power state */ | 2607 | /* Stop the device, and put it in low power state */ |