⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iwl-4965-rs.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		tbl->is_fat = 0;		tbl->is_SGI = 0;	}	rs_get_supported_rates(lq_data, NULL, tbl->lq_type, &rate_mask);	/* mask with station rate restriction */	if (is_legacy(tbl->lq_type)) {		if (lq_data->phymode == (u8) MODE_IEEE80211A)			rate_mask  = (u16)(rate_mask &			   (lq_data->supp_rates << IWL_FIRST_OFDM_RATE));		else			rate_mask = (u16)(rate_mask & lq_data->supp_rates);	}	/* if we did switched from HT to legacy check current rate */	if ((switch_to_legacy) &&	    (rate_mask & (1 << scale_index))) {		rs_mcs_from_tbl(mcs_rate, tbl, scale_index, is_green);		return 0;	}	high_low = rs_get_adjacent_rate(scale_index, rate_mask, tbl->lq_type);	low = high_low & 0xff;	if (low != IWL_RATE_INVALID)		rs_mcs_from_tbl(mcs_rate, tbl, low, is_green);	else		rs_mcs_from_tbl(mcs_rate, tbl, scale_index, is_green);	return 0;}static void rs_tx_status(void *priv_rate,			 struct net_device *dev,			 struct sk_buff *skb,			 struct ieee80211_tx_status *tx_resp){	int status;	u8 retries;	int rs_index, index = 0;	struct iwl_rate_scale_priv *lq;	struct iwl_link_quality_cmd *table;	struct sta_info *sta;	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;	struct iwl_priv *priv = (struct iwl_priv *)priv_rate;	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct iwl_rate_scale_data *window = NULL;	struct iwl_rate_scale_data *search_win = NULL;	struct iwl_rate tx_mcs;	struct iwl_scale_tbl_info tbl_type;	struct iwl_scale_tbl_info *curr_tbl, *search_tbl;	u8 active_index = 0;	u16 fc = le16_to_cpu(hdr->frame_control);	s32 tpt = 0;	IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n");	if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))		return;	retries = tx_resp->retry_count;	if (retries > 15)		retries = 15;	sta = sta_info_get(local, hdr->addr1);	if (!sta || !sta->rate_ctrl_priv) {		if (sta)			sta_info_put(sta);		return;	}	lq = (struct iwl_rate_scale_priv *)sta->rate_ctrl_priv;	if (!priv->lq_mngr.lq_ready)		return;	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && !lq->ibss_sta_added)		return;	table = &lq->lq;	active_index = lq->active_tbl;	lq->antenna = (lq->valid_antenna & local->hw.conf.antenna_sel_tx);	if (!lq->antenna)		lq->antenna = lq->valid_antenna;	lq->antenna = lq->valid_antenna;	curr_tbl = &(lq->lq_info[active_index]);	search_tbl = &(lq->lq_info[(1 - active_index)]);	window = (struct iwl_rate_scale_data *)	    &(curr_tbl->win[0]);	search_win = (struct iwl_rate_scale_data *)	    &(search_tbl->win[0]);	tx_mcs.rate_n_flags = tx_resp->control.tx_rate;	rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,				  &tbl_type, &rs_index);	if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) {		IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n",			     rs_index, tx_mcs.rate_n_flags);		sta_info_put(sta);		return;	}	if (retries &&	    (tx_mcs.rate_n_flags !=				le32_to_cpu(table->rs_table[0].rate_n_flags))) {		IWL_DEBUG_RATE("initial rate does not match 0x%x 0x%x\n",				tx_mcs.rate_n_flags,				le32_to_cpu(table->rs_table[0].rate_n_flags));		sta_info_put(sta);		return;	}	while (retries) {		tx_mcs.rate_n_flags =		    le32_to_cpu(table->rs_table[index].rate_n_flags);		rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,					  &tbl_type, &rs_index);		if ((tbl_type.lq_type == search_tbl->lq_type) &&		    (tbl_type.antenna_type == search_tbl->antenna_type) &&		    (tbl_type.is_SGI == search_tbl->is_SGI)) {			if (search_tbl->expected_tpt)				tpt = search_tbl->expected_tpt[rs_index];			else				tpt = 0;			rs_collect_tx_data(search_win,					    rs_index, tpt, 0);		} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&			   (tbl_type.antenna_type == curr_tbl->antenna_type) &&			   (tbl_type.is_SGI == curr_tbl->is_SGI)) {			if (curr_tbl->expected_tpt)				tpt = curr_tbl->expected_tpt[rs_index];			else				tpt = 0;			rs_collect_tx_data(window, rs_index, tpt, 0);		}		if (lq->stay_in_tbl)			lq->total_failed++;		--retries;		index++;	}	if (!tx_resp->retry_count)		tx_mcs.rate_n_flags = tx_resp->control.tx_rate;	else		tx_mcs.rate_n_flags =			le32_to_cpu(table->rs_table[index].rate_n_flags);	rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,				  &tbl_type, &rs_index);	if (tx_resp->flags & IEEE80211_TX_STATUS_ACK)		status = 1;	else		status = 0;	if ((tbl_type.lq_type == search_tbl->lq_type) &&	    (tbl_type.antenna_type == search_tbl->antenna_type) &&	    (tbl_type.is_SGI == search_tbl->is_SGI)) {		if (search_tbl->expected_tpt)			tpt = search_tbl->expected_tpt[rs_index];		else			tpt = 0;		rs_collect_tx_data(search_win,				    rs_index, tpt, status);	} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&		   (tbl_type.antenna_type == curr_tbl->antenna_type) &&		   (tbl_type.is_SGI == curr_tbl->is_SGI)) {		if (curr_tbl->expected_tpt)			tpt = curr_tbl->expected_tpt[rs_index];		else			tpt = 0;		rs_collect_tx_data(window, rs_index, tpt, status);	}	if (lq->stay_in_tbl) {		if (status)			lq->total_success++;		else			lq->total_failed++;	}	rs_rate_scale_perform(priv, dev, hdr, sta);	sta_info_put(sta);	return;}static u8 rs_is_ant_connected(u8 valid_antenna,			      enum iwl_antenna_type antenna_type){	if (antenna_type == ANT_AUX)		return ((valid_antenna & 0x2) ? 1:0);	else if (antenna_type == ANT_MAIN)		return ((valid_antenna & 0x1) ? 1:0);	else if (antenna_type == ANT_BOTH) {		if ((valid_antenna & 0x3) == 0x3)			return 1;		else			return 0;	}	return 1;}static u8 rs_is_other_ant_connected(u8 valid_antenna,				    enum iwl_antenna_type antenna_type){	if (antenna_type == ANT_AUX)		return (rs_is_ant_connected(valid_antenna, ANT_MAIN));	else		return (rs_is_ant_connected(valid_antenna, ANT_AUX));	return 0;}static void rs_set_stay_in_table(u8 is_legacy,				 struct iwl_rate_scale_priv *lq_data){	IWL_DEBUG_HT("we are staying in the same table\n");	lq_data->stay_in_tbl = 1;	if (is_legacy) {		lq_data->table_count_limit = IWL_LEGACY_TABLE_COUNT;		lq_data->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT;		lq_data->max_success_limit = IWL_LEGACY_TABLE_COUNT;	} else {		lq_data->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT;		lq_data->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT;		lq_data->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT;	}	lq_data->table_count = 0;	lq_data->total_failed = 0;	lq_data->total_success = 0;}static void rs_get_expected_tpt_table(struct iwl_rate_scale_priv *lq_data,				      struct iwl_scale_tbl_info *tbl){	if (is_legacy(tbl->lq_type)) {		if (!is_a_band(tbl->lq_type))			tbl->expected_tpt = expected_tpt_G;		else			tbl->expected_tpt = expected_tpt_A;	} else if (is_siso(tbl->lq_type)) {		if (tbl->is_fat && !lq_data->is_dup)			if (tbl->is_SGI)				tbl->expected_tpt = expected_tpt_siso40MHzSGI;			else				tbl->expected_tpt = expected_tpt_siso40MHz;		else if (tbl->is_SGI)			tbl->expected_tpt = expected_tpt_siso20MHzSGI;		else			tbl->expected_tpt = expected_tpt_siso20MHz;	} else if (is_mimo(tbl->lq_type)) {		if (tbl->is_fat && !lq_data->is_dup)			if (tbl->is_SGI)				tbl->expected_tpt = expected_tpt_mimo40MHzSGI;			else				tbl->expected_tpt = expected_tpt_mimo40MHz;		else if (tbl->is_SGI)			tbl->expected_tpt = expected_tpt_mimo20MHzSGI;		else			tbl->expected_tpt = expected_tpt_mimo20MHz;	} else		tbl->expected_tpt = expected_tpt_G;}#ifdef CONFIG_IWLWIFI_HTstatic s32 rs_get_best_rate(struct iwl_priv *priv,			    struct iwl_rate_scale_priv *lq_data,			    struct iwl_scale_tbl_info *tbl,			    u16 rate_mask, s8 index, s8 rate){	struct iwl_scale_tbl_info *active_tbl =	    &(lq_data->lq_info[lq_data->active_tbl]);	s32 new_rate, high, low, start_hi;	s32 active_sr = active_tbl->win[index].success_ratio;	s32 *tpt_tbl = tbl->expected_tpt;	s32 active_tpt = active_tbl->expected_tpt[index];	u16 high_low;	new_rate = high = low = start_hi = IWL_RATE_INVALID;	for (; ;) {		high_low = rs_get_adjacent_rate(rate, rate_mask, tbl->lq_type);		low = high_low & 0xff;		high = (high_low >> 8) & 0xff;		if ((((100 * tpt_tbl[rate]) > lq_data->last_tpt) &&		     ((active_sr > IWL_RATE_DECREASE_TH) &&		      (active_sr <= IWL_RATE_HIGH_TH) &&		      (tpt_tbl[rate] <= active_tpt))) ||		    ((active_sr >= IWL_RATE_SCALE_SWITCH) &&		     (tpt_tbl[rate] > active_tpt))) {			if (start_hi != IWL_RATE_INVALID) {				new_rate = start_hi;				break;			}			new_rate = rate;			if (low != IWL_RATE_INVALID)				rate = low;			else				break;		} else {			if (new_rate != IWL_RATE_INVALID)				break;			else if (high != IWL_RATE_INVALID) {				start_hi = high;				rate = high;			} else {				new_rate = rate;				break;			}		}	}	return new_rate;}#endif				/* CONFIG_IWLWIFI_HT */static inline u8 rs_is_both_ant_supp(u8 valid_antenna){	return (rs_is_ant_connected(valid_antenna, ANT_BOTH));}static int rs_switch_to_mimo(struct iwl_priv *priv,			     struct iwl_rate_scale_priv *lq_data,			     struct iwl_scale_tbl_info *tbl, int index){	int rc = -1;#ifdef CONFIG_IWLWIFI_HT	u16 rate_mask;	s32 rate;	s8 is_green = lq_data->is_green;	if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht)		return -1;	IWL_DEBUG_HT("LQ: try to switch to MIMO\n");	tbl->lq_type = LQ_MIMO;	rs_get_supported_rates(lq_data, NULL, tbl->lq_type,				&rate_mask);	if (priv->current_assoc_ht.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC)		return -1;	if (!rs_is_both_ant_supp(lq_data->antenna))		return -1;	rc = 0;	tbl->is_dup = lq_data->is_dup;	tbl->action = 0;	if (priv->current_channel_width == IWL_CHANNEL_WIDTH_40MHZ)		tbl->is_fat = 1;	else		tbl->is_fat = 0;	if (tbl->is_fat) {		if (priv->current_assoc_ht.sgf & HT_SHORT_GI_40MHZ_ONLY)			tbl->is_SGI = 1;		else			tbl->is_SGI = 0;	} else if (priv->current_assoc_ht.sgf & HT_SHORT_GI_20MHZ_ONLY)		tbl->is_SGI = 1;	else		tbl->is_SGI = 0;	rs_get_expected_tpt_table(lq_data, tbl);	rate = rs_get_best_rate(priv, lq_data, tbl, rate_mask, index, index);	IWL_DEBUG_HT("LQ: MIMO best rate %d mask %X\n", rate, rate_mask);	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask))		return -1;	rs_mcs_from_tbl(&tbl->current_rate, tbl, rate, is_green);	IWL_DEBUG_HT("LQ: Switch to new mcs %X index is green %X\n",		     tbl->current_rate.rate_n_flags, is_green);#endif				/*CONFIG_IWLWIFI_HT */	return rc;}static int rs_switch_to_siso(struct iwl_priv *priv,			     struct iwl_rate_scale_priv *lq_data,			     struct iwl_scale_tbl_info *tbl, int index){	int rc = -1;#ifdef CONFIG_IWLWIFI_HT	u16 rate_mask;	u8 is_green = lq_data->is_green;	s32 rate;	IWL_DEBUG_HT("LQ: try to switch to SISO\n");	if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht)		return -1;	rc = 0;	tbl->is_dup = lq_data->is_dup;	tbl->lq_type = LQ_SISO;	tbl->action = 0;	rs_get_supported_rates(lq_data, NULL, tbl->lq_type,				&rate_mask);	if (priv->current_channel_width == IWL_CHANNEL_WIDTH_40MHZ)		tbl->is_fat = 1;	else		tbl->is_fat = 0;	if (tbl->is_fat) {		if (priv->current_assoc_ht.sgf & HT_SHORT_GI_40MHZ_ONLY)			tbl->is_SGI = 1;		else			tbl->is_SGI = 0;	} else if (priv->current_assoc_ht.sgf & HT_SHORT_GI_20MHZ_ONLY)		tbl->is_SGI = 1;	else		tbl->is_SGI = 0;	if (is_green)		tbl->is_SGI = 0;	rs_get_expected_tpt_table(lq_data, tbl);	rate = rs_get_best_rate(priv, lq_data, tbl, rate_mask, index, index);	IWL_DEBUG_HT("LQ: get best rate %d mask %X\n", rate, rate_mask);	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {		IWL_DEBUG_HT("can not switch with index %d rate mask %x\n",			     rate, rate_mask);		return -1;	}	rs_mcs_from_tbl(&tbl->current_rate, tbl, rate, is_green);	IWL_DEBUG_HT("LQ: Switch to new mcs %X index is green %X\n",		     tbl->current_rate.rate_n_flags, is_green);#endif				/*CONFIG_IWLWIFI_HT */	return rc;}static int rs_move_legacy_other(struct iwl_priv *priv,				struct iwl_rate_scale_priv *lq_data,				int index){	int rc = 0;	struct iwl_scale_tbl_info *tbl =	    &(lq_data->lq_info[lq_data->active_tbl]);	struct iwl_scale_tbl_info *search_tbl =	    &(lq_data->lq_info[(1 - lq_data->active_tbl)]);	struct iwl_rate_scale_data *window = &(tbl->win[index]);	u32 sz = (sizeof(struct iwl_scale_tbl_info) -		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));	u8 start_action = tbl->action;	for (; ;) {		switch (tbl->action) {		case IWL_LEGACY_SWITCH_ANTENNA:			IWL_DEBUG_HT("LQ Legacy switch Antenna\n");			search_tbl->lq_type = LQ_NONE;			lq_data->action_counter++;			if (window->success_ratio >= IWL_RS_GOOD_RATIO)				break;			if (!rs_is_other_ant_connected(lq_data->antenna,							tbl->antenna_type))				break;			memcpy(search_tbl, tbl, sz);			rs_toggle_antenna(&(search_tbl->current_rate),					   search_tbl);			rs_get_expected_tpt_table(lq_data, search_tbl);			lq_data->search_better_tbl = 1;			goto out;		case IWL_LEGACY_SWITCH_SISO:			IWL_DEBUG_HT("LQ: Legacy switch to SISO\n");			memcpy(search_tbl, tbl, sz);			search_tbl->lq_type = LQ_SISO;			search_tbl->is_SGI = 0;			search_tbl->is_fat = 0;			rc = rs_switch_to_siso(priv, lq_data, search_tbl,					       index);			if (!rc) {				lq_data->search_better_tbl = 1;				lq_data->action_counter = 0;			}			if (!rc)				goto out;			break;		case IWL_LEGACY_SWITCH_MIMO:			IWL_DEBUG_HT("LQ: Legacy switch MIMO\n");			memcpy(search_tbl, tbl, sz);			search_tbl->lq_type = LQ_MIMO;			search_tbl->is_SGI = 0;			search_tbl->is_fat = 0;			search_tbl->antenna_type = ANT_BOTH;			rc = rs_switch_to_mimo(priv, lq_data, search_tbl,					       index);			if (!rc) {				lq_data->search_better_tbl = 1;				lq_data->action_counter = 0;			}			if (!rc)				goto out;			break;		}		tbl->action++;		if (tbl->action > IWL_LEGACY_SWITCH_MIMO)			tbl->action = IWL_LEGACY_SWITCH_ANTENNA;		if (tbl->action == start_action)			break;	}	return 0; out:	tbl->action++;	if (tbl->action > IWL_LEGACY_SWITCH_MIMO)		tbl->action = IWL_LEGACY_SWITCH_ANTENNA;	return 0;}static int rs_move_siso_to_other(struct iwl_priv *priv,				 struct iwl_rate_scale_priv *lq_data,				 int index){	int rc = -1;	u8 is_green = lq_data->is_green;	struct iwl_scale_tbl_info *tbl =	    &(lq_data->lq_info[lq_data->active_tbl]);	struct iwl_scale_tbl_info *search_tbl =	    &(lq_data->lq_info[(1 - lq_data->active_tbl)]);	struct iwl_rate_scale_data *window = &(tbl->win[index]);	u32 sz = (sizeof(struct iwl_scale_tbl_info) -		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));	u8 start_action = tbl->action;	for (;;) {		lq_data->action_counter++;		switch (tbl->action) {		case IWL_SISO_SWITCH_ANTENNA:			IWL_DEBUG_HT("LQ: SISO SWITCH ANTENNA SISO\n");			search_tbl->lq_type = LQ_NONE;			if (window->success_ratio >= IWL_RS_GOOD_RATIO)				break;			if (!rs_is_other_ant_connected(lq_data->antenna,						       tbl->antenna_type))				break;			memcpy(search_tbl, tbl, sz);			search_tbl->action = IWL_SISO_SWITCH_MIMO;			rs_toggle_antenna(&(search_tbl->current_rate),					   search_tbl);			lq_data->search_better_tbl = 1;			goto out;		case IWL_SISO_SWITCH_MIMO:			IWL_DEBUG_HT("LQ: SISO SWITCH TO MIMO FROM SISO\n");			memcpy(search_tbl, tbl, sz);			search_tbl->lq_type = LQ_MIMO;			search_tbl->is_SGI = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -