Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2c9fc97 authored by John W. Linville's avatar John W. Linville
Browse files

Merge branch 'wireless-next-2.6' of...

parents ecc3d5ae c8312fac
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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 = {
+8 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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 = {
@@ -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 = {
+4 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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 = {
+105 −28
Original line number Diff line number Diff line
@@ -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",
@@ -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;
@@ -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;
@@ -527,6 +598,9 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
	data->last_bad_plcp_cnt_cck = 0;
	data->last_fa_cnt_cck = 0;

	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);
}
@@ -633,6 +707,9 @@ 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);
	if (priv->enhance_sensitivity_table)
		iwl_enhance_sensitivity_write(priv);
	else
		iwl_sensitivity_write(priv);
}

+81 −1
Original line number Diff line number Diff line
@@ -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);
	}
}

@@ -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