Skip to content

Commit

Permalink
Merge branch 'wireless-next-2.6' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/iwlwifi/iwlwifi-2.6
  • Loading branch information
John W. Linville committed Jul 6, 2010
2 parents ecc3d5a + c8312fa commit a2c9fc9
Show file tree
Hide file tree
Showing 14 changed files with 477 additions and 89 deletions.
6 changes: 4 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-1000.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;

priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
Expand Down Expand Up @@ -226,6 +226,8 @@ static struct iwl_lib_ops iwl1000_lib = {
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};

static const struct iwl_ops iwl1000_ops = {
Expand Down
12 changes: 8 additions & 4 deletions drivers/net/wireless/iwlwifi/iwl-5000.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;

priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
Expand Down Expand Up @@ -226,8 +226,8 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;

priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
Expand Down Expand Up @@ -402,6 +402,8 @@ static struct iwl_lib_ops iwl5000_lib = {
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};

static struct iwl_lib_ops iwl5150_lib = {
Expand Down Expand Up @@ -465,6 +467,8 @@ static struct iwl_lib_ops iwl5150_lib = {
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};

static const struct iwl_ops iwl5000_ops = {
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-6000.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;

priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
Expand Down Expand Up @@ -327,6 +327,8 @@ static struct iwl_lib_ops iwl6000_lib = {
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};

static const struct iwl_ops iwl6000_ops = {
Expand Down
133 changes: 105 additions & 28 deletions drivers/net/wireless/iwlwifi/iwl-agn-calib.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,46 +409,34 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv,
return 0;
}

/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
static int iwl_sensitivity_write(struct iwl_priv *priv)
static void iwl_prepare_legacy_sensitivity_tbl(struct iwl_priv *priv,
struct iwl_sensitivity_data *data,
__le16 *tbl)
{
struct iwl_sensitivity_cmd cmd ;
struct iwl_sensitivity_data *data = NULL;
struct iwl_host_cmd cmd_out = {
.id = SENSITIVITY_CMD,
.len = sizeof(struct iwl_sensitivity_cmd),
.flags = CMD_ASYNC,
.data = &cmd,
};

data = &(priv->sensitivity_data);

memset(&cmd, 0, sizeof(cmd));

cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
cpu_to_le16((u16)data->auto_corr_ofdm);
cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
cpu_to_le16((u16)data->auto_corr_ofdm_x1);
cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);

cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
cpu_to_le16((u16)data->auto_corr_cck);
cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
cpu_to_le16((u16)data->auto_corr_cck_mrc);

cmd.table[HD_MIN_ENERGY_CCK_DET_INDEX] =
tbl[HD_MIN_ENERGY_CCK_DET_INDEX] =
cpu_to_le16((u16)data->nrg_th_cck);
cmd.table[HD_MIN_ENERGY_OFDM_DET_INDEX] =
tbl[HD_MIN_ENERGY_OFDM_DET_INDEX] =
cpu_to_le16((u16)data->nrg_th_ofdm);

cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
tbl[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
cpu_to_le16(data->barker_corr_th_min);
cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
tbl[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
cpu_to_le16(data->barker_corr_th_min_mrc);
cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] =
tbl[HD_OFDM_ENERGY_TH_IN_INDEX] =
cpu_to_le16(data->nrg_th_cca);

IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
Expand All @@ -459,6 +447,25 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n",
data->auto_corr_cck, data->auto_corr_cck_mrc,
data->nrg_th_cck);
}

/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
static int iwl_sensitivity_write(struct iwl_priv *priv)
{
struct iwl_sensitivity_cmd cmd;
struct iwl_sensitivity_data *data = NULL;
struct iwl_host_cmd cmd_out = {
.id = SENSITIVITY_CMD,
.len = sizeof(struct iwl_sensitivity_cmd),
.flags = CMD_ASYNC,
.data = &cmd,
};

data = &(priv->sensitivity_data);

memset(&cmd, 0, sizeof(cmd));

iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.table[0]);

/* Update uCode's "work" table, and copy it to DSP */
cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
Expand All @@ -477,6 +484,70 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
return iwl_send_cmd(priv, &cmd_out);
}

/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
{
struct iwl_enhance_sensitivity_cmd cmd;
struct iwl_sensitivity_data *data = NULL;
struct iwl_host_cmd cmd_out = {
.id = SENSITIVITY_CMD,
.len = sizeof(struct iwl_enhance_sensitivity_cmd),
.flags = CMD_ASYNC,
.data = &cmd,
};

data = &(priv->sensitivity_data);

memset(&cmd, 0, sizeof(cmd));

iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]);

cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
HD_INA_NON_SQUARE_DET_OFDM_DATA;
cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
HD_INA_NON_SQUARE_DET_CCK_DATA;
cmd.enhance_table[HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX] =
HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA;
cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA;
cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA;
cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX] =
HD_OFDM_NON_SQUARE_DET_SLOPE_DATA;
cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX] =
HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA;
cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA;
cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA;
cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_INDEX] =
HD_CCK_NON_SQUARE_DET_SLOPE_DATA;
cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX] =
HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA;

/* Update uCode's "work" table, and copy it to DSP */
cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;

/* Don't send command to uCode if nothing has changed */
if (!memcmp(&cmd.enhance_table[0], &(priv->sensitivity_tbl[0]),
sizeof(u16)*HD_TABLE_SIZE) &&
!memcmp(&cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX],
&(priv->enhance_sensitivity_tbl[0]),
sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES)) {
IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n");
return 0;
}

/* Copy table for comparison next time */
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.enhance_table[0]),
sizeof(u16)*HD_TABLE_SIZE);
memcpy(&(priv->enhance_sensitivity_tbl[0]),
&(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);

return iwl_send_cmd(priv, &cmd_out);
}

void iwl_init_sensitivity(struct iwl_priv *priv)
{
int ret = 0;
Expand Down Expand Up @@ -527,7 +598,10 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
data->last_bad_plcp_cnt_cck = 0;
data->last_fa_cnt_cck = 0;

ret |= iwl_sensitivity_write(priv);
if (priv->enhance_sensitivity_table)
ret |= iwl_enhance_sensitivity_write(priv);
else
ret |= iwl_sensitivity_write(priv);
IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
}

Expand Down Expand Up @@ -633,7 +707,10 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,

iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
iwl_sensitivity_write(priv);
if (priv->enhance_sensitivity_table)
iwl_enhance_sensitivity_write(priv);
else
iwl_sensitivity_write(priv);
}

static inline u8 find_first_chain(u8 mask)
Expand Down
82 changes: 81 additions & 1 deletion drivers/net/wireless/iwlwifi/iwl-agn-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ void iwl_check_abort_status(struct iwl_priv *priv,
u8 frame_count, u32 status)
{
if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
IWL_ERR(priv, "TODO: Implement Tx flush command!!!\n");
IWL_ERR(priv, "Tx flush command to flush out all frames\n");
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
queue_work(priv->workqueue, &priv->tx_flush);
}
}

Expand Down Expand Up @@ -1435,3 +1437,81 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
}
}

#define IWL_FLUSH_WAIT_MS 2000

int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv)
{
struct iwl_tx_queue *txq;
struct iwl_queue *q;
int cnt;
unsigned long now = jiffies;
int ret = 0;

/* waiting for all the tx frames complete might take a while */
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
if (cnt == IWL_CMD_QUEUE_NUM)
continue;
txq = &priv->txq[cnt];
q = &txq->q;
while (q->read_ptr != q->write_ptr && !time_after(jiffies,
now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS)))
msleep(1);

if (q->read_ptr != q->write_ptr) {
IWL_ERR(priv, "fail to flush all tx fifo queues\n");
ret = -ETIMEDOUT;
break;
}
}
return ret;
}

#define IWL_TX_QUEUE_MSK 0xfffff

/**
* iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode
*
* pre-requirements:
* 1. acquire mutex before calling
* 2. make sure rf is on and not in exit state
*/
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
{
struct iwl_txfifo_flush_cmd flush_cmd;
struct iwl_host_cmd cmd = {
.id = REPLY_TXFIFO_FLUSH,
.len = sizeof(struct iwl_txfifo_flush_cmd),
.flags = CMD_SYNC,
.data = &flush_cmd,
};

might_sleep();

memset(&flush_cmd, 0, sizeof(flush_cmd));
flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK |
IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK;
if (priv->cfg->sku & IWL_SKU_N)
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;

IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
flush_cmd.fifo_control);
flush_cmd.flush_control = cpu_to_le16(flush_control);

return iwl_send_cmd(priv, &cmd);
}

void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
{
mutex_lock(&priv->mutex);
ieee80211_stop_queues(priv->hw);
if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n");
iwlagn_wait_tx_queue_empty(priv);
done:
ieee80211_wake_queues(priv->hw);
mutex_unlock(&priv->mutex);
}
Loading

0 comments on commit a2c9fc9

Please sign in to comment.