diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 280 |
1 files changed, 88 insertions, 192 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6f703a041847..8972166386cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -45,6 +45,7 @@ | |||
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
46 | #include "iwl-calib.h" | 46 | #include "iwl-calib.h" |
47 | #include "iwl-sta.h" | 47 | #include "iwl-sta.h" |
48 | #include "iwl-agn-led.h" | ||
48 | 49 | ||
49 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 50 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
50 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | 51 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); |
@@ -62,8 +63,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | |||
62 | 63 | ||
63 | /* module parameters */ | 64 | /* module parameters */ |
64 | static struct iwl_mod_params iwl4965_mod_params = { | 65 | static struct iwl_mod_params iwl4965_mod_params = { |
65 | .num_of_queues = IWL49_NUM_QUEUES, | ||
66 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | ||
67 | .amsdu_size_8K = 1, | 66 | .amsdu_size_8K = 1, |
68 | .restart_fw = 1, | 67 | .restart_fw = 1, |
69 | /* the rest are 0 by default */ | 68 | /* the rest are 0 by default */ |
@@ -319,63 +318,13 @@ static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask) | |||
319 | iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); | 318 | iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); |
320 | } | 319 | } |
321 | 320 | ||
322 | static int iwl4965_apm_init(struct iwl_priv *priv) | ||
323 | { | ||
324 | int ret = 0; | ||
325 | |||
326 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
327 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
328 | |||
329 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | ||
330 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
331 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
332 | |||
333 | /* set "initialization complete" bit to move adapter | ||
334 | * D0U* --> D0A* state */ | ||
335 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
336 | |||
337 | /* wait for clock stabilization */ | ||
338 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
339 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
340 | if (ret < 0) { | ||
341 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
342 | goto out; | ||
343 | } | ||
344 | |||
345 | /* enable DMA */ | ||
346 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
347 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
348 | |||
349 | udelay(20); | ||
350 | |||
351 | /* disable L1-Active */ | ||
352 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
353 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
354 | |||
355 | out: | ||
356 | return ret; | ||
357 | } | ||
358 | |||
359 | |||
360 | static void iwl4965_nic_config(struct iwl_priv *priv) | 321 | static void iwl4965_nic_config(struct iwl_priv *priv) |
361 | { | 322 | { |
362 | unsigned long flags; | 323 | unsigned long flags; |
363 | u16 radio_cfg; | 324 | u16 radio_cfg; |
364 | u16 lctl; | ||
365 | 325 | ||
366 | spin_lock_irqsave(&priv->lock, flags); | 326 | spin_lock_irqsave(&priv->lock, flags); |
367 | 327 | ||
368 | lctl = iwl_pcie_link_ctl(priv); | ||
369 | |||
370 | /* HW bug W/A - negligible power consumption */ | ||
371 | /* L1-ASPM is enabled by BIOS */ | ||
372 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) | ||
373 | /* L1-ASPM enabled: disable L0S */ | ||
374 | iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
375 | else | ||
376 | /* L1-ASPM disabled: enable L0S */ | ||
377 | iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
378 | |||
379 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 328 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
380 | 329 | ||
381 | /* write radio config values to register */ | 330 | /* write radio config values to register */ |
@@ -396,79 +345,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv) | |||
396 | spin_unlock_irqrestore(&priv->lock, flags); | 345 | spin_unlock_irqrestore(&priv->lock, flags); |
397 | } | 346 | } |
398 | 347 | ||
399 | static int iwl4965_apm_stop_master(struct iwl_priv *priv) | ||
400 | { | ||
401 | unsigned long flags; | ||
402 | |||
403 | spin_lock_irqsave(&priv->lock, flags); | ||
404 | |||
405 | /* set stop master bit */ | ||
406 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
407 | |||
408 | iwl_poll_direct_bit(priv, CSR_RESET, | ||
409 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
410 | |||
411 | spin_unlock_irqrestore(&priv->lock, flags); | ||
412 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static void iwl4965_apm_stop(struct iwl_priv *priv) | ||
418 | { | ||
419 | unsigned long flags; | ||
420 | |||
421 | iwl4965_apm_stop_master(priv); | ||
422 | |||
423 | spin_lock_irqsave(&priv->lock, flags); | ||
424 | |||
425 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
426 | |||
427 | udelay(10); | ||
428 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
429 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
430 | spin_unlock_irqrestore(&priv->lock, flags); | ||
431 | } | ||
432 | |||
433 | static int iwl4965_apm_reset(struct iwl_priv *priv) | ||
434 | { | ||
435 | int ret = 0; | ||
436 | |||
437 | iwl4965_apm_stop_master(priv); | ||
438 | |||
439 | |||
440 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
441 | |||
442 | udelay(10); | ||
443 | |||
444 | /* FIXME: put here L1A -L0S w/a */ | ||
445 | |||
446 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
447 | |||
448 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
449 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
450 | if (ret < 0) | ||
451 | goto out; | ||
452 | |||
453 | udelay(10); | ||
454 | |||
455 | /* Enable DMA and BSM Clock */ | ||
456 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
457 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
458 | |||
459 | udelay(10); | ||
460 | |||
461 | /* disable L1A */ | ||
462 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
463 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
464 | |||
465 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | ||
466 | wake_up_interruptible(&priv->wait_command_queue); | ||
467 | |||
468 | out: | ||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. | 348 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. |
473 | * Called after every association, but this runs only once! | 349 | * Called after every association, but this runs only once! |
474 | * ... once chain noise is calibrated the first time, it's good forever. */ | 350 | * ... once chain noise is calibrated the first time, it's good forever. */ |
@@ -496,14 +372,15 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) | |||
496 | static void iwl4965_gain_computation(struct iwl_priv *priv, | 372 | static void iwl4965_gain_computation(struct iwl_priv *priv, |
497 | u32 *average_noise, | 373 | u32 *average_noise, |
498 | u16 min_average_noise_antenna_i, | 374 | u16 min_average_noise_antenna_i, |
499 | u32 min_average_noise) | 375 | u32 min_average_noise, |
376 | u8 default_chain) | ||
500 | { | 377 | { |
501 | int i, ret; | 378 | int i, ret; |
502 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 379 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
503 | 380 | ||
504 | data->delta_gain_code[min_average_noise_antenna_i] = 0; | 381 | data->delta_gain_code[min_average_noise_antenna_i] = 0; |
505 | 382 | ||
506 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 383 | for (i = default_chain; i < NUM_RX_CHAINS; i++) { |
507 | s32 delta_g = 0; | 384 | s32 delta_g = 0; |
508 | 385 | ||
509 | if (!(data->disconn_array[i]) && | 386 | if (!(data->disconn_array[i]) && |
@@ -557,18 +434,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
557 | data->beacon_count = 0; | 434 | data->beacon_count = 0; |
558 | } | 435 | } |
559 | 436 | ||
560 | static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
561 | __le32 *tx_flags) | ||
562 | { | ||
563 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
564 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
565 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
566 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
567 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
568 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | static void iwl4965_bg_txpower_work(struct work_struct *work) | 437 | static void iwl4965_bg_txpower_work(struct work_struct *work) |
573 | { | 438 | { |
574 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | 439 | struct iwl_priv *priv = container_of(work, struct iwl_priv, |
@@ -663,7 +528,8 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
663 | iwl_write_targ_mem(priv, a, 0); | 528 | iwl_write_targ_mem(priv, a, 0); |
664 | for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4) | 529 | for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4) |
665 | iwl_write_targ_mem(priv, a, 0); | 530 | iwl_write_targ_mem(priv, a, 0); |
666 | for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) | 531 | for (; a < priv->scd_base_addr + |
532 | IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
667 | iwl_write_targ_mem(priv, a, 0); | 533 | iwl_write_targ_mem(priv, a, 0); |
668 | 534 | ||
669 | /* Tel 4965 where to find Tx byte count tables */ | 535 | /* Tel 4965 where to find Tx byte count tables */ |
@@ -715,6 +581,13 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
715 | 581 | ||
716 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 582 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
717 | 583 | ||
584 | /* make sure all queue are not stopped */ | ||
585 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
586 | for (i = 0; i < 4; i++) | ||
587 | atomic_set(&priv->queue_stop_count[i], 0); | ||
588 | |||
589 | /* reset to 0 to enable all the queue first */ | ||
590 | priv->txq_ctx_active_msk = 0; | ||
718 | /* Map each Tx/cmd queue to its corresponding fifo */ | 591 | /* Map each Tx/cmd queue to its corresponding fifo */ |
719 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { | 592 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { |
720 | int ac = default_queue_to_tx_fifo[i]; | 593 | int ac = default_queue_to_tx_fifo[i]; |
@@ -748,6 +621,10 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = { | |||
748 | 621 | ||
749 | .nrg_th_cck = 100, | 622 | .nrg_th_cck = 100, |
750 | .nrg_th_ofdm = 100, | 623 | .nrg_th_ofdm = 100, |
624 | |||
625 | .barker_corr_th_min = 190, | ||
626 | .barker_corr_th_min_mrc = 390, | ||
627 | .nrg_th_cca = 62, | ||
751 | }; | 628 | }; |
752 | 629 | ||
753 | static void iwl4965_set_ct_threshold(struct iwl_priv *priv) | 630 | static void iwl4965_set_ct_threshold(struct iwl_priv *priv) |
@@ -764,19 +641,16 @@ static void iwl4965_set_ct_threshold(struct iwl_priv *priv) | |||
764 | */ | 641 | */ |
765 | static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | 642 | static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) |
766 | { | 643 | { |
644 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | ||
645 | priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES) | ||
646 | priv->cfg->num_of_queues = | ||
647 | priv->cfg->mod_params->num_of_queues; | ||
767 | 648 | ||
768 | if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) || | 649 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
769 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | ||
770 | IWL_ERR(priv, | ||
771 | "invalid queues_num, should be between %d and %d\n", | ||
772 | IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES); | ||
773 | return -EINVAL; | ||
774 | } | ||
775 | |||
776 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | ||
777 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; | 650 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; |
778 | priv->hw_params.scd_bc_tbls_size = | 651 | priv->hw_params.scd_bc_tbls_size = |
779 | IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); | 652 | priv->cfg->num_of_queues * |
653 | sizeof(struct iwl4965_scd_bc_tbl); | ||
780 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 654 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
781 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; | 655 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; |
782 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; | 656 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; |
@@ -787,10 +661,10 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
787 | 661 | ||
788 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | 662 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; |
789 | 663 | ||
790 | priv->hw_params.tx_chains_num = 2; | 664 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
791 | priv->hw_params.rx_chains_num = 2; | 665 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); |
792 | priv->hw_params.valid_tx_ant = ANT_A | ANT_B; | 666 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; |
793 | priv->hw_params.valid_rx_ant = ANT_A | ANT_B; | 667 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; |
794 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) | 668 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) |
795 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | 669 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); |
796 | 670 | ||
@@ -1337,7 +1211,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, | |||
1337 | iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); | 1211 | iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); |
1338 | 1212 | ||
1339 | /* calculate tx gain adjustment based on power supply voltage */ | 1213 | /* calculate tx gain adjustment based on power supply voltage */ |
1340 | voltage = priv->calib_info->voltage; | 1214 | voltage = le16_to_cpu(priv->calib_info->voltage); |
1341 | init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); | 1215 | init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); |
1342 | voltage_compensation = | 1216 | voltage_compensation = |
1343 | iwl4965_get_voltage_compensation(voltage, init_voltage); | 1217 | iwl4965_get_voltage_compensation(voltage, init_voltage); |
@@ -1567,14 +1441,13 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) | |||
1567 | return ret; | 1441 | return ret; |
1568 | } | 1442 | } |
1569 | 1443 | ||
1570 | #ifdef IEEE80211_CONF_CHANNEL_SWITCH | ||
1571 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 1444 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) |
1572 | { | 1445 | { |
1573 | int rc; | 1446 | int rc; |
1574 | u8 band = 0; | 1447 | u8 band = 0; |
1575 | bool is_ht40 = false; | 1448 | bool is_ht40 = false; |
1576 | u8 ctrl_chan_high = 0; | 1449 | u8 ctrl_chan_high = 0; |
1577 | struct iwl4965_channel_switch_cmd cmd = { 0 }; | 1450 | struct iwl4965_channel_switch_cmd cmd; |
1578 | const struct iwl_channel_info *ch_info; | 1451 | const struct iwl_channel_info *ch_info; |
1579 | 1452 | ||
1580 | band = priv->band == IEEE80211_BAND_2GHZ; | 1453 | band = priv->band == IEEE80211_BAND_2GHZ; |
@@ -1584,19 +1457,22 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1584 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); | 1457 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); |
1585 | 1458 | ||
1586 | if (is_ht40 && | 1459 | if (is_ht40 && |
1587 | (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) | 1460 | (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) |
1588 | ctrl_chan_high = 1; | 1461 | ctrl_chan_high = 1; |
1589 | 1462 | ||
1590 | cmd.band = band; | 1463 | cmd.band = band; |
1591 | cmd.expect_beacon = 0; | 1464 | cmd.expect_beacon = 0; |
1592 | cmd.channel = cpu_to_le16(channel); | 1465 | cmd.channel = cpu_to_le16(channel); |
1593 | cmd.rxon_flags = priv->active_rxon.flags; | 1466 | cmd.rxon_flags = priv->staging_rxon.flags; |
1594 | cmd.rxon_filter_flags = priv->active_rxon.filter_flags; | 1467 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
1595 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 1468 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); |
1596 | if (ch_info) | 1469 | if (ch_info) |
1597 | cmd.expect_beacon = is_channel_radar(ch_info); | 1470 | cmd.expect_beacon = is_channel_radar(ch_info); |
1598 | else | 1471 | else { |
1599 | cmd.expect_beacon = 1; | 1472 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
1473 | priv->active_rxon.channel, channel); | ||
1474 | return -EFAULT; | ||
1475 | } | ||
1600 | 1476 | ||
1601 | rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, | 1477 | rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, |
1602 | ctrl_chan_high, &cmd.tx_power); | 1478 | ctrl_chan_high, &cmd.tx_power); |
@@ -1605,10 +1481,11 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1605 | return rc; | 1481 | return rc; |
1606 | } | 1482 | } |
1607 | 1483 | ||
1608 | rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | 1484 | priv->switch_rxon.channel = cpu_to_le16(channel); |
1609 | return rc; | 1485 | priv->switch_rxon.switch_in_progress = true; |
1486 | |||
1487 | return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | ||
1610 | } | 1488 | } |
1611 | #endif | ||
1612 | 1489 | ||
1613 | /** | 1490 | /** |
1614 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | 1491 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
@@ -1805,11 +1682,13 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
1805 | u16 ssn_idx, u8 tx_fifo) | 1682 | u16 ssn_idx, u8 tx_fifo) |
1806 | { | 1683 | { |
1807 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1684 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1808 | (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { | 1685 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
1686 | <= txq_id)) { | ||
1809 | IWL_WARN(priv, | 1687 | IWL_WARN(priv, |
1810 | "queue number out of range: %d, must be %d to %d\n", | 1688 | "queue number out of range: %d, must be %d to %d\n", |
1811 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | 1689 | txq_id, IWL49_FIRST_AMPDU_QUEUE, |
1812 | IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); | 1690 | IWL49_FIRST_AMPDU_QUEUE + |
1691 | priv->cfg->num_of_ampdu_queues - 1); | ||
1813 | return -EINVAL; | 1692 | return -EINVAL; |
1814 | } | 1693 | } |
1815 | 1694 | ||
@@ -1870,11 +1749,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
1870 | u16 ra_tid; | 1749 | u16 ra_tid; |
1871 | 1750 | ||
1872 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1751 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1873 | (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { | 1752 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
1753 | <= txq_id)) { | ||
1874 | IWL_WARN(priv, | 1754 | IWL_WARN(priv, |
1875 | "queue number out of range: %d, must be %d to %d\n", | 1755 | "queue number out of range: %d, must be %d to %d\n", |
1876 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | 1756 | txq_id, IWL49_FIRST_AMPDU_QUEUE, |
1877 | IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); | 1757 | IWL49_FIRST_AMPDU_QUEUE + |
1758 | priv->cfg->num_of_ampdu_queues - 1); | ||
1878 | return -EINVAL; | 1759 | return -EINVAL; |
1879 | } | 1760 | } |
1880 | 1761 | ||
@@ -1944,8 +1825,9 @@ static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | |||
1944 | addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; | 1825 | addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; |
1945 | addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; | 1826 | addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; |
1946 | addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; | 1827 | addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; |
1828 | addsta->sleep_tx_count = cmd->sleep_tx_count; | ||
1947 | addsta->reserved1 = cpu_to_le16(0); | 1829 | addsta->reserved1 = cpu_to_le16(0); |
1948 | addsta->reserved2 = cpu_to_le32(0); | 1830 | addsta->reserved2 = cpu_to_le16(0); |
1949 | 1831 | ||
1950 | return (u16)sizeof(struct iwl4965_addsta_cmd); | 1832 | return (u16)sizeof(struct iwl4965_addsta_cmd); |
1951 | } | 1833 | } |
@@ -1991,8 +1873,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1991 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 1873 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); |
1992 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1874 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1993 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1875 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1994 | info->flags |= iwl_is_tx_success(status) ? | 1876 | info->flags |= iwl_tx_status_to_mac80211(status); |
1995 | IEEE80211_TX_STAT_ACK : 0; | ||
1996 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 1877 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); |
1997 | /* FIXME: code repetition end */ | 1878 | /* FIXME: code repetition end */ |
1998 | 1879 | ||
@@ -2078,7 +1959,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
2078 | static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | 1959 | static void iwl4965_rx_reply_tx(struct iwl_priv *priv, |
2079 | struct iwl_rx_mem_buffer *rxb) | 1960 | struct iwl_rx_mem_buffer *rxb) |
2080 | { | 1961 | { |
2081 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1962 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2082 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 1963 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
2083 | int txq_id = SEQ_TO_QUEUE(sequence); | 1964 | int txq_id = SEQ_TO_QUEUE(sequence); |
2084 | int index = SEQ_TO_INDEX(sequence); | 1965 | int index = SEQ_TO_INDEX(sequence); |
@@ -2087,7 +1968,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2087 | struct ieee80211_tx_info *info; | 1968 | struct ieee80211_tx_info *info; |
2088 | struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | 1969 | struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; |
2089 | u32 status = le32_to_cpu(tx_resp->u.status); | 1970 | u32 status = le32_to_cpu(tx_resp->u.status); |
2090 | int tid = MAX_TID_COUNT; | 1971 | int uninitialized_var(tid); |
2091 | int sta_id; | 1972 | int sta_id; |
2092 | int freed; | 1973 | int freed; |
2093 | u8 *qc = NULL; | 1974 | u8 *qc = NULL; |
@@ -2134,7 +2015,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2134 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " | 2015 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " |
2135 | "%d index %d\n", scd_ssn , index); | 2016 | "%d index %d\n", scd_ssn , index); |
2136 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2017 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
2137 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | 2018 | if (qc) |
2019 | iwl_free_tfds_in_queue(priv, sta_id, | ||
2020 | tid, freed); | ||
2138 | 2021 | ||
2139 | if (priv->mac80211_registered && | 2022 | if (priv->mac80211_registered && |
2140 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | 2023 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && |
@@ -2147,8 +2030,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2147 | } | 2030 | } |
2148 | } else { | 2031 | } else { |
2149 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 2032 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
2150 | info->flags |= iwl_is_tx_success(status) ? | 2033 | info->flags |= iwl_tx_status_to_mac80211(status); |
2151 | IEEE80211_TX_STAT_ACK : 0; | ||
2152 | iwl_hwrate_to_tx_control(priv, | 2034 | iwl_hwrate_to_tx_control(priv, |
2153 | le32_to_cpu(tx_resp->rate_n_flags), | 2035 | le32_to_cpu(tx_resp->rate_n_flags), |
2154 | info); | 2036 | info); |
@@ -2162,13 +2044,14 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2162 | 2044 | ||
2163 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2045 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
2164 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | 2046 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
2165 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | 2047 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
2048 | else if (sta_id == IWL_INVALID_STATION) | ||
2049 | IWL_DEBUG_TX_REPLY(priv, "Station not known\n"); | ||
2166 | 2050 | ||
2167 | if (priv->mac80211_registered && | 2051 | if (priv->mac80211_registered && |
2168 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | 2052 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) |
2169 | iwl_wake_queue(priv, txq_id); | 2053 | iwl_wake_queue(priv, txq_id); |
2170 | } | 2054 | } |
2171 | |||
2172 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | 2055 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
2173 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | 2056 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); |
2174 | 2057 | ||
@@ -2279,7 +2162,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | |||
2279 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | 2162 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, |
2280 | .chain_noise_reset = iwl4965_chain_noise_reset, | 2163 | .chain_noise_reset = iwl4965_chain_noise_reset, |
2281 | .gain_computation = iwl4965_gain_computation, | 2164 | .gain_computation = iwl4965_gain_computation, |
2282 | .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, | 2165 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, |
2283 | .calc_rssi = iwl4965_calc_rssi, | 2166 | .calc_rssi = iwl4965_calc_rssi, |
2284 | }; | 2167 | }; |
2285 | 2168 | ||
@@ -2301,10 +2184,10 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2301 | .load_ucode = iwl4965_load_bsm, | 2184 | .load_ucode = iwl4965_load_bsm, |
2302 | .dump_nic_event_log = iwl_dump_nic_event_log, | 2185 | .dump_nic_event_log = iwl_dump_nic_event_log, |
2303 | .dump_nic_error_log = iwl_dump_nic_error_log, | 2186 | .dump_nic_error_log = iwl_dump_nic_error_log, |
2187 | .set_channel_switch = iwl4965_hw_channel_switch, | ||
2304 | .apm_ops = { | 2188 | .apm_ops = { |
2305 | .init = iwl4965_apm_init, | 2189 | .init = iwl_apm_init, |
2306 | .reset = iwl4965_apm_reset, | 2190 | .stop = iwl_apm_stop, |
2307 | .stop = iwl4965_apm_stop, | ||
2308 | .config = iwl4965_nic_config, | 2191 | .config = iwl4965_nic_config, |
2309 | .set_pwr_src = iwl_set_pwr_src, | 2192 | .set_pwr_src = iwl_set_pwr_src, |
2310 | }, | 2193 | }, |
@@ -2333,13 +2216,15 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2333 | .temperature = iwl4965_temperature_calib, | 2216 | .temperature = iwl4965_temperature_calib, |
2334 | .set_ct_kill = iwl4965_set_ct_threshold, | 2217 | .set_ct_kill = iwl4965_set_ct_threshold, |
2335 | }, | 2218 | }, |
2219 | .add_bcast_station = iwl_add_bcast_station, | ||
2336 | }; | 2220 | }; |
2337 | 2221 | ||
2338 | static struct iwl_ops iwl4965_ops = { | 2222 | static const struct iwl_ops iwl4965_ops = { |
2339 | .ucode = &iwl4965_ucode, | 2223 | .ucode = &iwl4965_ucode, |
2340 | .lib = &iwl4965_lib, | 2224 | .lib = &iwl4965_lib, |
2341 | .hcmd = &iwl4965_hcmd, | 2225 | .hcmd = &iwl4965_hcmd, |
2342 | .utils = &iwl4965_hcmd_utils, | 2226 | .utils = &iwl4965_hcmd_utils, |
2227 | .led = &iwlagn_led_ops, | ||
2343 | }; | 2228 | }; |
2344 | 2229 | ||
2345 | struct iwl_cfg iwl4965_agn_cfg = { | 2230 | struct iwl_cfg iwl4965_agn_cfg = { |
@@ -2352,30 +2237,41 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2352 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, | 2237 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, |
2353 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, | 2238 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, |
2354 | .ops = &iwl4965_ops, | 2239 | .ops = &iwl4965_ops, |
2240 | .num_of_queues = IWL49_NUM_QUEUES, | ||
2241 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | ||
2355 | .mod_params = &iwl4965_mod_params, | 2242 | .mod_params = &iwl4965_mod_params, |
2243 | .valid_tx_ant = ANT_AB, | ||
2244 | .valid_rx_ant = ANT_ABC, | ||
2245 | .pll_cfg_val = 0, | ||
2246 | .set_l0s = true, | ||
2247 | .use_bsm = true, | ||
2356 | .use_isr_legacy = true, | 2248 | .use_isr_legacy = true, |
2357 | .ht_greenfield_support = false, | 2249 | .ht_greenfield_support = false, |
2358 | .broken_powersave = true, | 2250 | .broken_powersave = true, |
2251 | .led_compensation = 61, | ||
2252 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | ||
2253 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2359 | }; | 2254 | }; |
2360 | 2255 | ||
2361 | /* Module firmware */ | 2256 | /* Module firmware */ |
2362 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); | 2257 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); |
2363 | 2258 | ||
2364 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); | 2259 | module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO); |
2365 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 2260 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
2366 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); | 2261 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO); |
2367 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | 2262 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); |
2368 | module_param_named( | 2263 | module_param_named( |
2369 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); | 2264 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO); |
2370 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 2265 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
2371 | 2266 | ||
2372 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); | 2267 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO); |
2373 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | 2268 | MODULE_PARM_DESC(queues_num, "number of hw queues."); |
2374 | /* 11n */ | 2269 | /* 11n */ |
2375 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444); | 2270 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO); |
2376 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | 2271 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); |
2377 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); | 2272 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, |
2273 | int, S_IRUGO); | ||
2378 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | 2274 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); |
2379 | 2275 | ||
2380 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444); | 2276 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO); |
2381 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); | 2277 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); |