diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-07-13 15:57:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-07-13 15:57:29 -0400 |
commit | e300d955debdadf599c36e47eb0bc16f5976215c (patch) | |
tree | 8fafcc789dc06e90665e6eee6388af228bbd2fd7 /drivers/net/wireless/iwlwifi | |
parent | 242647bcf8464860f173f3d4d4ab3490d3558518 (diff) | |
parent | 815868e7b5c207ba42d5b317ccc51f8112732268 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/wl12xx/wl1271_cmd.h
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
20 files changed, 583 insertions, 105 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 6491e27baac5..a51e4da1bdfc 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -87,10 +87,15 @@ config IWL4965 | |||
87 | This option enables support for Intel Wireless WiFi Link 4965AGN | 87 | This option enables support for Intel Wireless WiFi Link 4965AGN |
88 | 88 | ||
89 | config IWL5000 | 89 | config IWL5000 |
90 | bool "Intel Wireless WiFi 5000AGN; Intel WiFi Link 1000, 6000, and 6050 Series" | 90 | bool "Intel Wireless-N/Advanced-N/Ultimate-N WiFi Link" |
91 | depends on IWLAGN | 91 | depends on IWLAGN |
92 | ---help--- | 92 | ---help--- |
93 | This option enables support for Intel Wireless WiFi Link 5000AGN Family | 93 | This option enables support for use with the following hardware: |
94 | Intel Wireless WiFi Link 6250AGN Adapter | ||
95 | Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN) | ||
96 | Intel WiFi Link 1000BGN | ||
97 | Intel Wireless WiFi 5150AGN | ||
98 | Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN | ||
94 | 99 | ||
95 | config IWL3945 | 100 | config IWL3945 |
96 | tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)" | 101 | tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)" |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 1daf159914ad..c281d07ec5e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -129,8 +129,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
129 | priv->cfg->num_of_queues * | 129 | priv->cfg->num_of_queues * |
130 | sizeof(struct iwlagn_scd_bc_tbl); | 130 | sizeof(struct iwlagn_scd_bc_tbl); |
131 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 131 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
132 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 132 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; |
133 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 133 | priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID; |
134 | 134 | ||
135 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; | 135 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
136 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; | 136 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
@@ -226,6 +226,8 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
226 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 226 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
227 | .check_plcp_health = iwl_good_plcp_health, | 227 | .check_plcp_health = iwl_good_plcp_health, |
228 | .check_ack_health = iwl_good_ack_health, | 228 | .check_ack_health = iwl_good_ack_health, |
229 | .txfifo_flush = iwlagn_txfifo_flush, | ||
230 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | ||
229 | }; | 231 | }; |
230 | 232 | ||
231 | static const struct iwl_ops iwl1000_ops = { | 233 | static const struct iwl_ops iwl1000_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index b8f3e20f2c80..7d89d99ce19c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -179,8 +179,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
179 | priv->cfg->num_of_queues * | 179 | priv->cfg->num_of_queues * |
180 | sizeof(struct iwlagn_scd_bc_tbl); | 180 | sizeof(struct iwlagn_scd_bc_tbl); |
181 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 181 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
182 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 182 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; |
183 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 183 | priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID; |
184 | 184 | ||
185 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; | 185 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
186 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; | 186 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
@@ -226,8 +226,8 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |||
226 | priv->cfg->num_of_queues * | 226 | priv->cfg->num_of_queues * |
227 | sizeof(struct iwlagn_scd_bc_tbl); | 227 | sizeof(struct iwlagn_scd_bc_tbl); |
228 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 228 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
229 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 229 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; |
230 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 230 | priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID; |
231 | 231 | ||
232 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; | 232 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
233 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; | 233 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
@@ -402,6 +402,8 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
402 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 402 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
403 | .check_plcp_health = iwl_good_plcp_health, | 403 | .check_plcp_health = iwl_good_plcp_health, |
404 | .check_ack_health = iwl_good_ack_health, | 404 | .check_ack_health = iwl_good_ack_health, |
405 | .txfifo_flush = iwlagn_txfifo_flush, | ||
406 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | ||
405 | }; | 407 | }; |
406 | 408 | ||
407 | static struct iwl_lib_ops iwl5150_lib = { | 409 | static struct iwl_lib_ops iwl5150_lib = { |
@@ -465,6 +467,8 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
465 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 467 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
466 | .check_plcp_health = iwl_good_plcp_health, | 468 | .check_plcp_health = iwl_good_plcp_health, |
467 | .check_ack_health = iwl_good_ack_health, | 469 | .check_ack_health = iwl_good_ack_health, |
470 | .txfifo_flush = iwlagn_txfifo_flush, | ||
471 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | ||
468 | }; | 472 | }; |
469 | 473 | ||
470 | static const struct iwl_ops iwl5000_ops = { | 474 | static const struct iwl_ops iwl5000_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 8577664da77c..095521952bbe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -160,8 +160,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
160 | priv->cfg->num_of_queues * | 160 | priv->cfg->num_of_queues * |
161 | sizeof(struct iwlagn_scd_bc_tbl); | 161 | sizeof(struct iwlagn_scd_bc_tbl); |
162 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 162 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
163 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 163 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; |
164 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 164 | priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID; |
165 | 165 | ||
166 | priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; | 166 | priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; |
167 | priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; | 167 | priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; |
@@ -327,6 +327,8 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
327 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 327 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
328 | .check_plcp_health = iwl_good_plcp_health, | 328 | .check_plcp_health = iwl_good_plcp_health, |
329 | .check_ack_health = iwl_good_ack_health, | 329 | .check_ack_health = iwl_good_ack_health, |
330 | .txfifo_flush = iwlagn_txfifo_flush, | ||
331 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | ||
330 | }; | 332 | }; |
331 | 333 | ||
332 | static const struct iwl_ops iwl6000_ops = { | 334 | static const struct iwl_ops iwl6000_ops = { |
@@ -827,6 +829,44 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
827 | .need_dc_calib = true, | 829 | .need_dc_calib = true, |
828 | }; | 830 | }; |
829 | 831 | ||
832 | struct iwl_cfg iwl6050g2_bgn_cfg = { | ||
833 | .name = "6050 Series 1x2 BGN Gen2", | ||
834 | .fw_name_pre = IWL6050_FW_PRE, | ||
835 | .ucode_api_max = IWL6050_UCODE_API_MAX, | ||
836 | .ucode_api_min = IWL6050_UCODE_API_MIN, | ||
837 | .sku = IWL_SKU_G|IWL_SKU_N, | ||
838 | .ops = &iwl6000_ops, | ||
839 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
840 | .eeprom_ver = EEPROM_6050G2_EEPROM_VERSION, | ||
841 | .eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION, | ||
842 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
843 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
844 | .mod_params = &iwlagn_mod_params, | ||
845 | .valid_tx_ant = ANT_A, | ||
846 | .valid_rx_ant = ANT_AB, | ||
847 | .pll_cfg_val = 0, | ||
848 | .set_l0s = true, | ||
849 | .use_bsm = false, | ||
850 | .pa_type = IWL_PA_SYSTEM, | ||
851 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | ||
852 | .shadow_ram_support = true, | ||
853 | .ht_greenfield_support = true, | ||
854 | .led_compensation = 51, | ||
855 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
856 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
857 | .supports_idle = true, | ||
858 | .adv_thermal_throttle = true, | ||
859 | .support_ct_kill_exit = true, | ||
860 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
861 | .chain_noise_scale = 1500, | ||
862 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
863 | .max_event_log_size = 1024, | ||
864 | .ucode_tracing = true, | ||
865 | .sensitivity_calib_by_driver = true, | ||
866 | .chain_noise_calib_by_driver = true, | ||
867 | .need_dc_calib = true, | ||
868 | }; | ||
869 | |||
830 | struct iwl_cfg iwl6050_2abg_cfg = { | 870 | struct iwl_cfg iwl6050_2abg_cfg = { |
831 | .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG", | 871 | .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG", |
832 | .fw_name_pre = IWL6050_FW_PRE, | 872 | .fw_name_pre = IWL6050_FW_PRE, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index eb052b05e790..90033e8752bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -409,46 +409,34 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, | |||
409 | return 0; | 409 | return 0; |
410 | } | 410 | } |
411 | 411 | ||
412 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ | 412 | static void iwl_prepare_legacy_sensitivity_tbl(struct iwl_priv *priv, |
413 | static int iwl_sensitivity_write(struct iwl_priv *priv) | 413 | struct iwl_sensitivity_data *data, |
414 | __le16 *tbl) | ||
414 | { | 415 | { |
415 | struct iwl_sensitivity_cmd cmd ; | 416 | tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] = |
416 | struct iwl_sensitivity_data *data = NULL; | ||
417 | struct iwl_host_cmd cmd_out = { | ||
418 | .id = SENSITIVITY_CMD, | ||
419 | .len = sizeof(struct iwl_sensitivity_cmd), | ||
420 | .flags = CMD_ASYNC, | ||
421 | .data = &cmd, | ||
422 | }; | ||
423 | |||
424 | data = &(priv->sensitivity_data); | ||
425 | |||
426 | memset(&cmd, 0, sizeof(cmd)); | ||
427 | |||
428 | cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] = | ||
429 | cpu_to_le16((u16)data->auto_corr_ofdm); | 417 | cpu_to_le16((u16)data->auto_corr_ofdm); |
430 | cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] = | 418 | tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] = |
431 | cpu_to_le16((u16)data->auto_corr_ofdm_mrc); | 419 | cpu_to_le16((u16)data->auto_corr_ofdm_mrc); |
432 | cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] = | 420 | tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] = |
433 | cpu_to_le16((u16)data->auto_corr_ofdm_x1); | 421 | cpu_to_le16((u16)data->auto_corr_ofdm_x1); |
434 | cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] = | 422 | tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] = |
435 | cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1); | 423 | cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1); |
436 | 424 | ||
437 | cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] = | 425 | tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] = |
438 | cpu_to_le16((u16)data->auto_corr_cck); | 426 | cpu_to_le16((u16)data->auto_corr_cck); |
439 | cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] = | 427 | tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] = |
440 | cpu_to_le16((u16)data->auto_corr_cck_mrc); | 428 | cpu_to_le16((u16)data->auto_corr_cck_mrc); |
441 | 429 | ||
442 | cmd.table[HD_MIN_ENERGY_CCK_DET_INDEX] = | 430 | tbl[HD_MIN_ENERGY_CCK_DET_INDEX] = |
443 | cpu_to_le16((u16)data->nrg_th_cck); | 431 | cpu_to_le16((u16)data->nrg_th_cck); |
444 | cmd.table[HD_MIN_ENERGY_OFDM_DET_INDEX] = | 432 | tbl[HD_MIN_ENERGY_OFDM_DET_INDEX] = |
445 | cpu_to_le16((u16)data->nrg_th_ofdm); | 433 | cpu_to_le16((u16)data->nrg_th_ofdm); |
446 | 434 | ||
447 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] = | 435 | tbl[HD_BARKER_CORR_TH_ADD_MIN_INDEX] = |
448 | cpu_to_le16(data->barker_corr_th_min); | 436 | cpu_to_le16(data->barker_corr_th_min); |
449 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] = | 437 | tbl[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] = |
450 | cpu_to_le16(data->barker_corr_th_min_mrc); | 438 | cpu_to_le16(data->barker_corr_th_min_mrc); |
451 | cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] = | 439 | tbl[HD_OFDM_ENERGY_TH_IN_INDEX] = |
452 | cpu_to_le16(data->nrg_th_cca); | 440 | cpu_to_le16(data->nrg_th_cca); |
453 | 441 | ||
454 | IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", | 442 | IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", |
@@ -459,6 +447,25 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) | |||
459 | IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n", | 447 | IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n", |
460 | data->auto_corr_cck, data->auto_corr_cck_mrc, | 448 | data->auto_corr_cck, data->auto_corr_cck_mrc, |
461 | data->nrg_th_cck); | 449 | data->nrg_th_cck); |
450 | } | ||
451 | |||
452 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ | ||
453 | static int iwl_sensitivity_write(struct iwl_priv *priv) | ||
454 | { | ||
455 | struct iwl_sensitivity_cmd cmd; | ||
456 | struct iwl_sensitivity_data *data = NULL; | ||
457 | struct iwl_host_cmd cmd_out = { | ||
458 | .id = SENSITIVITY_CMD, | ||
459 | .len = sizeof(struct iwl_sensitivity_cmd), | ||
460 | .flags = CMD_ASYNC, | ||
461 | .data = &cmd, | ||
462 | }; | ||
463 | |||
464 | data = &(priv->sensitivity_data); | ||
465 | |||
466 | memset(&cmd, 0, sizeof(cmd)); | ||
467 | |||
468 | iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.table[0]); | ||
462 | 469 | ||
463 | /* Update uCode's "work" table, and copy it to DSP */ | 470 | /* Update uCode's "work" table, and copy it to DSP */ |
464 | cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE; | 471 | cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE; |
@@ -477,6 +484,70 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) | |||
477 | return iwl_send_cmd(priv, &cmd_out); | 484 | return iwl_send_cmd(priv, &cmd_out); |
478 | } | 485 | } |
479 | 486 | ||
487 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ | ||
488 | static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) | ||
489 | { | ||
490 | struct iwl_enhance_sensitivity_cmd cmd; | ||
491 | struct iwl_sensitivity_data *data = NULL; | ||
492 | struct iwl_host_cmd cmd_out = { | ||
493 | .id = SENSITIVITY_CMD, | ||
494 | .len = sizeof(struct iwl_enhance_sensitivity_cmd), | ||
495 | .flags = CMD_ASYNC, | ||
496 | .data = &cmd, | ||
497 | }; | ||
498 | |||
499 | data = &(priv->sensitivity_data); | ||
500 | |||
501 | memset(&cmd, 0, sizeof(cmd)); | ||
502 | |||
503 | iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]); | ||
504 | |||
505 | cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] = | ||
506 | HD_INA_NON_SQUARE_DET_OFDM_DATA; | ||
507 | cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] = | ||
508 | HD_INA_NON_SQUARE_DET_CCK_DATA; | ||
509 | cmd.enhance_table[HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX] = | ||
510 | HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA; | ||
511 | cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX] = | ||
512 | HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA; | ||
513 | cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] = | ||
514 | HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA; | ||
515 | cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX] = | ||
516 | HD_OFDM_NON_SQUARE_DET_SLOPE_DATA; | ||
517 | cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX] = | ||
518 | HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA; | ||
519 | cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX] = | ||
520 | HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA; | ||
521 | cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] = | ||
522 | HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA; | ||
523 | cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_INDEX] = | ||
524 | HD_CCK_NON_SQUARE_DET_SLOPE_DATA; | ||
525 | cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX] = | ||
526 | HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA; | ||
527 | |||
528 | /* Update uCode's "work" table, and copy it to DSP */ | ||
529 | cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE; | ||
530 | |||
531 | /* Don't send command to uCode if nothing has changed */ | ||
532 | if (!memcmp(&cmd.enhance_table[0], &(priv->sensitivity_tbl[0]), | ||
533 | sizeof(u16)*HD_TABLE_SIZE) && | ||
534 | !memcmp(&cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX], | ||
535 | &(priv->enhance_sensitivity_tbl[0]), | ||
536 | sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES)) { | ||
537 | IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n"); | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | /* Copy table for comparison next time */ | ||
542 | memcpy(&(priv->sensitivity_tbl[0]), &(cmd.enhance_table[0]), | ||
543 | sizeof(u16)*HD_TABLE_SIZE); | ||
544 | memcpy(&(priv->enhance_sensitivity_tbl[0]), | ||
545 | &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), | ||
546 | sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); | ||
547 | |||
548 | return iwl_send_cmd(priv, &cmd_out); | ||
549 | } | ||
550 | |||
480 | void iwl_init_sensitivity(struct iwl_priv *priv) | 551 | void iwl_init_sensitivity(struct iwl_priv *priv) |
481 | { | 552 | { |
482 | int ret = 0; | 553 | int ret = 0; |
@@ -527,7 +598,10 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
527 | data->last_bad_plcp_cnt_cck = 0; | 598 | data->last_bad_plcp_cnt_cck = 0; |
528 | data->last_fa_cnt_cck = 0; | 599 | data->last_fa_cnt_cck = 0; |
529 | 600 | ||
530 | ret |= iwl_sensitivity_write(priv); | 601 | if (priv->enhance_sensitivity_table) |
602 | ret |= iwl_enhance_sensitivity_write(priv); | ||
603 | else | ||
604 | ret |= iwl_sensitivity_write(priv); | ||
531 | IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); | 605 | IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); |
532 | } | 606 | } |
533 | 607 | ||
@@ -633,7 +707,10 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, | |||
633 | 707 | ||
634 | iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); | 708 | iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); |
635 | iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); | 709 | iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); |
636 | iwl_sensitivity_write(priv); | 710 | if (priv->enhance_sensitivity_table) |
711 | iwl_enhance_sensitivity_write(priv); | ||
712 | else | ||
713 | iwl_sensitivity_write(priv); | ||
637 | } | 714 | } |
638 | 715 | ||
639 | static inline u8 find_first_chain(u8 mask) | 716 | static inline u8 find_first_chain(u8 mask) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 5f1e7d802cbf..74623e0d535f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -205,7 +205,9 @@ void iwl_check_abort_status(struct iwl_priv *priv, | |||
205 | u8 frame_count, u32 status) | 205 | u8 frame_count, u32 status) |
206 | { | 206 | { |
207 | if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { | 207 | if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { |
208 | IWL_ERR(priv, "TODO: Implement Tx flush command!!!\n"); | 208 | IWL_ERR(priv, "Tx flush command to flush out all frames\n"); |
209 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
210 | queue_work(priv->workqueue, &priv->tx_flush); | ||
209 | } | 211 | } |
210 | } | 212 | } |
211 | 213 | ||
@@ -1435,3 +1437,81 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, | |||
1435 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; | 1437 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; |
1436 | } | 1438 | } |
1437 | } | 1439 | } |
1440 | |||
1441 | #define IWL_FLUSH_WAIT_MS 2000 | ||
1442 | |||
1443 | int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) | ||
1444 | { | ||
1445 | struct iwl_tx_queue *txq; | ||
1446 | struct iwl_queue *q; | ||
1447 | int cnt; | ||
1448 | unsigned long now = jiffies; | ||
1449 | int ret = 0; | ||
1450 | |||
1451 | /* waiting for all the tx frames complete might take a while */ | ||
1452 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | ||
1453 | if (cnt == IWL_CMD_QUEUE_NUM) | ||
1454 | continue; | ||
1455 | txq = &priv->txq[cnt]; | ||
1456 | q = &txq->q; | ||
1457 | while (q->read_ptr != q->write_ptr && !time_after(jiffies, | ||
1458 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) | ||
1459 | msleep(1); | ||
1460 | |||
1461 | if (q->read_ptr != q->write_ptr) { | ||
1462 | IWL_ERR(priv, "fail to flush all tx fifo queues\n"); | ||
1463 | ret = -ETIMEDOUT; | ||
1464 | break; | ||
1465 | } | ||
1466 | } | ||
1467 | return ret; | ||
1468 | } | ||
1469 | |||
1470 | #define IWL_TX_QUEUE_MSK 0xfffff | ||
1471 | |||
1472 | /** | ||
1473 | * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode | ||
1474 | * | ||
1475 | * pre-requirements: | ||
1476 | * 1. acquire mutex before calling | ||
1477 | * 2. make sure rf is on and not in exit state | ||
1478 | */ | ||
1479 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | ||
1480 | { | ||
1481 | struct iwl_txfifo_flush_cmd flush_cmd; | ||
1482 | struct iwl_host_cmd cmd = { | ||
1483 | .id = REPLY_TXFIFO_FLUSH, | ||
1484 | .len = sizeof(struct iwl_txfifo_flush_cmd), | ||
1485 | .flags = CMD_SYNC, | ||
1486 | .data = &flush_cmd, | ||
1487 | }; | ||
1488 | |||
1489 | might_sleep(); | ||
1490 | |||
1491 | memset(&flush_cmd, 0, sizeof(flush_cmd)); | ||
1492 | flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK | | ||
1493 | IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK; | ||
1494 | if (priv->cfg->sku & IWL_SKU_N) | ||
1495 | flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK; | ||
1496 | |||
1497 | IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", | ||
1498 | flush_cmd.fifo_control); | ||
1499 | flush_cmd.flush_control = cpu_to_le16(flush_control); | ||
1500 | |||
1501 | return iwl_send_cmd(priv, &cmd); | ||
1502 | } | ||
1503 | |||
1504 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | ||
1505 | { | ||
1506 | mutex_lock(&priv->mutex); | ||
1507 | ieee80211_stop_queues(priv->hw); | ||
1508 | if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) { | ||
1509 | IWL_ERR(priv, "flush request fail\n"); | ||
1510 | goto done; | ||
1511 | } | ||
1512 | IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); | ||
1513 | iwlagn_wait_tx_queue_empty(priv); | ||
1514 | done: | ||
1515 | ieee80211_wake_queues(priv->hw); | ||
1516 | mutex_unlock(&priv->mutex); | ||
1517 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 2573234e4db1..55a1b31fd09a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -950,9 +950,12 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | |||
950 | /* Stop each Tx DMA channel, and wait for it to be idle */ | 950 | /* Stop each Tx DMA channel, and wait for it to be idle */ |
951 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | 951 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { |
952 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | 952 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); |
953 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | 953 | if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, |
954 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | 954 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), |
955 | 1000); | 955 | 1000)) |
956 | IWL_ERR(priv, "Failing on timeout while stopping" | ||
957 | " DMA channel %d [0x%08x]", ch, | ||
958 | iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); | ||
956 | } | 959 | } |
957 | spin_unlock_irqrestore(&priv->lock, flags); | 960 | spin_unlock_irqrestore(&priv->lock, flags); |
958 | } | 961 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3368cfd25a99..7391c63fb024 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -859,6 +859,24 @@ int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) | |||
859 | return 0; | 859 | return 0; |
860 | } | 860 | } |
861 | 861 | ||
862 | static void iwl_bg_tx_flush(struct work_struct *work) | ||
863 | { | ||
864 | struct iwl_priv *priv = | ||
865 | container_of(work, struct iwl_priv, tx_flush); | ||
866 | |||
867 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
868 | return; | ||
869 | |||
870 | /* do nothing if rf-kill is on */ | ||
871 | if (!iwl_is_ready_rf(priv)) | ||
872 | return; | ||
873 | |||
874 | if (priv->cfg->ops->lib->txfifo_flush) { | ||
875 | IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); | ||
876 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); | ||
877 | } | ||
878 | } | ||
879 | |||
862 | /** | 880 | /** |
863 | * iwl_setup_rx_handlers - Initialize Rx handler callbacks | 881 | * iwl_setup_rx_handlers - Initialize Rx handler callbacks |
864 | * | 882 | * |
@@ -1806,12 +1824,21 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1806 | const u8 *data; | 1824 | const u8 *data; |
1807 | int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; | 1825 | int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; |
1808 | u64 alternatives; | 1826 | u64 alternatives; |
1827 | u32 tlv_len; | ||
1828 | enum iwl_ucode_tlv_type tlv_type; | ||
1829 | const u8 *tlv_data; | ||
1830 | int ret = 0; | ||
1809 | 1831 | ||
1810 | if (len < sizeof(*ucode)) | 1832 | if (len < sizeof(*ucode)) { |
1833 | IWL_ERR(priv, "uCode has invalid length: %zd\n", len); | ||
1811 | return -EINVAL; | 1834 | return -EINVAL; |
1835 | } | ||
1812 | 1836 | ||
1813 | if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) | 1837 | if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) { |
1838 | IWL_ERR(priv, "invalid uCode magic: 0X%x\n", | ||
1839 | le32_to_cpu(ucode->magic)); | ||
1814 | return -EINVAL; | 1840 | return -EINVAL; |
1841 | } | ||
1815 | 1842 | ||
1816 | /* | 1843 | /* |
1817 | * Check which alternatives are present, and "downgrade" | 1844 | * Check which alternatives are present, and "downgrade" |
@@ -1836,11 +1863,9 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1836 | 1863 | ||
1837 | len -= sizeof(*ucode); | 1864 | len -= sizeof(*ucode); |
1838 | 1865 | ||
1839 | while (len >= sizeof(*tlv)) { | 1866 | while (len >= sizeof(*tlv) && !ret) { |
1840 | u32 tlv_len; | ||
1841 | enum iwl_ucode_tlv_type tlv_type; | ||
1842 | u16 tlv_alt; | 1867 | u16 tlv_alt; |
1843 | const u8 *tlv_data; | 1868 | u32 fixed_tlv_size = 4; |
1844 | 1869 | ||
1845 | len -= sizeof(*tlv); | 1870 | len -= sizeof(*tlv); |
1846 | tlv = (void *)data; | 1871 | tlv = (void *)data; |
@@ -1850,8 +1875,11 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1850 | tlv_alt = le16_to_cpu(tlv->alternative); | 1875 | tlv_alt = le16_to_cpu(tlv->alternative); |
1851 | tlv_data = tlv->data; | 1876 | tlv_data = tlv->data; |
1852 | 1877 | ||
1853 | if (len < tlv_len) | 1878 | if (len < tlv_len) { |
1879 | IWL_ERR(priv, "invalid TLV len: %zd/%u\n", | ||
1880 | len, tlv_len); | ||
1854 | return -EINVAL; | 1881 | return -EINVAL; |
1882 | } | ||
1855 | len -= ALIGN(tlv_len, 4); | 1883 | len -= ALIGN(tlv_len, 4); |
1856 | data += sizeof(*tlv) + ALIGN(tlv_len, 4); | 1884 | data += sizeof(*tlv) + ALIGN(tlv_len, 4); |
1857 | 1885 | ||
@@ -1885,56 +1913,77 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1885 | pieces->boot_size = tlv_len; | 1913 | pieces->boot_size = tlv_len; |
1886 | break; | 1914 | break; |
1887 | case IWL_UCODE_TLV_PROBE_MAX_LEN: | 1915 | case IWL_UCODE_TLV_PROBE_MAX_LEN: |
1888 | if (tlv_len != 4) | 1916 | if (tlv_len != fixed_tlv_size) |
1889 | return -EINVAL; | 1917 | ret = -EINVAL; |
1890 | capa->max_probe_length = | 1918 | else |
1891 | le32_to_cpup((__le32 *)tlv_data); | 1919 | capa->max_probe_length = |
1920 | le32_to_cpup((__le32 *)tlv_data); | ||
1892 | break; | 1921 | break; |
1893 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | 1922 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: |
1894 | if (tlv_len != 4) | 1923 | if (tlv_len != fixed_tlv_size) |
1895 | return -EINVAL; | 1924 | ret = -EINVAL; |
1896 | pieces->init_evtlog_ptr = | 1925 | else |
1897 | le32_to_cpup((__le32 *)tlv_data); | 1926 | pieces->init_evtlog_ptr = |
1927 | le32_to_cpup((__le32 *)tlv_data); | ||
1898 | break; | 1928 | break; |
1899 | case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: | 1929 | case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: |
1900 | if (tlv_len != 4) | 1930 | if (tlv_len != fixed_tlv_size) |
1901 | return -EINVAL; | 1931 | ret = -EINVAL; |
1902 | pieces->init_evtlog_size = | 1932 | else |
1903 | le32_to_cpup((__le32 *)tlv_data); | 1933 | pieces->init_evtlog_size = |
1934 | le32_to_cpup((__le32 *)tlv_data); | ||
1904 | break; | 1935 | break; |
1905 | case IWL_UCODE_TLV_INIT_ERRLOG_PTR: | 1936 | case IWL_UCODE_TLV_INIT_ERRLOG_PTR: |
1906 | if (tlv_len != 4) | 1937 | if (tlv_len != fixed_tlv_size) |
1907 | return -EINVAL; | 1938 | ret = -EINVAL; |
1908 | pieces->init_errlog_ptr = | 1939 | else |
1909 | le32_to_cpup((__le32 *)tlv_data); | 1940 | pieces->init_errlog_ptr = |
1941 | le32_to_cpup((__le32 *)tlv_data); | ||
1910 | break; | 1942 | break; |
1911 | case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: | 1943 | case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: |
1912 | if (tlv_len != 4) | 1944 | if (tlv_len != fixed_tlv_size) |
1913 | return -EINVAL; | 1945 | ret = -EINVAL; |
1914 | pieces->inst_evtlog_ptr = | 1946 | else |
1915 | le32_to_cpup((__le32 *)tlv_data); | 1947 | pieces->inst_evtlog_ptr = |
1948 | le32_to_cpup((__le32 *)tlv_data); | ||
1916 | break; | 1949 | break; |
1917 | case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: | 1950 | case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: |
1918 | if (tlv_len != 4) | 1951 | if (tlv_len != fixed_tlv_size) |
1919 | return -EINVAL; | 1952 | ret = -EINVAL; |
1920 | pieces->inst_evtlog_size = | 1953 | else |
1921 | le32_to_cpup((__le32 *)tlv_data); | 1954 | pieces->inst_evtlog_size = |
1955 | le32_to_cpup((__le32 *)tlv_data); | ||
1922 | break; | 1956 | break; |
1923 | case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: | 1957 | case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: |
1924 | if (tlv_len != 4) | 1958 | if (tlv_len != fixed_tlv_size) |
1925 | return -EINVAL; | 1959 | ret = -EINVAL; |
1926 | pieces->inst_errlog_ptr = | 1960 | else |
1927 | le32_to_cpup((__le32 *)tlv_data); | 1961 | pieces->inst_errlog_ptr = |
1962 | le32_to_cpup((__le32 *)tlv_data); | ||
1963 | break; | ||
1964 | case IWL_UCODE_TLV_ENHANCE_SENS_TBL: | ||
1965 | if (tlv_len) | ||
1966 | ret = -EINVAL; | ||
1967 | else | ||
1968 | priv->enhance_sensitivity_table = true; | ||
1928 | break; | 1969 | break; |
1929 | default: | 1970 | default: |
1971 | IWL_WARN(priv, "unknown TLV: %d\n", tlv_type); | ||
1930 | break; | 1972 | break; |
1931 | } | 1973 | } |
1932 | } | 1974 | } |
1933 | 1975 | ||
1934 | if (len) | 1976 | if (len) { |
1935 | return -EINVAL; | 1977 | IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len); |
1978 | iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len); | ||
1979 | ret = -EINVAL; | ||
1980 | } else if (ret) { | ||
1981 | IWL_ERR(priv, "TLV %d has invalid size: %u\n", | ||
1982 | tlv_type, tlv_len); | ||
1983 | iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)tlv_data, tlv_len); | ||
1984 | } | ||
1936 | 1985 | ||
1937 | return 0; | 1986 | return ret; |
1938 | } | 1987 | } |
1939 | 1988 | ||
1940 | /** | 1989 | /** |
@@ -2247,17 +2296,41 @@ static const char *desc_lookup_text[] = { | |||
2247 | "DEBUG_1", | 2296 | "DEBUG_1", |
2248 | "DEBUG_2", | 2297 | "DEBUG_2", |
2249 | "DEBUG_3", | 2298 | "DEBUG_3", |
2250 | "ADVANCED SYSASSERT" | ||
2251 | }; | 2299 | }; |
2252 | 2300 | ||
2253 | static const char *desc_lookup(int i) | 2301 | static struct { char *name; u8 num; } advanced_lookup[] = { |
2302 | { "NMI_INTERRUPT_WDG", 0x34 }, | ||
2303 | { "SYSASSERT", 0x35 }, | ||
2304 | { "UCODE_VERSION_MISMATCH", 0x37 }, | ||
2305 | { "BAD_COMMAND", 0x38 }, | ||
2306 | { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, | ||
2307 | { "FATAL_ERROR", 0x3D }, | ||
2308 | { "NMI_TRM_HW_ERR", 0x46 }, | ||
2309 | { "NMI_INTERRUPT_TRM", 0x4C }, | ||
2310 | { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, | ||
2311 | { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, | ||
2312 | { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, | ||
2313 | { "NMI_INTERRUPT_HOST", 0x66 }, | ||
2314 | { "NMI_INTERRUPT_ACTION_PT", 0x7C }, | ||
2315 | { "NMI_INTERRUPT_UNKNOWN", 0x84 }, | ||
2316 | { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, | ||
2317 | { "ADVANCED_SYSASSERT", 0 }, | ||
2318 | }; | ||
2319 | |||
2320 | static const char *desc_lookup(u32 num) | ||
2254 | { | 2321 | { |
2255 | int max = ARRAY_SIZE(desc_lookup_text) - 1; | 2322 | int i; |
2323 | int max = ARRAY_SIZE(desc_lookup_text); | ||
2256 | 2324 | ||
2257 | if (i < 0 || i > max) | 2325 | if (num < max) |
2258 | i = max; | 2326 | return desc_lookup_text[num]; |
2259 | 2327 | ||
2260 | return desc_lookup_text[i]; | 2328 | max = ARRAY_SIZE(advanced_lookup) - 1; |
2329 | for (i = 0; i < max; i++) { | ||
2330 | if (advanced_lookup[i].num == num) | ||
2331 | break;; | ||
2332 | } | ||
2333 | return advanced_lookup[i].name; | ||
2261 | } | 2334 | } |
2262 | 2335 | ||
2263 | #define ERROR_START_OFFSET (1 * sizeof(u32)) | 2336 | #define ERROR_START_OFFSET (1 * sizeof(u32)) |
@@ -3614,6 +3687,44 @@ out_exit: | |||
3614 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3687 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3615 | } | 3688 | } |
3616 | 3689 | ||
3690 | static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop) | ||
3691 | { | ||
3692 | struct iwl_priv *priv = hw->priv; | ||
3693 | |||
3694 | mutex_lock(&priv->mutex); | ||
3695 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
3696 | |||
3697 | /* do not support "flush" */ | ||
3698 | if (!priv->cfg->ops->lib->txfifo_flush) | ||
3699 | goto done; | ||
3700 | |||
3701 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
3702 | IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n"); | ||
3703 | goto done; | ||
3704 | } | ||
3705 | if (iwl_is_rfkill(priv)) { | ||
3706 | IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n"); | ||
3707 | goto done; | ||
3708 | } | ||
3709 | |||
3710 | /* | ||
3711 | * mac80211 will not push any more frames for transmit | ||
3712 | * until the flush is completed | ||
3713 | */ | ||
3714 | if (drop) { | ||
3715 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); | ||
3716 | if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) { | ||
3717 | IWL_ERR(priv, "flush request fail\n"); | ||
3718 | goto done; | ||
3719 | } | ||
3720 | } | ||
3721 | IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); | ||
3722 | iwlagn_wait_tx_queue_empty(priv); | ||
3723 | done: | ||
3724 | mutex_unlock(&priv->mutex); | ||
3725 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3726 | } | ||
3727 | |||
3617 | /***************************************************************************** | 3728 | /***************************************************************************** |
3618 | * | 3729 | * |
3619 | * driver setup and teardown | 3730 | * driver setup and teardown |
@@ -3630,6 +3741,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3630 | INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); | 3741 | INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); |
3631 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); | 3742 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); |
3632 | INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); | 3743 | INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); |
3744 | INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); | ||
3633 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); | 3745 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); |
3634 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); | 3746 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); |
3635 | 3747 | ||
@@ -3787,6 +3899,7 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3787 | .sta_add = iwlagn_mac_sta_add, | 3899 | .sta_add = iwlagn_mac_sta_add, |
3788 | .sta_remove = iwl_mac_sta_remove, | 3900 | .sta_remove = iwl_mac_sta_remove, |
3789 | .channel_switch = iwl_mac_channel_switch, | 3901 | .channel_switch = iwl_mac_channel_switch, |
3902 | .flush = iwl_mac_flush, | ||
3790 | }; | 3903 | }; |
3791 | 3904 | ||
3792 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3905 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -4234,6 +4347,14 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
4234 | {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, | 4347 | {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, |
4235 | {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, | 4348 | {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, |
4236 | 4349 | ||
4350 | /* 6x50 WiFi/WiMax Series Gen2 */ | ||
4351 | {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6050g2_bgn_cfg)}, | ||
4352 | {IWL_PCI_DEVICE(0x0885, 0x1306, iwl6050g2_bgn_cfg)}, | ||
4353 | {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6050g2_bgn_cfg)}, | ||
4354 | {IWL_PCI_DEVICE(0x0885, 0x1326, iwl6050g2_bgn_cfg)}, | ||
4355 | {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6050g2_bgn_cfg)}, | ||
4356 | {IWL_PCI_DEVICE(0x0886, 0x1316, iwl6050g2_bgn_cfg)}, | ||
4357 | |||
4237 | /* 1000 Series WiFi */ | 4358 | /* 1000 Series WiFi */ |
4238 | {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)}, | 4359 | {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)}, |
4239 | {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)}, | 4360 | {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index be9d298cae2c..cc6464dc72e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -89,6 +89,7 @@ extern struct iwl_cfg iwl6000i_2bg_cfg; | |||
89 | extern struct iwl_cfg iwl6000_3agn_cfg; | 89 | extern struct iwl_cfg iwl6000_3agn_cfg; |
90 | extern struct iwl_cfg iwl6050_2agn_cfg; | 90 | extern struct iwl_cfg iwl6050_2agn_cfg; |
91 | extern struct iwl_cfg iwl6050_2abg_cfg; | 91 | extern struct iwl_cfg iwl6050_2abg_cfg; |
92 | extern struct iwl_cfg iwl6050g2_bgn_cfg; | ||
92 | extern struct iwl_cfg iwl1000_bgn_cfg; | 93 | extern struct iwl_cfg iwl1000_bgn_cfg; |
93 | extern struct iwl_cfg iwl1000_bg_cfg; | 94 | extern struct iwl_cfg iwl1000_bg_cfg; |
94 | 95 | ||
@@ -147,6 +148,9 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | |||
147 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 148 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
148 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 149 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
149 | int iwlagn_hw_nic_init(struct iwl_priv *priv); | 150 | int iwlagn_hw_nic_init(struct iwl_priv *priv); |
151 | int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); | ||
152 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | ||
153 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | ||
150 | 154 | ||
151 | /* rx */ | 155 | /* rx */ |
152 | void iwlagn_rx_queue_restock(struct iwl_priv *priv); | 156 | void iwlagn_rx_queue_restock(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index acf8e980b1fe..8d2db9d22045 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -97,6 +97,7 @@ enum { | |||
97 | REPLY_ADD_STA = 0x18, | 97 | REPLY_ADD_STA = 0x18, |
98 | REPLY_REMOVE_STA = 0x19, | 98 | REPLY_REMOVE_STA = 0x19, |
99 | REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ | 99 | REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ |
100 | REPLY_TXFIFO_FLUSH = 0x1e, | ||
100 | 101 | ||
101 | /* Security */ | 102 | /* Security */ |
102 | REPLY_WEPKEY = 0x20, | 103 | REPLY_WEPKEY = 0x20, |
@@ -957,8 +958,8 @@ struct iwl_qosparam_cmd { | |||
957 | #define IWL3945_STATION_COUNT 25 | 958 | #define IWL3945_STATION_COUNT 25 |
958 | #define IWL4965_BROADCAST_ID 31 | 959 | #define IWL4965_BROADCAST_ID 31 |
959 | #define IWL4965_STATION_COUNT 32 | 960 | #define IWL4965_STATION_COUNT 32 |
960 | #define IWL5000_BROADCAST_ID 15 | 961 | #define IWLAGN_BROADCAST_ID 15 |
961 | #define IWL5000_STATION_COUNT 16 | 962 | #define IWLAGN_STATION_COUNT 16 |
962 | 963 | ||
963 | #define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ | 964 | #define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ |
964 | #define IWL_INVALID_STATION 255 | 965 | #define IWL_INVALID_STATION 255 |
@@ -1209,6 +1210,43 @@ struct iwl_rem_sta_cmd { | |||
1209 | u8 reserved2[2]; | 1210 | u8 reserved2[2]; |
1210 | } __packed; | 1211 | } __packed; |
1211 | 1212 | ||
1213 | #define IWL_TX_FIFO_BK_MSK cpu_to_le32(BIT(0)) | ||
1214 | #define IWL_TX_FIFO_BE_MSK cpu_to_le32(BIT(1)) | ||
1215 | #define IWL_TX_FIFO_VI_MSK cpu_to_le32(BIT(2)) | ||
1216 | #define IWL_TX_FIFO_VO_MSK cpu_to_le32(BIT(3)) | ||
1217 | #define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00) | ||
1218 | |||
1219 | #define IWL_DROP_SINGLE 0 | ||
1220 | #define IWL_DROP_SELECTED 1 | ||
1221 | #define IWL_DROP_ALL 2 | ||
1222 | |||
1223 | /* | ||
1224 | * REPLY_TXFIFO_FLUSH = 0x1e(command and response) | ||
1225 | * | ||
1226 | * When using full FIFO flush this command checks the scheduler HW block WR/RD | ||
1227 | * pointers to check if all the frames were transferred by DMA into the | ||
1228 | * relevant TX FIFO queue. Only when the DMA is finished and the queue is | ||
1229 | * empty the command can finish. | ||
1230 | * This command is used to flush the TXFIFO from transmit commands, it may | ||
1231 | * operate on single or multiple queues, the command queue can't be flushed by | ||
1232 | * this command. The command response is returned when all the queue flush | ||
1233 | * operations are done. Each TX command flushed return response with the FLUSH | ||
1234 | * status set in the TX response status. When FIFO flush operation is used, | ||
1235 | * the flush operation ends when both the scheduler DMA done and TXFIFO empty | ||
1236 | * are set. | ||
1237 | * | ||
1238 | * @fifo_control: bit mask for which queues to flush | ||
1239 | * @flush_control: flush controls | ||
1240 | * 0: Dump single MSDU | ||
1241 | * 1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable. | ||
1242 | * 2: Dump all FIFO | ||
1243 | */ | ||
1244 | struct iwl_txfifo_flush_cmd { | ||
1245 | __le32 fifo_control; | ||
1246 | __le16 flush_control; | ||
1247 | __le16 reserved; | ||
1248 | } __attribute__ ((packed)); | ||
1249 | |||
1212 | /* | 1250 | /* |
1213 | * REPLY_WEP_KEY = 0x20 | 1251 | * REPLY_WEP_KEY = 0x20 |
1214 | */ | 1252 | */ |
@@ -3452,6 +3490,41 @@ struct iwl_missed_beacon_notif { | |||
3452 | #define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX (9) | 3490 | #define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX (9) |
3453 | #define HD_OFDM_ENERGY_TH_IN_INDEX (10) | 3491 | #define HD_OFDM_ENERGY_TH_IN_INDEX (10) |
3454 | 3492 | ||
3493 | /* | ||
3494 | * Additional table entries in enhance SENSITIVITY_CMD | ||
3495 | */ | ||
3496 | #define HD_INA_NON_SQUARE_DET_OFDM_INDEX (11) | ||
3497 | #define HD_INA_NON_SQUARE_DET_CCK_INDEX (12) | ||
3498 | #define HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX (13) | ||
3499 | #define HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX (14) | ||
3500 | #define HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX (15) | ||
3501 | #define HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX (16) | ||
3502 | #define HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX (17) | ||
3503 | #define HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX (18) | ||
3504 | #define HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX (19) | ||
3505 | #define HD_CCK_NON_SQUARE_DET_SLOPE_INDEX (20) | ||
3506 | #define HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX (21) | ||
3507 | #define HD_RESERVED (22) | ||
3508 | |||
3509 | /* number of entries for enhanced tbl */ | ||
3510 | #define ENHANCE_HD_TABLE_SIZE (23) | ||
3511 | |||
3512 | /* number of additional entries for enhanced tbl */ | ||
3513 | #define ENHANCE_HD_TABLE_ENTRIES (ENHANCE_HD_TABLE_SIZE - HD_TABLE_SIZE) | ||
3514 | |||
3515 | #define HD_INA_NON_SQUARE_DET_OFDM_DATA cpu_to_le16(0) | ||
3516 | #define HD_INA_NON_SQUARE_DET_CCK_DATA cpu_to_le16(0) | ||
3517 | #define HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA cpu_to_le16(0) | ||
3518 | #define HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA cpu_to_le16(668) | ||
3519 | #define HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA cpu_to_le16(4) | ||
3520 | #define HD_OFDM_NON_SQUARE_DET_SLOPE_DATA cpu_to_le16(486) | ||
3521 | #define HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA cpu_to_le16(37) | ||
3522 | #define HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA cpu_to_le16(853) | ||
3523 | #define HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA cpu_to_le16(4) | ||
3524 | #define HD_CCK_NON_SQUARE_DET_SLOPE_DATA cpu_to_le16(476) | ||
3525 | #define HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA cpu_to_le16(99) | ||
3526 | |||
3527 | |||
3455 | /* Control field in struct iwl_sensitivity_cmd */ | 3528 | /* Control field in struct iwl_sensitivity_cmd */ |
3456 | #define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE cpu_to_le16(0) | 3529 | #define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE cpu_to_le16(0) |
3457 | #define SENSITIVITY_CMD_CONTROL_WORK_TABLE cpu_to_le16(1) | 3530 | #define SENSITIVITY_CMD_CONTROL_WORK_TABLE cpu_to_le16(1) |
@@ -3468,6 +3541,14 @@ struct iwl_sensitivity_cmd { | |||
3468 | __le16 table[HD_TABLE_SIZE]; /* use HD_* as index */ | 3541 | __le16 table[HD_TABLE_SIZE]; /* use HD_* as index */ |
3469 | } __packed; | 3542 | } __packed; |
3470 | 3543 | ||
3544 | /* | ||
3545 | * | ||
3546 | */ | ||
3547 | struct iwl_enhance_sensitivity_cmd { | ||
3548 | __le16 control; /* always use "1" */ | ||
3549 | __le16 enhance_table[ENHANCE_HD_TABLE_SIZE]; /* use HD_* as index */ | ||
3550 | } __attribute__ ((packed)); | ||
3551 | |||
3471 | 3552 | ||
3472 | /** | 3553 | /** |
3473 | * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response) | 3554 | * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a56fb466d0b6..f73eb08a9494 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -2627,7 +2627,7 @@ static void iwl_force_rf_reset(struct iwl_priv *priv) | |||
2627 | } | 2627 | } |
2628 | 2628 | ||
2629 | 2629 | ||
2630 | int iwl_force_reset(struct iwl_priv *priv, int mode) | 2630 | int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) |
2631 | { | 2631 | { |
2632 | struct iwl_force_reset *force_reset; | 2632 | struct iwl_force_reset *force_reset; |
2633 | 2633 | ||
@@ -2640,12 +2640,14 @@ int iwl_force_reset(struct iwl_priv *priv, int mode) | |||
2640 | } | 2640 | } |
2641 | force_reset = &priv->force_reset[mode]; | 2641 | force_reset = &priv->force_reset[mode]; |
2642 | force_reset->reset_request_count++; | 2642 | force_reset->reset_request_count++; |
2643 | if (force_reset->last_force_reset_jiffies && | 2643 | if (!external) { |
2644 | time_after(force_reset->last_force_reset_jiffies + | 2644 | if (force_reset->last_force_reset_jiffies && |
2645 | force_reset->reset_duration, jiffies)) { | 2645 | time_after(force_reset->last_force_reset_jiffies + |
2646 | IWL_DEBUG_INFO(priv, "force reset rejected\n"); | 2646 | force_reset->reset_duration, jiffies)) { |
2647 | force_reset->reset_reject_count++; | 2647 | IWL_DEBUG_INFO(priv, "force reset rejected\n"); |
2648 | return -EAGAIN; | 2648 | force_reset->reset_reject_count++; |
2649 | return -EAGAIN; | ||
2650 | } | ||
2649 | } | 2651 | } |
2650 | force_reset->reset_success_count++; | 2652 | force_reset->reset_success_count++; |
2651 | force_reset->last_force_reset_jiffies = jiffies; | 2653 | force_reset->last_force_reset_jiffies = jiffies; |
@@ -2655,6 +2657,19 @@ int iwl_force_reset(struct iwl_priv *priv, int mode) | |||
2655 | iwl_force_rf_reset(priv); | 2657 | iwl_force_rf_reset(priv); |
2656 | break; | 2658 | break; |
2657 | case IWL_FW_RESET: | 2659 | case IWL_FW_RESET: |
2660 | /* | ||
2661 | * if the request is from external(ex: debugfs), | ||
2662 | * then always perform the request in regardless the module | ||
2663 | * parameter setting | ||
2664 | * if the request is from internal (uCode error or driver | ||
2665 | * detect failure), then fw_restart module parameter | ||
2666 | * need to be check before performing firmware reload | ||
2667 | */ | ||
2668 | if (!external && !priv->cfg->mod_params->restart_fw) { | ||
2669 | IWL_DEBUG_INFO(priv, "Cancel firmware reload based on " | ||
2670 | "module parameter setting\n"); | ||
2671 | break; | ||
2672 | } | ||
2658 | IWL_ERR(priv, "On demand firmware reload\n"); | 2673 | IWL_ERR(priv, "On demand firmware reload\n"); |
2659 | /* Set the FW error flag -- cleared on iwl_down */ | 2674 | /* Set the FW error flag -- cleared on iwl_down */ |
2660 | set_bit(STATUS_FW_ERROR, &priv->status); | 2675 | set_bit(STATUS_FW_ERROR, &priv->status); |
@@ -2713,7 +2728,7 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) | |||
2713 | "queue %d stuck %d time. Fw reload.\n", | 2728 | "queue %d stuck %d time. Fw reload.\n", |
2714 | q->id, q->repeat_same_read_ptr); | 2729 | q->id, q->repeat_same_read_ptr); |
2715 | q->repeat_same_read_ptr = 0; | 2730 | q->repeat_same_read_ptr = 0; |
2716 | iwl_force_reset(priv, IWL_FW_RESET); | 2731 | iwl_force_reset(priv, IWL_FW_RESET, false); |
2717 | } else { | 2732 | } else { |
2718 | q->repeat_same_read_ptr++; | 2733 | q->repeat_same_read_ptr++; |
2719 | IWL_DEBUG_RADIO(priv, | 2734 | IWL_DEBUG_RADIO(priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 15930e064022..fcbba3d604de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -205,6 +205,9 @@ struct iwl_lib_ops { | |||
205 | /* check for ack health */ | 205 | /* check for ack health */ |
206 | bool (*check_ack_health)(struct iwl_priv *priv, | 206 | bool (*check_ack_health)(struct iwl_priv *priv, |
207 | struct iwl_rx_packet *pkt); | 207 | struct iwl_rx_packet *pkt); |
208 | int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control); | ||
209 | void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); | ||
210 | |||
208 | struct iwl_debugfs_ops debugfs_ops; | 211 | struct iwl_debugfs_ops debugfs_ops; |
209 | }; | 212 | }; |
210 | 213 | ||
@@ -525,7 +528,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
525 | struct cfg80211_scan_request *req); | 528 | struct cfg80211_scan_request *req); |
526 | void iwl_bg_start_internal_scan(struct work_struct *work); | 529 | void iwl_bg_start_internal_scan(struct work_struct *work); |
527 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | 530 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); |
528 | int iwl_force_reset(struct iwl_priv *priv, int mode); | 531 | int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); |
529 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 532 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
530 | const u8 *ta, const u8 *ie, int ie_len, int left); | 533 | const u8 *ta, const u8 *ie, int ie_len, int left); |
531 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | 534 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 254c35ae8b38..ecf98e7ac4ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -298,6 +298,7 @@ | |||
298 | #define CSR_HW_REV_TYPE_1000 (0x0000060) | 298 | #define CSR_HW_REV_TYPE_1000 (0x0000060) |
299 | #define CSR_HW_REV_TYPE_6x00 (0x0000070) | 299 | #define CSR_HW_REV_TYPE_6x00 (0x0000070) |
300 | #define CSR_HW_REV_TYPE_6x50 (0x0000080) | 300 | #define CSR_HW_REV_TYPE_6x50 (0x0000080) |
301 | #define CSR_HW_REV_TYPE_6x50g2 (0x0000084) | ||
301 | #define CSR_HW_REV_TYPE_6x00g2 (0x00000B0) | 302 | #define CSR_HW_REV_TYPE_6x00g2 (0x00000B0) |
302 | #define CSR_HW_REV_TYPE_NONE (0x00000F0) | 303 | #define CSR_HW_REV_TYPE_NONE (0x00000F0) |
303 | 304 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 7d9ffc1575de..088a2c13f59b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -1487,7 +1487,7 @@ static ssize_t iwl_dbgfs_force_reset_write(struct file *file, | |||
1487 | switch (reset) { | 1487 | switch (reset) { |
1488 | case IWL_RF_RESET: | 1488 | case IWL_RF_RESET: |
1489 | case IWL_FW_RESET: | 1489 | case IWL_FW_RESET: |
1490 | ret = iwl_force_reset(priv, reset); | 1490 | ret = iwl_force_reset(priv, reset, true); |
1491 | break; | 1491 | break; |
1492 | default: | 1492 | default: |
1493 | return -EINVAL; | 1493 | return -EINVAL; |
@@ -1495,6 +1495,30 @@ static ssize_t iwl_dbgfs_force_reset_write(struct file *file, | |||
1495 | return ret ? ret : count; | 1495 | return ret ? ret : count; |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, | ||
1499 | const char __user *user_buf, | ||
1500 | size_t count, loff_t *ppos) { | ||
1501 | |||
1502 | struct iwl_priv *priv = file->private_data; | ||
1503 | char buf[8]; | ||
1504 | int buf_size; | ||
1505 | int flush; | ||
1506 | |||
1507 | memset(buf, 0, sizeof(buf)); | ||
1508 | buf_size = min(count, sizeof(buf) - 1); | ||
1509 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1510 | return -EFAULT; | ||
1511 | if (sscanf(buf, "%d", &flush) != 1) | ||
1512 | return -EINVAL; | ||
1513 | |||
1514 | if (iwl_is_rfkill(priv)) | ||
1515 | return -EFAULT; | ||
1516 | |||
1517 | priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL); | ||
1518 | |||
1519 | return count; | ||
1520 | } | ||
1521 | |||
1498 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 1522 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
1499 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 1523 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
1500 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 1524 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -1516,6 +1540,7 @@ DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | |||
1516 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | 1540 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); |
1517 | DEBUGFS_READ_FILE_OPS(rxon_flags); | 1541 | DEBUGFS_READ_FILE_OPS(rxon_flags); |
1518 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); | 1542 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); |
1543 | DEBUGFS_WRITE_FILE_OPS(txfifo_flush); | ||
1519 | 1544 | ||
1520 | /* | 1545 | /* |
1521 | * Create the debugfs files and directories | 1546 | * Create the debugfs files and directories |
@@ -1574,6 +1599,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1574 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); | 1599 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); |
1575 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); | 1600 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); |
1576 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | 1601 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); |
1602 | if (priv->cfg->ops->lib->dev_txfifo_flush) | ||
1603 | DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); | ||
1577 | 1604 | ||
1578 | if (priv->cfg->sensitivity_calib_by_driver) | 1605 | if (priv->cfg->sensitivity_calib_by_driver) |
1579 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | 1606 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 728752aa1bb5..c4dba62b74af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -570,6 +570,7 @@ enum iwl_ucode_tlv_type { | |||
570 | IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, | 570 | IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, |
571 | IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, | 571 | IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, |
572 | IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, | 572 | IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, |
573 | IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, | ||
573 | }; | 574 | }; |
574 | 575 | ||
575 | struct iwl_ucode_tlv { | 576 | struct iwl_ucode_tlv { |
@@ -1193,7 +1194,9 @@ struct iwl_priv { | |||
1193 | u8 start_calib; | 1194 | u8 start_calib; |
1194 | struct iwl_sensitivity_data sensitivity_data; | 1195 | struct iwl_sensitivity_data sensitivity_data; |
1195 | struct iwl_chain_noise_data chain_noise_data; | 1196 | struct iwl_chain_noise_data chain_noise_data; |
1197 | bool enhance_sensitivity_table; | ||
1196 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; | 1198 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; |
1199 | __le16 enhance_sensitivity_tbl[ENHANCE_HD_TABLE_ENTRIES]; | ||
1197 | 1200 | ||
1198 | struct iwl_ht_config current_ht_config; | 1201 | struct iwl_ht_config current_ht_config; |
1199 | 1202 | ||
@@ -1345,6 +1348,7 @@ struct iwl_priv { | |||
1345 | struct work_struct ct_enter; | 1348 | struct work_struct ct_enter; |
1346 | struct work_struct ct_exit; | 1349 | struct work_struct ct_exit; |
1347 | struct work_struct start_internal_scan; | 1350 | struct work_struct start_internal_scan; |
1351 | struct work_struct tx_flush; | ||
1348 | 1352 | ||
1349 | struct tasklet_struct irq_tasklet; | 1353 | struct tasklet_struct irq_tasklet; |
1350 | 1354 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 5488006491a2..3452dfa7b571 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -276,6 +276,10 @@ struct iwl_eeprom_enhanced_txpwr { | |||
276 | #define EEPROM_6050_TX_POWER_VERSION (4) | 276 | #define EEPROM_6050_TX_POWER_VERSION (4) |
277 | #define EEPROM_6050_EEPROM_VERSION (0x532) | 277 | #define EEPROM_6050_EEPROM_VERSION (0x532) |
278 | 278 | ||
279 | /* 6x50g2 Specific */ | ||
280 | #define EEPROM_6050G2_TX_POWER_VERSION (6) | ||
281 | #define EEPROM_6050G2_EEPROM_VERSION (0x553) | ||
282 | |||
279 | /* 6x00g2 Specific */ | 283 | /* 6x00g2 Specific */ |
280 | #define EEPROM_6000G2_TX_POWER_VERSION (6) | 284 | #define EEPROM_6000G2_TX_POWER_VERSION (6) |
281 | #define EEPROM_6000G2_EEPROM_VERSION (0x709) | 285 | #define EEPROM_6000G2_EEPROM_VERSION (0x709) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index a3fcbb5f2c70..55b8370bc6d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -398,12 +398,7 @@ | |||
398 | */ | 398 | */ |
399 | #define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018) | 399 | #define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018) |
400 | 400 | ||
401 | #define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24) | 401 | #define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16) |
402 | #define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16) | ||
403 | |||
404 | #define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) \ | ||
405 | (FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \ | ||
406 | FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl)) | ||
407 | 402 | ||
408 | /* Tx service channels */ | 403 | /* Tx service channels */ |
409 | #define FH_SRVC_CHNL (9) | 404 | #define FH_SRVC_CHNL (9) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 51f89e7ba681..258d059ef41f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -49,6 +49,7 @@ const char *get_cmd_string(u8 cmd) | |||
49 | IWL_CMD(REPLY_ADD_STA); | 49 | IWL_CMD(REPLY_ADD_STA); |
50 | IWL_CMD(REPLY_REMOVE_STA); | 50 | IWL_CMD(REPLY_REMOVE_STA); |
51 | IWL_CMD(REPLY_REMOVE_ALL_STA); | 51 | IWL_CMD(REPLY_REMOVE_ALL_STA); |
52 | IWL_CMD(REPLY_TXFIFO_FLUSH); | ||
52 | IWL_CMD(REPLY_WEPKEY); | 53 | IWL_CMD(REPLY_WEPKEY); |
53 | IWL_CMD(REPLY_3945_RX); | 54 | IWL_CMD(REPLY_3945_RX); |
54 | IWL_CMD(REPLY_TX); | 55 | IWL_CMD(REPLY_TX); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b437f317b979..79773e353baa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -238,7 +238,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, | |||
238 | */ | 238 | */ |
239 | IWL_ERR(priv, "low ack count detected, " | 239 | IWL_ERR(priv, "low ack count detected, " |
240 | "restart firmware\n"); | 240 | "restart firmware\n"); |
241 | if (!iwl_force_reset(priv, IWL_FW_RESET)) | 241 | if (!iwl_force_reset(priv, IWL_FW_RESET, false)) |
242 | return; | 242 | return; |
243 | } | 243 | } |
244 | } | 244 | } |
@@ -249,7 +249,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, | |||
249 | * high plcp error detected | 249 | * high plcp error detected |
250 | * reset Radio | 250 | * reset Radio |
251 | */ | 251 | */ |
252 | iwl_force_reset(priv, IWL_RF_RESET); | 252 | iwl_force_reset(priv, IWL_RF_RESET, false); |
253 | } | 253 | } |
254 | } | 254 | } |
255 | } | 255 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index ba95b1a590a5..d38a350ba0bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -98,6 +98,17 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv) | |||
98 | spin_lock_irqsave(&priv->sta_lock, flags); | 98 | spin_lock_irqsave(&priv->sta_lock, flags); |
99 | memset(priv->stations, 0, sizeof(priv->stations)); | 99 | memset(priv->stations, 0, sizeof(priv->stations)); |
100 | priv->num_stations = 0; | 100 | priv->num_stations = 0; |
101 | |||
102 | /* | ||
103 | * Remove all key information that is not stored as part of station | ||
104 | * information since mac80211 may not have had a | ||
105 | * chance to remove all the keys. When device is reconfigured by | ||
106 | * mac80211 after an error all keys will be reconfigured. | ||
107 | */ | ||
108 | priv->ucode_key_table = 0; | ||
109 | priv->key_mapping_key = 0; | ||
110 | memset(priv->wep_keys, 0, sizeof(priv->wep_keys)); | ||
111 | |||
101 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 112 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
102 | } | 113 | } |
103 | 114 | ||