aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-07-06 14:19:01 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-06 14:19:01 -0400
commita2c9fc971d9ff11643d9c7b7c0af0e8ced7d895e (patch)
treec4cdf4dcb98359bf19c2f2f48f1cb9db4603c5ba /drivers/net
parentecc3d5ae17e62ce1250abf16ff523c677bf19e2f (diff)
parentc8312facd99b4cd05998fe3440926b667a896c9e (diff)
Merge branch 'wireless-next-2.6' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c133
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c82
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c165
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h85
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c4
14 files changed, 477 insertions, 89 deletions
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
231static const struct iwl_ops iwl1000_ops = { 233static 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
407static struct iwl_lib_ops iwl5150_lib = { 409static 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
470static const struct iwl_ops iwl5000_ops = { 474static 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..59681c5eeb9f 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
332static const struct iwl_ops iwl6000_ops = { 334static const struct iwl_ops iwl6000_ops = {
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 */ 412static void iwl_prepare_legacy_sensitivity_tbl(struct iwl_priv *priv,
413static 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 */
453static 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 */
488static 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
480void iwl_init_sensitivity(struct iwl_priv *priv) 551void 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
639static inline u8 find_first_chain(u8 mask) 716static 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
1443int 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 */
1479int 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
1504void 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);
1514done:
1515 ieee80211_wake_queues(priv->hw);
1516 mutex_unlock(&priv->mutex);
1517}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 3368cfd25a99..66c83b24884f 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
862static 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/**
@@ -3614,6 +3663,44 @@ out_exit:
3614 IWL_DEBUG_MAC80211(priv, "leave\n"); 3663 IWL_DEBUG_MAC80211(priv, "leave\n");
3615} 3664}
3616 3665
3666static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop)
3667{
3668 struct iwl_priv *priv = hw->priv;
3669
3670 mutex_lock(&priv->mutex);
3671 IWL_DEBUG_MAC80211(priv, "enter\n");
3672
3673 /* do not support "flush" */
3674 if (!priv->cfg->ops->lib->txfifo_flush)
3675 goto done;
3676
3677 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
3678 IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
3679 goto done;
3680 }
3681 if (iwl_is_rfkill(priv)) {
3682 IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n");
3683 goto done;
3684 }
3685
3686 /*
3687 * mac80211 will not push any more frames for transmit
3688 * until the flush is completed
3689 */
3690 if (drop) {
3691 IWL_DEBUG_MAC80211(priv, "send flush command\n");
3692 if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
3693 IWL_ERR(priv, "flush request fail\n");
3694 goto done;
3695 }
3696 }
3697 IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
3698 iwlagn_wait_tx_queue_empty(priv);
3699done:
3700 mutex_unlock(&priv->mutex);
3701 IWL_DEBUG_MAC80211(priv, "leave\n");
3702}
3703
3617/***************************************************************************** 3704/*****************************************************************************
3618 * 3705 *
3619 * driver setup and teardown 3706 * driver setup and teardown
@@ -3630,6 +3717,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
3630 INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); 3717 INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
3631 INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); 3718 INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
3632 INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); 3719 INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
3720 INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
3633 INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); 3721 INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
3634 INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); 3722 INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
3635 3723
@@ -3787,6 +3875,7 @@ static struct ieee80211_ops iwl_hw_ops = {
3787 .sta_add = iwlagn_mac_sta_add, 3875 .sta_add = iwlagn_mac_sta_add,
3788 .sta_remove = iwl_mac_sta_remove, 3876 .sta_remove = iwl_mac_sta_remove,
3789 .channel_switch = iwl_mac_channel_switch, 3877 .channel_switch = iwl_mac_channel_switch,
3878 .flush = iwl_mac_flush,
3790}; 3879};
3791 3880
3792static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 3881static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index be9d298cae2c..5c46b2cd8e91 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -147,6 +147,9 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
147void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); 147void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
148int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); 148int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
149int iwlagn_hw_nic_init(struct iwl_priv *priv); 149int iwlagn_hw_nic_init(struct iwl_priv *priv);
150int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
151int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
152void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
150 153
151/* rx */ 154/* rx */
152void iwlagn_rx_queue_restock(struct iwl_priv *priv); 155void 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 a304f771bcc3..a587999d07db 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} __attribute__ ((packed)); 1211} __attribute__ ((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 */
1244struct 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} __attribute__ ((packed)); 3542} __attribute__ ((packed));
3470 3543
3544/*
3545 *
3546 */
3547struct 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
2630int iwl_force_reset(struct iwl_priv *priv, int mode) 2630int 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);
526void iwl_bg_start_internal_scan(struct work_struct *work); 529void iwl_bg_start_internal_scan(struct work_struct *work);
527void iwl_internal_short_hw_scan(struct iwl_priv *priv); 530void iwl_internal_short_hw_scan(struct iwl_priv *priv);
528int iwl_force_reset(struct iwl_priv *priv, int mode); 531int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
529u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, 532u16 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);
531void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); 534void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
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
1498static 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
1498DEBUGFS_READ_FILE_OPS(rx_statistics); 1522DEBUGFS_READ_FILE_OPS(rx_statistics);
1499DEBUGFS_READ_FILE_OPS(tx_statistics); 1523DEBUGFS_READ_FILE_OPS(tx_statistics);
1500DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); 1524DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -1516,6 +1540,7 @@ DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
1516DEBUGFS_READ_WRITE_FILE_OPS(force_reset); 1540DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1517DEBUGFS_READ_FILE_OPS(rxon_flags); 1541DEBUGFS_READ_FILE_OPS(rxon_flags);
1518DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 1542DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1543DEBUGFS_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 df07a144c786..dff1b17d5ea8 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
575struct iwl_ucode_tlv { 576struct 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-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 }